From 05cd6e4fd71866b6328ee669b7823def671c1a42 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 4 Apr 2024 02:46:44 -0300 Subject: [PATCH] 1.0 Alpha (#1599) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update model kwargs and temperature values * Update keyboard shortcuts for advanced editing * make Message field have no handles * Update OpenAI API Key handling in OpenAIEmbeddingsComponent * Remove unnecessary field_type key from CustomComponent class * Update required field behavior in CustomComponent class * Refactor AzureOpenAIModel.py: Removed unnecessary "required" attribute from input parameters * Update BaiduQianfanChatModel and OpenAIModel configurations * Fix range_spec step type validation * Update RangeSpec step_type default value to "float" * Fix Save debounce * Update parameterUtils to use debounce instead of throttle * Update input type options in schemas and graph base classes * Refactor run_flow_with_caching endpoint to include simplified and experimental versions * Add PythonFunctionComponent and test case for it * Add nest_asyncio to fix event loop issue * Refactor test_initial_setup.py to use RunOutputs instead of ResultData * Remove unused code in test_endpoints.py * Add asyncio loop to uvicorn command * Refactor load_session method to handle coroutine result * Fixed saving * Fixed debouncing * Add InputType and OutputType literals to schema.py * Update input type in Graph class * Add new schema for simplified API request * Add delete_messages function and update test_successful_run assertions * Add STREAM_INFO_TEXT constant to model components * Add session_id to simplified_run_flow_with_caching endpoint * Add field_typing import to OpenAIModel.py * update starter projects * Add constants for Langflow base module * Update setup.py to include latest component versions * Update Starter Examples * sets starter_project fixture to Basic Prompting * Refactor test_endpoints.py: Update test names and add new tests for different output types * Update HuggingFace Spaces link and add image for dark mode * Remove filepath reference * Update Vertex params in base.py * Add tests for different input types * Add type annotations and improve test coverage * Add duplicate space link to README * Update HuggingFace Spaces badge in README * Add Python 3.10 installation requirement to README * Refactor flow running endpoints * Refactor SimplifiedAPIRequest and add documentation for Tweaks * Refactor input_request parameter in simplified_run_flow function * Add support for retrieving specific component output * Add custom Uvicorn worker for Langflow application * Add asyncio loop to LangflowApplication initialization * Update Makefile with new variables and start command * Fix indentation in Makefile * Refactor run_graph function to add support for running a JSON flow * Refactor getChatInputField function and update API code * Update HuggingFace Spaces documentation with duplication process * Add asyncio event loop to uvicorn command * Add installation of backend in start target * udpate some starter projects * Fix formatting in hugging-face-spaces.mdx * Update installation instructions for Langflow * set examples order * Update start command in Makefile * Add installation and usage instructions for Langflow * Update Langflow installation and usage instructions * Fix langflow command in README.md * Fix broken link to HuggingFace Spaces guide * Add new SVG assets for blog post, chat bot, and cloud docs * Refactor example rendering in NewFlowModal * Add new SVG file for short bio section * Remove unused import and add new component * Update title in usage.mdx * Update HuggingFace Spaces heading in usage.mdx * Update usage instructions in getting-started/usage.mdx * Update cache option in usage documentation * Remove 'advanced' flag from 'n_messages' parameter in MemoryComponent.py * Refactor code to improve performance and readability * Update project names and flow examples * fix document qa example * Remove commented out code in sidebars.js * Delete unused documentation files * Fix bug in login functionality * Remove global variables from components * Fix bug in login functionality * fix modal returning to input * Update max-width of chat message sender name * Update styling for chat message component * Refactor OpenAIEmbeddingsComponent signature * Update usage.mdx file * Update path in Makefile * Add new migration and what's new documentation files * Add new chapters and migration guides * Update version to 0.0.13 in pyproject.toml * new locks * Update dependencies in pyproject.toml * general fixes * Update dependencies in pyproject.toml and poetry.lock files * add padding to modal * ✨ (undrawCards/index.tsx): update the SVG used for BasicPrompt component to undraw_short_bio_re_fmx0.svg to match the desired design ♻️ (undrawCards/index.tsx): adjust the width and height of the BasicPrompt SVG to 65% to improve the visual appearance * Commented out components/data in sidebars.js * Refactor component names in outputs.mdx * Update embedded chat script URL * Add data component and fix formatting in outputs component * Update dependencies in poetry.lock and pyproject.toml * Update dependencies in poetry.lock and pyproject.toml * Refactor code to improve performance and readability * Update dependencies in poetry.lock and pyproject.toml * Fixed IO Modal updates * Remove dead code at API Modal * Fixed overflow at CodeTabsComponent tweaks page * ✨ (NewFlowModal/index.tsx): update the name of the example from "Blog Writter" to "Blog Writer" for better consistency and clarity * Update dependencies versions * Update langflow-base to version 0.0.15 and fix setup_env script * Update dependencies in pyproject.toml * Lock dependencies in parallel * Add logging statement to setup_app function * Fix Ace not having type="module" and breaking build * Update authentication settings for access token cookie * Update package versions in package-lock.json * Add scripts directory to Dockerfile * Add setup_env command to build_and_run target * Remove unnecessary make command in setup_env * Remove unnecessary installation step in build_and_run * Add debug configuration for CLI * 🔧 chore(Makefile): refactor build_langflow target to use a separate script for updating dependencies and building ✨ feat(update_dependencies.py): add script to update pyproject.toml dependency version based on langflow-base version in src/backend/base/pyproject.toml * Add number_of_results parameter to AstraDBSearchComponent * Update HuggingFace Spaces links * Remove duplicate imports in hugging-face-spaces.mdx * Add number_of_results parameter to vector search components * Fixed supabase not commited * Revert "Fixed supabase not commited" This reverts commit afb10a6262ef453ec89c9c5fd6811e9f856e7a6b. * Update duplicate-space.png image * Delete unused files and components * Add/update script to update dependencies * Add .bak files to .gitignore * Update version numbers and remove unnecessary dependencies * Update langflow-base dependency path * Add Text import to VertexAiModel.py * Update langflow-base version to 0.0.16 and update dependencies * Delete start projects and commit session in delete_start_projects function * Refactor backend startup script to handle autologin option * Update poetry installation script to include pipx update check * Update pipx installation script for different operating systems * Update Makefile to improve setup process * Add error handling on streaming and fix streaming bug on error * Added description to Blog Writer * Sort base classes alphabetically * Update duplicate-space.png image * update position on langflow prompt chaining * Add Langflow CLI and first steps documentation * Add exception handling for missing 'content' field in search_with_vector_store method * Remove unused import and update type hinting * fix bug on egdes after creating group component * Refactor APIRequest class and update model imports * Remove unused imports and fix formatting issues * Refactor reactflowUtils and styleUtils * Add CLI documentation to getting-started/cli.mdx * Add CLI usage instructions * Add ZoomableImage component to first-steps.mdx * Update CLI and first steps documentation * Remove duplicate import and add new imports for ThemedImage and useBaseUrl * Update Langflow CLI documentation link * Remove first-steps.mdx and update index.mdx and sidebars.js * Update Docusaurus dependencies * Add AstraDB RAG Flow guide * Remove unused imports * Remove unnecessary import statement * Refactor guide for better readability * Add data component documentation * Update component headings and add prompt template * Fix logging level and version display * Add datetime import and buffer for alembic log * Update flow names in NewFlowModal and documentation * Add starter projects to sidebars.js * Fix error handling in DirectoryReader class * Handle exception when loading components in setup.py * Update version numbers in pyproject.toml files * Update build_langflow_base and build_langflow_backup in Makefile * Added docs * Update dependencies and build process * Add Admonition component for API Key documentation * Update API endpoint in async-api.mdx * Remove async-api guidelines * Fix UnicodeDecodeError in DirectoryReader * Update dependency version and fix encoding issues * Add conditional build and publish for base and main projects * Update version to 1.0.0a2 in pyproject.toml * Remove duplicate imports and unnecessary code in custom-component.mdx * Fix poetry lock command in Makefile * Update package versions in pyproject.toml * Remove unused components and update imports * 📦 chore(pre-release-base.yml): add pre-release workflow for base project 📦 chore(pre-release-langflow.yml): add pre-release workflow for langflow project * Add ChatLiteLLMModelComponent to models package * Add frontend installation and build steps * Add Dockerfile for building and pushing base image * Add emoji package and nest-asyncio dependency * 📝 (components.mdx): update margin style of ZoomableImage to improve spacing 📝 (features.mdx): update margin style of ZoomableImage to improve spacing 📝 (login.mdx): update margin style of ZoomableImage to improve spacing * Fix module import error in validate.py * Fix error message in directory_reader.py * Update version import and handle ImportError * Add cryptography and langchain-openai dependencies * Update poetry installation and remove poetry-monorepo-dependency-plugin * Update workflow and Dockerfile for Langflow base pre-release * Update display names and descriptions for AstraDB components * Update installation instructions for Langflow * Update Astra DB links and remove unnecessary imports * Rename AstraDB * Add new components and images * Update HuggingFace Spaces URLs * Update Langflow documentation and add new starter projects * Update flow name to "Basic Prompting (Hello, world!)" in relevant files * Update Basic Prompting flow name to "Ahoy World!" * Remove HuggingFace Spaces documentation * Add new files and update sidebars.js * Remove async-tasks.mdx and update sidebars.js * Update starter project URLs * Enable migration of global variables * Update OpenAIEmbeddings deployment and model * 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (inputs.mdx): add margin to image style to improve spacing and center alignment 📝 (rag-with-astradb.mdx): add margin to image styles to improve spacing and readability * Update welcome message in index.mdx * Add global variable feature to Langflow documentation * Reorganized sidebar categories * Update migration documentation * Refactor SplitTextComponent class to accept inputs of type Record and Text * Adjust embeddings docs * ✨ (cardComponent/index.tsx): add a minimum height to the card component to ensure consistent layout and prevent content from overlapping when the card is empty or has minimal content * Update flow name from "Ahoy World!" to "Hello, world!" * Update documentation for embeddings, models, and vector stores * Update CreateRecordComponent and parameterUtils.ts * Add documentation for Text and Record types * Remove commented lines in sidebars.js * Add run_flow_from_json function to load.py * Update Langflow package to run flow from JSON file * Fix type annotations and import errors * Refactor tests and fix test data --------- Co-authored-by: Rodrigo Nader Co-authored-by: anovazzi1 Co-authored-by: Lucas Oliveira Co-authored-by: carlosrcoelho Co-authored-by: cristhianzl Co-authored-by: Matheus --- .dockerignore | 2 +- .env.example | 7 + .github/workflows/lint.yml | 8 +- .../{pre-release.yml => pre-release-base.yml} | 13 +- .github/workflows/pre-release-langflow.yml | 70 + .../workflows/{test.yml => python_test.yml} | 10 +- .github/workflows/release.yml | 2 +- .github/workflows/typescript_test.yml | 149 + .gitignore | 5 + .vscode/launch.json | 26 +- Makefile | 162 +- README.md | 7 +- base.Dockerfile | 2 +- build_and_push.Dockerfile | 10 +- build_and_push_base.Dockerfile | 91 + deploy/base.Dockerfile | 2 +- docs/docs/components/custom.mdx | 15 +- docs/docs/components/data.mdx | 87 + docs/docs/components/embeddings.mdx | 130 +- docs/docs/components/experimental.mdx | 250 + docs/docs/components/helpers.mdx | 127 + docs/docs/components/inputs.mdx | 164 + docs/docs/components/memories.mdx | 24 +- .../components/{llms.mdx => model_specs.mdx} | 0 docs/docs/components/models.mdx | 346 + docs/docs/components/outputs.mdx | 37 + docs/docs/components/prompts.mdx | 2 +- docs/docs/components/utilities.mdx | 20 + docs/docs/components/vector-stores.mdx | 634 +- docs/docs/components/wrappers.mdx | 20 - docs/docs/examples/buffer-memory.mdx | 6 + docs/docs/examples/conversation-chain.mdx | 7 + docs/docs/examples/csv-loader.mdx | 6 + docs/docs/examples/flow-runner.mdx | 28 +- docs/docs/examples/how-upload-examples.mdx | 28 - .../docs/examples/midjourney-prompt-chain.mdx | 46 - docs/docs/examples/multiple-vectorstores.mdx | 58 - docs/docs/examples/python-function.mdx | 6 + docs/docs/examples/serp-api-tool.mdx | 6 + .../docs/getting-started/basic-prompting.mdx | 0 .../docs/getting-started/blog-writer.mdx | 0 docs/docs/getting-started/cli.mdx | 44 + docs/docs/getting-started/creating-flows.mdx | 38 - .../docs/getting-started/document-qa.mdx | 0 .../getting-started/hugging-face-spaces.mdx | 20 - docs/docs/getting-started/installation.md | 15 - .../docs/getting-started/memory-chatbot.mdx | 0 .../docs/getting-started/rag-with-astradb.mdx | 195 + docs/docs/guidelines/api.mdx | 12 +- docs/docs/guidelines/async-api.mdx | 73 - docs/docs/guidelines/components.mdx | 3 +- docs/docs/guidelines/custom-component.mdx | 22 +- docs/docs/guidelines/features.mdx | 25 +- docs/docs/guidelines/login.mdx | 7 +- docs/docs/guides/async-tasks.mdx | 44 - docs/docs/guides/superuser.mdx | 7 - docs/docs/index.mdx | 85 +- .../docs/migration/api.mdx | 0 docs/docs/migration/compatibility.mdx | 44 + .../component-status-and-data-passing.mdx | 0 .../connecting-output-components.mdx | 0 .../docs/migration/custom-component.mdx | 0 .../migration/experimental-components.mdx | 0 .../docs/migration/flow-of-data.mdx | 0 docs/docs/migration/global-variables.mdx | 65 + docs/docs/migration/inputs-and-outputs.mdx | 36 + .../docs/migration/multiple-flows.mdx | 0 .../new-categories-and-components.mdx | 0 .../migration/passing-tweaks-and-inputs.mdx | 0 .../renaming-and-editing-components.mdx | 0 .../sidebar-and-interaction-panel.mdx | 0 .../docs/migration/state-management.mdx | 0 .../docs/migration/supported-frameworks.mdx | 0 docs/docs/migration/text-and-record.mdx | 45 + .../docs/whats-new/a-new-chapter-langflow.mdx | 96 + docs/docs/whats-new/customization-control.mdx | 1 + docs/docs/whats-new/debugging-reimagined.mdx | 1 + .../whats-new/migrating-to-one-point-zero.mdx | 125 + .../simplification-standardization.mdx | 1 + docs/docusaurus.config.js | 5 + docs/package-lock.json | 940 ++- docs/package.json | 15 +- docs/sidebars.js | 103 +- docs/src/theme/DownloadableJsonFile.js | 29 + docs/static/data/AstraDB-RAG-Flows.json | 3403 +++++++++ docs/static/img/add-new-variable.png | Bin 0 -> 49435 bytes .../static/img/astra-configure-deployment.png | Bin 0 -> 207197 bytes docs/static/img/astra-create-database.png | Bin 0 -> 37699 bytes docs/static/img/astra-generate-token.png | Bin 0 -> 75966 bytes docs/static/img/astra-ingestion-fields.png | Bin 0 -> 225568 bytes docs/static/img/astra-ingestion-flow-dark.png | Bin 0 -> 87389 bytes docs/static/img/astra-ingestion-flow.png | Bin 0 -> 81772 bytes docs/static/img/astra-ingestion-run.png | Bin 0 -> 64198 bytes docs/static/img/astra-rag-flow-dark.png | Bin 0 -> 164630 bytes ...rag-flow-interaction-panel-interaction.png | Bin 0 -> 361975 bytes .../img/astra-rag-flow-interaction-panel.png | Bin 0 -> 168580 bytes docs/static/img/astra-rag-flow-run.png | Bin 0 -> 194688 bytes docs/static/img/astra-rag-flow.png | Bin 0 -> 152709 bytes docs/static/img/chat-input-expanded.png | Bin 0 -> 92523 bytes docs/static/img/chat-input.png | Bin 0 -> 54171 bytes docs/static/img/create-variable-window.png | Bin 0 -> 82320 bytes docs/static/img/drag-and-drop-canvas.png | Bin 0 -> 199514 bytes docs/static/img/drag-and-drop-flow.png | Bin 0 -> 187938 bytes docs/static/img/duplicate-space.png | Bin 0 -> 271831 bytes .../img/interaction-panel-text-input.png | Bin 0 -> 120285 bytes .../img/interaction-panel-with-chat-input.png | Bin 0 -> 127949 bytes docs/static/img/ollama-gv.png | Bin 0 -> 50068 bytes docs/static/img/prompt-with-template.png | Bin 0 -> 55738 bytes docs/static/img/prompt.png | Bin 0 -> 41403 bytes docs/static/img/text-input-expanded.png | Bin 0 -> 55994 bytes docs/static/img/text-input.png | Bin 0 -> 39820 bytes docs/static/json_files/SearchApi_Tool.json | 1748 ++++- lcserve.Dockerfile | 16 - poetry.lock | 2870 +++++--- pyproject.toml | 63 +- scripts/setup/setup_env.sh | 9 + scripts/setup/update_poetry.sh | 148 + scripts/update_dependencies.py | 51 + .../__init__.py => base/README.md} | 0 src/backend/{ => base}/langflow/__main__.py | 99 +- src/backend/{ => base}/langflow/alembic.ini | 0 .../{ => base}/langflow/alembic/README | 0 .../{ => base}/langflow/alembic/env.py | 25 +- .../langflow/alembic/script.py.mako | 2 + .../006b3990db50_add_unique_constraints.py | 8 +- .../alembic/versions/0b8757876a7c_.py | 0 ..._replace_credential_table_with_variable.py | 65 + .../alembic/versions/1ef9c4f3765d_.py | 8 +- .../versions/260dbcc8b680_adds_tables.py | 49 +- .../2ac71eb9c3ae_adds_credential_table.py | 4 +- ...fd30_add_icon_and_icon_bg_color_to_flow.py | 50 + .../67cc006d50bf_add_profile_image_column.py | 0 .../versions/7843803a87b5_store_updates.py | 12 +- ...2acc8b2_adds_updated_at_and_folder_cols.py | 15 +- .../b2fa308044b5_add_unique_constraints.py | 26 +- .../versions/bc2f01c40e4a_new_fixes.py | 16 +- ...866d51fd2_change_columns_to_be_nullable.py | 2 +- ...5ee9749d1a6_user_id_can_be_null_in_flow.py | 8 +- .../fd531f8868b1_fix_credential_table.py | 4 +- .../{ => base}/langflow/api/__init__.py | 0 src/backend/{ => base}/langflow/api/router.py | 8 +- src/backend/{ => base}/langflow/api/utils.py | 153 +- .../{ => base}/langflow/api/v1/__init__.py | 8 +- .../{ => base}/langflow/api/v1/api_key.py | 16 +- src/backend/base/langflow/api/v1/base.py | 165 + .../{ => base}/langflow/api/v1/callback.py | 56 +- src/backend/base/langflow/api/v1/chat.py | 329 + src/backend/base/langflow/api/v1/endpoints.py | 455 ++ src/backend/base/langflow/api/v1/files.py | 116 + .../{ => base}/langflow/api/v1/flows.py | 64 +- .../{ => base}/langflow/api/v1/login.py | 8 +- src/backend/base/langflow/api/v1/monitor.py | 73 + src/backend/base/langflow/api/v1/schemas.py | 325 + .../{ => base}/langflow/api/v1/store.py | 0 .../{ => base}/langflow/api/v1/users.py | 0 src/backend/base/langflow/api/v1/validate.py | 81 + src/backend/base/langflow/api/v1/variable.py | 113 + .../langflow/base}/__init__.py | 0 .../langflow/base/agents}/__init__.py | 0 .../base/langflow/base/agents/agent.py | 75 + src/backend/base/langflow/base/constants.py | 27 + .../langflow/base/data}/__init__.py | 0 src/backend/base/langflow/base/data/utils.py | 141 + .../langflow/base/io}/__init__.py | 0 src/backend/base/langflow/base/io/chat.py | 118 + src/backend/base/langflow/base/io/text.py | 42 + .../base/langflow/base/models/__init__.py | 3 + .../base/langflow/base/models/model.py | 50 + .../langflow/base/prompts}/__init__.py | 0 .../base/langflow/base/prompts/utils.py | 137 + .../base/langflow/components/__init__.py | 17 + .../components/agents/AgentInitializer.py | 3 +- .../langflow/components/agents/CSVAgent.py | 34 + .../langflow/components/agents/JsonAgent.py | 5 +- .../agents/OpenAIConversationalAgent.py | 6 +- .../langflow/components/agents/SQLAgent.py | 10 +- .../components/agents/VectorStoreAgent.py | 6 +- .../agents/VectorStoreRouterAgent.py | 10 +- .../langflow/components/agents/XMLAgent.py | 89 + .../langflow/components/agents/__init__.py | 19 + .../components/chains/ConversationChain.py | 46 + .../langflow/components/chains/LLMChain.py | 21 +- .../components/chains/LLMCheckerChain.py | 31 + .../components/chains/LLMMathChain.py | 26 +- .../langflow/components/chains/RetrievalQA.py | 68 + .../chains/RetrievalQAWithSourcesChain.py | 63 + .../components/chains/SQLGenerator.py | 61 + .../langflow/components/chains/__init__.py | 17 + .../langflow/components/data/APIRequest.py | 121 + .../langflow/components/data/Directory.py | 63 + .../base/langflow/components/data/File.py | 48 + .../base/langflow/components/data/URL.py | 27 + .../base/langflow/components/data/__init__.py | 7 + .../components/documentloaders}/__init__.py | 0 .../embeddings/AmazonBedrockEmbeddings.py | 12 +- .../embeddings/AzureOpenAIEmbeddings.py | 7 +- .../components/embeddings/CohereEmbeddings.py | 7 +- .../embeddings/HuggingFaceEmbeddings.py | 11 +- .../HuggingFaceInferenceAPIEmbeddings.py | 8 +- .../components/embeddings/OllamaEmbeddings.py | 10 +- .../components/embeddings/OpenAIEmbeddings.py | 49 +- .../embeddings/VertexAIEmbeddings.py | 54 +- .../components/embeddings/__init__.py | 19 + .../experimental/ClearMessageHistory.py | 26 + .../experimental/ExtractDataFromRecord.py | 45 + .../components/experimental/FlowTool.py | 86 + .../components/experimental/ListFlows.py | 21 + .../components/experimental/Listen.py | 21 + .../components/experimental/MergeRecords.py | 36 + .../components/experimental/Notify.py | 41 + .../components/experimental/PythonFunction.py | 25 + .../components/experimental/RunFlow.py | 66 + .../experimental/RunnableExecutor.py | 122 + .../components/experimental/SQLExecutor.py | 69 + .../components/experimental/SubFlow.py | 119 + .../components/experimental/__init__.py | 28 + .../components/helpers/CombineText.py | 29 + .../components/helpers/CreateRecord.py | 81 + .../components/helpers/CustomComponent.py | 16 + .../components/helpers/DocumentToRecord.py | 22 + .../components/helpers/IDGenerator.py | 31 + .../components/helpers/MemoryComponent.py | 66 + .../components/helpers/MessageHistory.py | 56 + .../components/helpers/RecordsToText.py | 35 + .../langflow/components/helpers/SplitText.py | 85 + .../components/helpers/UpdateRecord.py | 39 + .../langflow/components/helpers/__init__.py | 17 + .../langflow/components/inputs/ChatInput.py | 37 + .../base/langflow/components/inputs/Prompt.py | 33 + .../langflow/components/inputs/TextInput.py | 32 + .../langflow/components/inputs/__init__.py | 5 + .../BingSearchAPIWrapper.py | 4 +- .../GoogleSearchAPIWrapper.py | 3 +- .../GoogleSerperAPIWrapper.py | 12 +- .../JSONDocumentBuilder.py | 4 +- .../langchain_utilities/SQLDatabase.py | 22 + .../langchain_utilities}/SearchApi.py | 18 +- .../SearxSearchWrapper.py | 6 +- .../langchain_utilities}/SerpAPIWrapper.py | 3 +- .../WikipediaAPIWrapper.py | 3 +- .../WolframAlphaAPIWrapper.py | 3 +- .../langflow/components/memories}/__init__.py | 0 .../model_specs/AmazonBedrockSpecs.py} | 6 +- .../model_specs/AnthropicLLMSpecs.py} | 5 +- .../components/model_specs/AnthropicSpecs.py} | 3 +- .../model_specs/AzureChatOpenAISpecs.py} | 7 +- .../BaiduQianfanChatEndpointsSpecs.py} | 4 +- .../BaiduQianfanLLMEndpointsSpecs.py} | 4 +- .../model_specs/ChatAnthropicSpecs.py} | 5 +- .../model_specs/ChatLiteLLMSpecs.py} | 48 +- .../model_specs/ChatOllamaEndpointSpecs.py} | 3 +- .../model_specs/ChatOpenAISpecs.py} | 9 +- .../model_specs/ChatVertexAISpecs.py} | 4 +- .../components/model_specs/CohereSpecs.py} | 4 +- .../model_specs/GoogleGenerativeAISpecs.py | 74 + .../model_specs/HuggingFaceEndpointsSpecs.py} | 4 +- .../components/model_specs/OllamaLLMSpecs.py} | 2 +- .../components/model_specs/VertexAISpecs.py} | 7 +- .../components/model_specs/__init__.py | 35 + .../components/models/AmazonBedrockModel.py | 99 + .../components/models/AnthropicModel.py | 106 + .../components/models/AzureOpenAIModel.py | 121 + .../models/BaiduQianfanChatModel.py | 123 + .../components/models/ChatLiteLLMModel.py | 191 + .../langflow/components/models/CohereModel.py | 73 + .../models/GoogleGenerativeAIModel.py | 102 + .../components/models/HuggingFaceModel.py | 74 + .../langflow/components/models/OllamaModel.py | 300 + .../langflow/components/models/OpenAIModel.py | 106 + .../components/models/VertexAiModel.py | 126 + .../langflow/components/models/__init__.py | 26 + .../langflow/components/outputs/ChatOutput.py | 29 + .../langflow/components/outputs/TextOutput.py | 28 + .../langflow/components/outputs/__init__.py | 4 + .../components/retrievers/AmazonKendra.py | 7 +- .../components/retrievers/MetalRetriever.py | 6 +- .../retrievers/MultiQueryRetriever.py | 3 +- .../retrievers/VectaraSelfQueryRetriver.py | 14 +- .../retrievers/VectorStoreRetriever.py | 2 +- .../components/retrievers/__init__.py | 13 + .../textsplitters/CharacterTextSplitter.py | 25 +- .../LanguageRecursiveTextSplitter.py | 25 +- .../RecursiveCharacterTextSplitter.py | 32 +- .../components/textsplitters/__init__.py | 9 + .../components/toolkits/JsonToolkit.py | 5 +- .../langflow/components/toolkits/Metaphor.py | 2 +- .../components/toolkits/OpenAPIToolkit.py | 3 +- .../components/toolkits/VectorStoreInfo.py | 2 +- .../toolkits/VectorStoreRouterToolkit.py | 7 +- .../components/toolkits/VectorStoreToolkit.py | 14 +- .../langflow/components/toolkits/__init__.py | 15 + .../components/tools/RetrieverTool.py | 2 +- .../components/tools/SearchAPITool.py | 37 + .../langflow/components/tools/SearchApi.py | 53 + .../langflow/components/tools/__init__.py | 5 + .../components/vectorsearch/AstraDBSearch.py | 148 + .../components/vectorsearch/ChromaSearch.py | 111 + .../components/vectorsearch/FAISSSearch.py | 48 + .../vectorsearch/MongoDBAtlasVectorSearch.py | 57 + .../components/vectorsearch/PineconeSearch.py | 76 + .../components/vectorsearch/QdrantSearch.py | 98 + .../components/vectorsearch/RedisSearch.py | 82 + .../vectorsearch/SupabaseVectorStoreSearch.py | 54 + .../components/vectorsearch/VectaraSearch.py | 66 + .../components/vectorsearch/WeaviateSearch.py | 86 + .../components/vectorsearch/__init__.py | 25 + .../components/vectorsearch/pgvectorSearch.py | 74 + .../components/vectorstores/AstraDB.py | 158 + .../components/vectorstores/Chroma.py | 45 +- .../langflow/components/vectorstores/FAISS.py | 46 + .../vectorstores/MongoDBAtlasVector.py | 67 + .../components/vectorstores/Pinecone.py | 36 +- .../components/vectorstores/Qdrant.py | 27 +- .../langflow/components/vectorstores/Redis.py | 18 +- .../vectorstores/SupabaseVectorStore.py | 18 +- .../components/vectorstores/Vectara.py | 25 +- .../components/vectorstores/Weaviate.py | 33 +- .../components/vectorstores/__init__.py | 26 + .../components/vectorstores/base/__init__.py | 3 + .../components/vectorstores/base/model.py | 47 + .../components/vectorstores/pgvector.py | 15 +- src/backend/{ => base}/langflow/config.yaml | 70 +- .../langflow/core}/__init__.py | 0 .../{ => base}/langflow/core/celery_app.py | 0 .../{ => base}/langflow/core/celeryconfig.py | 0 .../__init__.py => base/langflow/custom.py} | 5 +- .../langflow/field_typing/__init__.py | 4 + .../langflow/field_typing/constants.py | 7 +- .../base/langflow/field_typing/range_spec.py | 30 + .../{ => base}/langflow/graph/__init__.py | 6 +- .../langflow/graph/edge}/__init__.py | 0 .../{ => base}/langflow/graph/edge/base.py | 91 +- .../base/langflow/graph/edge/schema.py | 34 + src/backend/base/langflow/graph/edge/utils.py | 19 + .../langflow/graph/graph}/__init__.py | 0 src/backend/base/langflow/graph/graph/base.py | 1220 ++++ .../langflow/graph/graph/constants.py | 14 +- .../graph/graph/runnable_vertices_manager.py | 111 + .../langflow/graph/graph/state_manager.py | 36 + .../{ => base}/langflow/graph/graph/utils.py | 46 +- src/backend/base/langflow/graph/schema.py | 55 + .../{ => base}/langflow/graph/utils.py | 21 + .../langflow/graph/vertex}/__init__.py | 0 .../base/langflow/graph/vertex/base.py | 749 ++ .../langflow/graph/vertex/constants.py | 0 .../base/langflow/graph/vertex/types.py | 491 ++ .../base/langflow/graph/vertex/utils.py | 65 + src/backend/base/langflow/helpers/__init__.py | 3 + src/backend/base/langflow/helpers/flow.py | 201 + src/backend/base/langflow/helpers/record.py | 41 + .../langflow/initial_setup}/__init__.py | 0 .../base/langflow/initial_setup/setup.py | 239 + .../Basic Prompting (Hello, world!).json | 888 +++ .../Langflow Blog Writter.json | 989 +++ .../Langflow Document QA.json | 1031 +++ .../Langflow Memory Conversation.json | 1274 ++++ .../Langflow Prompt Chaining.json | 1773 +++++ .../VectorStore-RAG-Flows.json | 3403 +++++++++ .../langflow/interface}/__init__.py | 0 .../langflow/interface/agents/__init__.py | 0 .../langflow/interface/agents/base.py | 5 +- .../langflow/interface/agents/custom.py | 6 +- .../langflow/interface/agents/prebuilt.py | 0 .../{ => base}/langflow/interface/base.py | 8 +- .../langflow/interface/chains/__init__.py | 0 .../langflow/interface/chains/base.py | 16 +- .../langflow/interface/chains/custom.py | 7 +- .../langflow/interface/custom/__init__.py | 0 .../langflow/interface/custom/attributes.py | 43 + .../langflow/interface/custom/base.py | 10 +- .../interface/custom/code_parser/__init__.py | 0 .../custom/code_parser/code_parser.py | 38 +- .../interface/custom/code_parser/utils.py | 11 +- .../custom/custom_component/__init__.py | 0 .../custom/custom_component/component.py | 57 +- .../custom_component/custom_component.py | 459 ++ .../custom/directory_reader/__init__.py | 0 .../directory_reader/directory_reader.py | 47 +- .../custom/directory_reader/utils.py | 19 +- .../base/langflow/interface/custom/eval.py | 12 + .../langflow/interface/custom/schema.py | 9 + .../langflow/interface/custom/utils.py | 214 +- .../langflow/interface/custom_lists.py | 2 +- .../interface/document_loaders}/__init__.py | 0 .../interface/document_loaders/base.py | 6 +- .../interface/embeddings}/__init__.py | 0 .../langflow/interface/embeddings/base.py | 4 +- .../langflow/interface/importing/__init__.py | 2 - .../langflow/interface/importing/utils.py | 26 +- .../interface/initialize}/__init__.py | 0 .../langflow/interface/initialize/llm.py | 0 .../langflow/interface/initialize/loading.py | 113 +- .../langflow/interface/initialize/utils.py | 0 .../interface/initialize/vector_store.py | 0 .../{ => base}/langflow/interface/listing.py | 2 +- .../langflow/interface/llms/__init__.py | 0 .../langflow/interface/llms/base.py | 6 +- .../langflow/interface/memories/__init__.py | 0 .../langflow/interface/memories/base.py | 6 +- .../interface/output_parsers}/__init__.py | 0 .../langflow/interface/output_parsers/base.py | 3 +- .../langflow/interface/prompts/__init__.py | 0 .../langflow/interface/prompts/base.py | 5 +- .../langflow/interface/prompts/custom.py | 0 .../interface/retrievers}/__init__.py | 0 .../langflow/interface/retrievers/base.py | 3 +- .../{ => base}/langflow/interface/run.py | 16 +- .../interface/text_splitters/__init__.py | 0 .../langflow/interface/text_splitters/base.py | 6 +- .../langflow/interface/toolkits}/__init__.py | 0 .../langflow/interface/toolkits/base.py | 20 +- .../langflow/interface/toolkits/custom.py | 0 .../langflow/interface/tools/__init__.py | 0 .../langflow/interface/tools/base.py | 18 +- .../langflow/interface/tools/constants.py | 4 +- .../langflow/interface/tools/custom.py | 4 +- .../langflow/interface/tools/util.py | 0 .../{ => base}/langflow/interface/types.py | 24 +- .../langflow/interface/utilities}/__init__.py | 0 .../langflow/interface/utilities/base.py | 2 +- .../{ => base}/langflow/interface/utils.py | 38 +- .../interface/vector_store}/__init__.py | 0 .../langflow/interface/vector_store/base.py | 0 .../langflow/interface/wrappers}/__init__.py | 0 .../langflow/interface/wrappers/base.py | 20 +- .../langflow/legacy_custom}/__init__.py | 0 .../langflow/legacy_custom}/customs.py | 3 +- src/backend/base/langflow/load.py | 1 + src/backend/{ => base}/langflow/main.py | 37 +- src/backend/base/langflow/memory.py | 100 + .../base/langflow/processing/__init__.py | 0 .../{ => base}/langflow/processing/base.py | 9 +- src/backend/base/langflow/processing/load.py | 67 + .../base/langflow/processing/process.py | 302 + src/backend/base/langflow/py.typed | 0 src/backend/base/langflow/schema/__init__.py | 4 + src/backend/base/langflow/schema/dotdict.py | 71 + src/backend/base/langflow/schema/schema.py | 150 + src/backend/{ => base}/langflow/server.py | 10 +- .../{ => base}/langflow/services/__init__.py | 0 .../base/langflow/services/auth/__init__.py | 0 .../langflow/services/auth/factory.py | 2 +- .../langflow/services/auth/service.py | 3 +- .../langflow/services/auth/utils.py | 16 +- src/backend/base/langflow/services/base.py | 29 + .../base/langflow/services/cache/__init__.py | 12 + .../base/langflow/services/cache/base.py | 168 + .../langflow/services/cache/factory.py | 10 +- .../langflow/services/cache/service.py | 117 +- .../langflow/services/cache/utils.py | 0 .../base/langflow/services/chat/__init__.py | 0 .../langflow/services/chat/cache.py | 3 +- .../langflow/services/chat/config.py | 0 .../langflow/services/chat/factory.py | 0 .../base/langflow/services/chat/service.py | 39 + .../langflow/services/chat/utils.py | 3 +- .../langflow/services/database/__init__.py | 0 .../langflow/services/database/factory.py | 2 + .../services/database/models/__init__.py | 6 + .../database/models/api_key/__init__.py | 0 .../services/database/models/api_key/crud.py | 0 .../services/database/models/api_key/model.py | 0 .../langflow/services/database/models/base.py | 0 .../services/database/models/flow/__init__.py | 0 .../services/database/models/flow/model.py | 127 + .../services/database/models/user/__init__.py | 0 .../services/database/models/user/crud.py | 5 +- .../services/database/models/user/model.py | 4 +- .../database/models/variable/__init__.py | 3 + .../database/models/variable/model.py | 49 + .../langflow/services/database/service.py | 19 +- .../langflow/services/database/utils.py | 0 src/backend/base/langflow/services/deps.py | 219 + src/backend/base/langflow/services/factory.py | 83 + .../{ => base}/langflow/services/manager.py | 59 +- .../langflow/services/monitor/__init__.py | 0 .../base/langflow/services/monitor/factory.py | 13 + .../base/langflow/services/monitor/schema.py | 142 + .../base/langflow/services/monitor/service.py | 167 + .../base/langflow/services/monitor/utils.py | 159 + .../langflow/services/plugins/__init__.py | 0 .../langflow/services/plugins/base.py | 0 .../langflow/services/plugins/factory.py | 0 .../services/plugins/langfuse_plugin.py | 3 +- .../langflow/services/plugins/service.py | 3 +- .../{ => base}/langflow/services/schema.py | 8 +- .../langflow/services/session/__init__.py | 0 .../langflow/services/session/factory.py | 7 +- .../langflow/services/session/service.py | 33 +- .../langflow/services/session/utils.py | 0 .../langflow/services/settings/__init__.py | 0 .../langflow/services/settings/auth.py | 34 +- .../langflow/services/settings/base.py | 6 +- .../langflow/services/settings/constants.py | 0 .../langflow/services/settings/factory.py | 3 +- .../langflow/services/settings/manager.py} | 8 +- .../langflow/services/settings/service.py | 44 + .../langflow/services/settings/utils.py | 0 .../base/langflow/services/socket/__init__.py | 0 .../base/langflow/services/socket/factory.py | 17 + .../base/langflow/services/socket/service.py | 86 + .../base/langflow/services/socket/utils.py | 103 + .../base/langflow/services/state/__init__.py | 0 .../base/langflow/services/state/factory.py | 13 + .../base/langflow/services/state/service.py | 74 + .../langflow/services/storage/__init__.py | 0 .../langflow/services/storage/constants.py | 28 + .../base/langflow/services/storage/factory.py | 29 + .../base/langflow/services/storage/local.py | 95 + .../base/langflow/services/storage/s3.py | 89 + .../base/langflow/services/storage/service.py | 42 + .../base/langflow/services/storage/utils.py | 5 + .../base/langflow/services/store/__init__.py | 0 .../langflow/services/store/exceptions.py | 0 .../langflow/services/store/factory.py | 3 +- .../langflow/services/store/schema.py | 0 .../langflow/services/store/service.py | 0 .../langflow/services/store/utils.py | 0 .../base/langflow/services/task/__init__.py | 0 .../services/task/backends/__init__.py | 0 .../langflow/services/task/backends/anyio.py | 0 .../langflow/services/task/backends/base.py | 2 + .../langflow/services/task/backends/celery.py | 3 + .../langflow/services/task/factory.py | 2 +- .../langflow/services/task/service.py | 38 +- .../langflow/services/task/utils.py | 0 .../{ => base}/langflow/services/utils.py | 90 +- .../langflow/services/variable/__init__.py | 0 .../langflow/services/variable}/factory.py | 8 +- .../langflow/services/variable/service.py | 66 + src/backend/{ => base}/langflow/settings.py | 0 .../base/langflow/template/__init__.py | 0 .../base/langflow/template/field/__init__.py | 0 .../langflow/template/field/base.py | 48 +- .../base/langflow/template/field/prompt.py | 14 + .../template/frontend_node/__init__.py | 8 +- .../langflow/template/frontend_node/agents.py | 2 + .../langflow/template/frontend_node/base.py | 32 +- .../langflow/template/frontend_node/chains.py | 36 +- .../template/frontend_node/constants.py | 10 - .../frontend_node/custom_components.py | 5 +- .../template/frontend_node/documentloaders.py | 0 .../template/frontend_node/embeddings.py | 0 .../frontend_node/formatter/__init__.py | 0 .../template/frontend_node/formatter/base.py | 3 +- .../formatter/field_formatters.py | 0 .../langflow/template/frontend_node/llms.py | 0 .../template/frontend_node/memories.py | 8 +- .../template/frontend_node/output_parsers.py | 2 + .../template/frontend_node/prompts.py | 0 .../template/frontend_node/retrievers.py | 0 .../template/frontend_node/textsplitters.py | 3 +- .../langflow/template/frontend_node/tools.py | 0 .../template/frontend_node/utilities.py | 2 +- .../template/frontend_node/vectorstores.py | 0 .../langflow/template/template/__init__.py | 0 .../langflow/template/template/base.py | 5 +- src/backend/base/langflow/utils/__init__.py | 0 .../{ => base}/langflow/utils/constants.py | 4 +- .../{ => base}/langflow/utils/lazy_load.py | 0 .../{ => base}/langflow/utils/logger.py | 4 +- .../{ => base}/langflow/utils/payload.py | 0 src/backend/base/langflow/utils/schemas.py | 55 + src/backend/{ => base}/langflow/utils/util.py | 40 +- .../{ => base}/langflow/utils/validate.py | 7 +- src/backend/base/langflow/worker.py | 37 + src/backend/base/poetry.lock | 6271 +++++++++++++++++ src/backend/base/pyproject.toml | 120 + src/backend/langflow/__init__.py | 16 - src/backend/langflow/api/v1/base.py | 160 - src/backend/langflow/api/v1/chat.py | 245 - src/backend/langflow/api/v1/credential.py | 86 - src/backend/langflow/api/v1/endpoints.py | 394 -- src/backend/langflow/api/v1/schemas.py | 214 - src/backend/langflow/api/v1/validate.py | 120 - .../langflow/components/agents/CSVAgent.py | 23 - .../components/chains/ConversationChain.py | 29 - .../components/chains/LLMCheckerChain.py | 22 - .../components/chains/PromptRunner.py | 28 - .../langflow/components/chains/RetrievalQA.py | 39 - .../chains/RetrievalQAWithSourcesChain.py | 42 - .../components/chains/SQLDatabaseChain.py | 25 - .../custom_components/CustomComponent.py | 12 - .../documentloaders/DirectoryLoader.py | 42 - .../components/documentloaders/FileLoader.py | 113 - .../components/documentloaders/UrlLoader.py | 47 - .../langflow/components/llms/CTransformers.py | 33 - .../components/llms/GoogleGenerativeAI.py | 72 - .../langflow/components/llms/LlamaCpp.py | 129 - .../components/utilities/GetRequest.py | 74 - .../components/utilities/PostRequest.py | 77 - .../components/utilities/UpdateRequest.py | 88 - .../langflow/components/vectorstores/FAISS.py | 26 - .../vectorstores/MongoDBAtlasVectorSearch.py | 48 - .../langflow/field_typing/range_spec.py | 21 - src/backend/langflow/graph/graph/base.py | 255 - src/backend/langflow/graph/vertex/base.py | 378 - src/backend/langflow/graph/vertex/types.py | 302 - src/backend/langflow/graph/vertex/utils.py | 5 - .../custom_component/custom_component.py | 238 - src/backend/langflow/processing/load.py | 52 - src/backend/langflow/processing/process.py | 299 - src/backend/langflow/services/base.py | 12 - .../langflow/services/cache/__init__.py | 9 - src/backend/langflow/services/cache/base.py | 98 - src/backend/langflow/services/chat/service.py | 260 - .../langflow/services/credentials/service.py | 37 - .../services/database/models/__init__.py | 6 - .../database/models/component/__init__.py | 3 - .../database/models/component/model.py | 29 - .../database/models/credential/__init__.py | 3 - .../database/models/credential/model.py | 43 - .../database/models/credential/schema.py | 8 - .../services/database/models/flow/model.py | 73 - src/backend/langflow/services/deps.py | 63 - src/backend/langflow/services/factory.py | 12 - src/backend/langflow/utils/types.py | 2 - src/backend/langflow/version/__init__.py | 1 + src/backend/langflow/version/version.py | 7 + src/backend/langflow/worker.py | 75 - src/frontend/.eslintrc.json | 29 + src/frontend/.github/workflows/playwright.yml | 27 - src/frontend/.gitignore | 4 + src/frontend/harFiles/backend_12112023.har | 599 -- src/frontend/harFiles/langflow.har | 944 ++- src/frontend/index.html | 21 +- src/frontend/package-lock.json | 4942 ++++++++----- src/frontend/package.json | 28 +- src/frontend/playwright-report/index.html | 18 - src/frontend/playwright.config.ts | 67 +- src/frontend/run-tests.sh | 112 +- src/frontend/src/App.css | 9 + src/frontend/src/App.tsx | 246 +- .../components/parameterComponent/index.tsx | 350 +- .../src/CustomNodes/GenericNode/index.tsx | 505 +- .../src/alerts/alertDropDown/index.tsx | 10 +- .../src/assets/Gooey Ring-5s-271px.svg | 40 - src/frontend/src/assets/froze-flow.png | Bin 11568 -> 0 bytes .../src/assets/undraw_blog_post_re_fy5x.svg | 1 + .../src/assets/undraw_chat_bot_re_e2gj.svg | 1 + .../src/assets/undraw_cloud_docs_re_xjht.svg | 1 + .../assets/undraw_design_components_9vy6.svg | 1 + .../assets/undraw_mobile_messages_re_yx8w.svg | 1 + .../undraw_real_time_analytics_re_yliv.svg | 1 + .../src/assets/undraw_short_bio_re_fmx0.svg | 1 + .../undraw_team_collaboration_re_ow29.svg | 1 + .../assets/undraw_transfer_files_re_a2a9.svg | 1 + .../components/AccordionComponent/index.tsx | 9 +- .../components/CrashErrorComponent/index.tsx | 4 +- .../DropdownButtonComponent/index.tsx | 39 +- .../EditFlowSettingsComponent/index.tsx | 2 +- .../LightTooltipComponent/index.tsx | 17 - .../src/components/LoadingSpinner/index.tsx | 3 - .../src/components/RadialProgress/index.tsx | 18 - .../ReactTooltipComponent/index.tsx | 45 - .../components/ShadTooltipComponent/index.tsx | 3 +- .../src/components/TooltipComponent/index.tsx | 14 - .../components/ViewTriggers/chat/index.tsx | 31 + .../addNewVariableButton.tsx | 99 + .../src/components/cardComponent/index.tsx | 8 +- .../chatComponent/buildTrigger/index.tsx | 189 - .../chatComponent/chatTrigger/index.tsx | 71 - .../src/components/chatComponent/index.tsx | 172 +- .../components/codeAreaComponent/index.tsx | 4 + .../components/codeTabsComponent/index.tsx | 114 +- .../components/dropdownComponent/index.tsx | 211 +- .../src/components/exampleComponent/index.tsx | 100 + .../components/fetchErrorComponent/index.tsx | 47 +- .../components/genericIconComponent/index.tsx | 77 +- .../components/menuBar/index.tsx | 126 +- .../src/components/headerComponent/index.tsx | 13 +- .../src/components/inputComponent/index.tsx | 247 +- .../components/inputFileComponent/index.tsx | 12 +- .../components/inputGlobalComponent/index.tsx | 134 + .../src/components/intComponent/index.tsx | 9 +- .../components/keypairListComponent/index.tsx | 11 +- .../src/components/promptComponent/index.tsx | 1 + .../components/stackedComponents/index.tsx | 30 - .../components/textAreaComponent/index.tsx | 73 +- .../components/textInputComponent/index.tsx | 15 + .../components/textOutputComponent/index.tsx | 15 + .../src/components/toggleComponent/index.tsx | 59 - .../components/toggleShadComponent/index.tsx | 2 + src/frontend/src/components/ui/accordion.tsx | 2 +- src/frontend/src/components/ui/button.tsx | 21 +- src/frontend/src/components/ui/checkmark.tsx | 31 + src/frontend/src/components/ui/command.tsx | 2 +- .../components/ui/dialog-with-no-close.tsx | 119 + src/frontend/src/components/ui/dialog.tsx | 2 +- src/frontend/src/components/ui/popover.tsx | 19 +- .../src/components/ui/refreshButton.tsx | 58 + .../src/components/ui/rename-label.tsx | 3 + .../src/components/ui/select-custom.tsx | 2 +- src/frontend/src/components/ui/xmark.tsx | 45 + .../src/constants/alerts_constants.tsx | 60 + src/frontend/src/constants/constants.ts | 81 +- src/frontend/src/constants/enums.ts | 13 + src/frontend/src/contexts/authContext.tsx | 3 +- src/frontend/src/controllers/API/api.tsx | 100 +- src/frontend/src/controllers/API/index.ts | 111 +- src/frontend/src/icons/AstraDB/AstraDB.jsx | 28 + src/frontend/src/icons/AstraDB/Favicon.svg | 12 + src/frontend/src/icons/AstraDB/index.tsx | 9 + src/frontend/src/icons/Azure/Azure.jsx | 61 + src/frontend/src/icons/Azure/index.tsx | 8 + .../BotMessageSquare/BotMessageSquare.jsx | 23 + .../src/icons/BotMessageSquare/index.tsx | 9 + .../GoogleGenerativeAI/Google Gemini icon.svg | 1 + .../icons/GoogleGenerativeAI/GoogleGemini.jsx | 28 + .../src/icons/GoogleGenerativeAI/index.tsx | 9 + src/frontend/src/icons/Ollama/Ollama.jsx | 64 + src/frontend/src/icons/Ollama/Ollama.svg | 1 + src/frontend/src/icons/Ollama/index.tsx | 9 + src/frontend/src/icons/Postgres/Postgres.jsx | 67 + src/frontend/src/icons/Postgres/Postgres.svg | 1 + src/frontend/src/icons/Postgres/index.tsx | 9 + src/frontend/src/icons/Python/Python.jsx | 158 + src/frontend/src/icons/Python/Python.svg | 41 + src/frontend/src/icons/Python/index.tsx | 9 + .../src/icons/QianFanChat/QianFanChat.jsx | 23 + .../src/icons/QianFanChat/QianFanChat.svg | 1 + src/frontend/src/icons/QianFanChat/index.tsx | 9 + src/frontend/src/icons/Redis/Redis.jsx | 67 + src/frontend/src/icons/Redis/Redis.svg | 1 + src/frontend/src/icons/Redis/index.tsx | 8 + src/frontend/src/index.tsx | 9 +- src/frontend/src/modals/ApiModal/index.tsx | 27 +- .../src/modals/ConfirmationModal/index.tsx | 3 +- .../modals/DeleteConfirmationModal/index.tsx | 28 +- .../src/modals/EditNodeModal/index.tsx | 72 +- .../components/FileInput/index.tsx | 151 + .../IOModal/components/IOFieldView/index.tsx | 117 + .../components/chatView/chatInput/index.tsx | 140 + .../chatView}/chatMessage/codeBlock/index.tsx | 6 +- .../components/chatView/chatMessage/index.tsx | 324 + .../chatView}/fileComponent/index.tsx | 4 +- .../IOModal/components/chatView/index.tsx | 216 + src/frontend/src/modals/IOModal/index.tsx | 405 ++ .../components/NewFlowCardComponent/index.tsx | 31 + .../components/undrawCards/index.tsx | 129 + .../src/modals/NewFlowModal/index.tsx | 77 + .../src/modals/SecretKeyModal/index.tsx | 3 +- .../src/modals/StoreApiKeyModal/index.tsx | 22 +- src/frontend/src/modals/baseModal/index.tsx | 72 +- .../src/modals/codeAreaModal/index.tsx | 174 +- src/frontend/src/modals/exportModal/index.tsx | 15 +- .../src/modals/formModal/chatInput/index.tsx | 111 - .../modals/formModal/chatMessage/index.tsx | 221 - src/frontend/src/modals/formModal/index.tsx | 635 -- .../src/modals/genericModal/index.tsx | 41 +- src/frontend/src/modals/shareModal/index.tsx | 16 +- .../src/pages/AdminPage/LoginPage/index.tsx | 3 +- src/frontend/src/pages/AdminPage/index.tsx | 28 +- src/frontend/src/pages/ApiKeysPage/index.tsx | 8 +- .../components/DisclosureComponent/index.tsx | 11 +- .../components/PageComponent/index.tsx | 302 +- .../ParentDisclosureComponent/index.tsx | 41 + .../extraSidebarComponent/index.tsx | 352 +- .../sideBarDraggableComponent/index.tsx | 1 + .../extraSidebarComponent/utils.tsx | 26 + .../components/nodeToolbarComponent/index.tsx | 573 +- .../toolbarSelectItem/index.tsx | 51 + src/frontend/src/pages/FlowPage/index.tsx | 18 +- .../MainPage/components/components/index.tsx | 18 +- src/frontend/src/pages/MainPage/index.tsx | 24 +- .../src/pages/ProfileSettingsPage/index.tsx | 14 +- src/frontend/src/pages/StorePage/index.tsx | 27 +- .../src/pages/deleteAccountPage/index.tsx | 1 - src/frontend/src/pages/loginPage/index.tsx | 3 +- src/frontend/src/pages/signUpPage/index.tsx | 3 +- src/frontend/src/stores/alertStore.ts | 138 +- src/frontend/src/stores/darkStore.tsx | 27 +- src/frontend/src/stores/flowStore.ts | 390 +- src/frontend/src/stores/flowsManagerStore.ts | 49 +- src/frontend/src/stores/globalVariables.ts | 34 + src/frontend/src/stores/shortcuts.ts | 15 + src/frontend/src/stores/typesStore.ts | 4 - src/frontend/src/style/applies.css | 90 +- src/frontend/src/style/index.css | 8 + src/frontend/src/types/api/index.ts | 51 + src/frontend/src/types/chat/index.ts | 24 +- src/frontend/src/types/components/index.ts | 130 +- src/frontend/src/types/flow/index.ts | 15 +- src/frontend/src/types/store/index.ts | 5 + src/frontend/src/types/zustand/alert/index.ts | 9 +- src/frontend/src/types/zustand/flow/index.ts | 84 +- .../src/types/zustand/flowIOStore/index.ts | 21 + .../src/types/zustand/flowsManager/index.ts | 9 +- .../types/zustand/globalVariables/index.ts | 10 + src/frontend/src/utils/buildUtils.ts | 257 + src/frontend/src/utils/parameterUtils.ts | 45 + src/frontend/src/utils/reactflowUtils.ts | 151 +- src/frontend/src/utils/storeUtils.ts | 27 +- src/frontend/src/utils/styleUtils.ts | 156 +- src/frontend/src/utils/utils.ts | 183 +- src/frontend/tailwind.config.js | 14 +- src/frontend/tests/custom_component_full.ts | 2 +- .../tests/end-to-end/assets/ChatTest.json | 358 + .../assets/collection.json | 295 +- .../assets/flow.json | 0 .../end-to-end/assets/flow_group_test.json | 532 ++ .../assets/flowtest.json | 39 +- .../auto_login.spec.ts | 30 +- src/frontend/tests/end-to-end/chat_io.spec.ts | 46 + .../end-to-end/codeAreaModalComponent.spec.ts | 142 +- .../end-to-end/curl_api_generation.spec.ts | 17 + .../dragAndDrop.spec.ts | 23 +- .../end-to-end/dropdownComponent.spec.ts | 260 + .../floatComponent.spec.ts | 44 +- .../flowPage.spec.ts | 23 +- src/frontend/tests/end-to-end/group.spec.ts | 29 + .../inputComponent.spec.ts | 74 +- .../tests/end-to-end/intComponent.spec.ts | 203 + .../keyPairListComponent.spec.ts | 83 +- .../end-to-end/langflowShortcuts.spec.ts | 90 + .../nestedComponent.spec.ts | 195 +- .../end-to-end/promptModalComponent.spec.ts | 41 +- .../end-to-end/python_api_generation.spec.ts | 17 + .../saveComponents.spec.ts | 52 +- .../toggleComponent.spec.ts | 78 +- .../tests/end-to-end/tweaks_test.spec.ts | 38 + src/frontend/tests/globalTeardown.ts | 25 + .../tests/onlyFront/dropdownComponent.spec.ts | 107 - src/frontend/tests/onlyFront/group.spec.ts | 84 - .../tests/onlyFront/intComponent.spec.ts | 124 - src/frontend/tests/onlyFront/login.spec.ts | 121 - tests/conftest.py | 131 +- tests/data/ChatInputTest.json | 918 +++ tests/data/TwoOutputsTest.json | 1024 +++ tests/data/component.py | 2 +- tests/data/component_with_templatefield.py | 2 +- tests/test_api_key.py | 2 +- tests/test_cache.py | 3 +- tests/test_cli.py | 4 +- tests/test_custom_component.py | 88 +- tests/test_custom_types.py | 4 +- tests/test_data_components.py | 166 + tests/test_database.py | 43 +- tests/test_embeddings_template.py | 59 - tests/test_endpoints.py | 760 +- tests/test_files.py | 104 + tests/test_graph.py | 183 +- tests/test_helper_components.py | 80 + tests/test_initial_setup.py | 92 + tests/test_loading.py | 26 +- tests/test_login.py | 6 +- tests/test_process.py | 73 +- tests/test_prompts_template.py | 11 - tests/test_record.py | 139 + tests/test_setup_superuser.py | 9 +- tests/test_user.py | 25 +- tests/test_websocket.py | 50 - tests/text_experimental_components.py | 15 + 853 files changed, 59936 insertions(+), 15456 deletions(-) rename .github/workflows/{pre-release.yml => pre-release-base.yml} (86%) create mode 100644 .github/workflows/pre-release-langflow.yml rename .github/workflows/{test.yml => python_test.yml} (76%) create mode 100644 .github/workflows/typescript_test.yml create mode 100644 build_and_push_base.Dockerfile create mode 100644 docs/docs/components/data.mdx create mode 100644 docs/docs/components/experimental.mdx create mode 100644 docs/docs/components/helpers.mdx create mode 100644 docs/docs/components/inputs.mdx rename docs/docs/components/{llms.mdx => model_specs.mdx} (100%) create mode 100644 docs/docs/components/models.mdx create mode 100644 docs/docs/components/outputs.mdx delete mode 100644 docs/docs/components/wrappers.mdx delete mode 100644 docs/docs/examples/how-upload-examples.mdx delete mode 100644 docs/docs/examples/midjourney-prompt-chain.mdx delete mode 100644 docs/docs/examples/multiple-vectorstores.mdx rename src/backend/langflow/components/agents/__init__.py => docs/docs/getting-started/basic-prompting.mdx (100%) rename src/backend/langflow/components/chains/__init__.py => docs/docs/getting-started/blog-writer.mdx (100%) create mode 100644 docs/docs/getting-started/cli.mdx delete mode 100644 docs/docs/getting-started/creating-flows.mdx rename src/backend/langflow/components/custom_components/__init__.py => docs/docs/getting-started/document-qa.mdx (100%) delete mode 100644 docs/docs/getting-started/hugging-face-spaces.mdx delete mode 100644 docs/docs/getting-started/installation.md rename src/backend/langflow/components/documentloaders/__init__.py => docs/docs/getting-started/memory-chatbot.mdx (100%) create mode 100644 docs/docs/getting-started/rag-with-astradb.mdx delete mode 100644 docs/docs/guidelines/async-api.mdx delete mode 100644 docs/docs/guides/async-tasks.mdx delete mode 100644 docs/docs/guides/superuser.mdx rename src/backend/langflow/components/embeddings/__init__.py => docs/docs/migration/api.mdx (100%) create mode 100644 docs/docs/migration/compatibility.mdx rename src/backend/langflow/components/llms/__init__.py => docs/docs/migration/component-status-and-data-passing.mdx (100%) rename src/backend/langflow/components/retrievers/__init__.py => docs/docs/migration/connecting-output-components.mdx (100%) rename src/backend/langflow/components/textsplitters/__init__.py => docs/docs/migration/custom-component.mdx (100%) rename src/backend/langflow/components/toolkits/__init__.py => docs/docs/migration/experimental-components.mdx (100%) rename src/backend/langflow/components/tools/__init__.py => docs/docs/migration/flow-of-data.mdx (100%) create mode 100644 docs/docs/migration/global-variables.mdx create mode 100644 docs/docs/migration/inputs-and-outputs.mdx rename src/backend/langflow/components/vectorstores/__init__.py => docs/docs/migration/multiple-flows.mdx (100%) rename src/backend/langflow/core/__init__.py => docs/docs/migration/new-categories-and-components.mdx (100%) rename src/backend/langflow/custom/__init__.py => docs/docs/migration/passing-tweaks-and-inputs.mdx (100%) rename src/backend/langflow/graph/edge/__init__.py => docs/docs/migration/renaming-and-editing-components.mdx (100%) rename src/backend/langflow/graph/graph/__init__.py => docs/docs/migration/sidebar-and-interaction-panel.mdx (100%) rename src/backend/langflow/graph/vertex/__init__.py => docs/docs/migration/state-management.mdx (100%) rename src/backend/langflow/interface/__init__.py => docs/docs/migration/supported-frameworks.mdx (100%) create mode 100644 docs/docs/migration/text-and-record.mdx create mode 100644 docs/docs/whats-new/a-new-chapter-langflow.mdx create mode 100644 docs/docs/whats-new/customization-control.mdx create mode 100644 docs/docs/whats-new/debugging-reimagined.mdx create mode 100644 docs/docs/whats-new/migrating-to-one-point-zero.mdx create mode 100644 docs/docs/whats-new/simplification-standardization.mdx create mode 100644 docs/src/theme/DownloadableJsonFile.js create mode 100644 docs/static/data/AstraDB-RAG-Flows.json create mode 100644 docs/static/img/add-new-variable.png create mode 100644 docs/static/img/astra-configure-deployment.png create mode 100644 docs/static/img/astra-create-database.png create mode 100644 docs/static/img/astra-generate-token.png create mode 100644 docs/static/img/astra-ingestion-fields.png create mode 100644 docs/static/img/astra-ingestion-flow-dark.png create mode 100644 docs/static/img/astra-ingestion-flow.png create mode 100644 docs/static/img/astra-ingestion-run.png create mode 100644 docs/static/img/astra-rag-flow-dark.png create mode 100644 docs/static/img/astra-rag-flow-interaction-panel-interaction.png create mode 100644 docs/static/img/astra-rag-flow-interaction-panel.png create mode 100644 docs/static/img/astra-rag-flow-run.png create mode 100644 docs/static/img/astra-rag-flow.png create mode 100644 docs/static/img/chat-input-expanded.png create mode 100644 docs/static/img/chat-input.png create mode 100644 docs/static/img/create-variable-window.png create mode 100644 docs/static/img/drag-and-drop-canvas.png create mode 100644 docs/static/img/drag-and-drop-flow.png create mode 100644 docs/static/img/duplicate-space.png create mode 100644 docs/static/img/interaction-panel-text-input.png create mode 100644 docs/static/img/interaction-panel-with-chat-input.png create mode 100644 docs/static/img/ollama-gv.png create mode 100644 docs/static/img/prompt-with-template.png create mode 100644 docs/static/img/prompt.png create mode 100644 docs/static/img/text-input-expanded.png create mode 100644 docs/static/img/text-input.png delete mode 100644 lcserve.Dockerfile create mode 100644 scripts/setup/setup_env.sh create mode 100644 scripts/setup/update_poetry.sh create mode 100644 scripts/update_dependencies.py rename src/backend/{langflow/interface/document_loaders/__init__.py => base/README.md} (100%) rename src/backend/{ => base}/langflow/__main__.py (85%) rename src/backend/{ => base}/langflow/alembic.ini (100%) rename src/backend/{ => base}/langflow/alembic/README (100%) rename src/backend/{ => base}/langflow/alembic/env.py (72%) rename src/backend/{ => base}/langflow/alembic/script.py.mako (90%) rename src/backend/{ => base}/langflow/alembic/versions/006b3990db50_add_unique_constraints.py (93%) rename src/backend/{ => base}/langflow/alembic/versions/0b8757876a7c_.py (100%) create mode 100644 src/backend/base/langflow/alembic/versions/1a110b568907_replace_credential_table_with_variable.py rename src/backend/{ => base}/langflow/alembic/versions/1ef9c4f3765d_.py (83%) rename src/backend/{ => base}/langflow/alembic/versions/260dbcc8b680_adds_tables.py (81%) rename src/backend/{ => base}/langflow/alembic/versions/2ac71eb9c3ae_adds_credential_table.py (92%) create mode 100644 src/backend/base/langflow/alembic/versions/63b9c451fd30_add_icon_and_icon_bg_color_to_flow.py rename src/backend/{ => base}/langflow/alembic/versions/67cc006d50bf_add_profile_image_column.py (100%) rename src/backend/{ => base}/langflow/alembic/versions/7843803a87b5_store_updates.py (82%) rename src/backend/{ => base}/langflow/alembic/versions/7d2162acc8b2_adds_updated_at_and_folder_cols.py (80%) rename src/backend/{ => base}/langflow/alembic/versions/b2fa308044b5_add_unique_constraints.py (81%) rename src/backend/{ => base}/langflow/alembic/versions/bc2f01c40e4a_new_fixes.py (82%) rename src/backend/{ => base}/langflow/alembic/versions/eb5866d51fd2_change_columns_to_be_nullable.py (94%) rename src/backend/{ => base}/langflow/alembic/versions/f5ee9749d1a6_user_id_can_be_null_in_flow.py (79%) rename src/backend/{ => base}/langflow/alembic/versions/fd531f8868b1_fix_credential_table.py (93%) rename src/backend/{ => base}/langflow/api/__init__.py (100%) rename src/backend/{ => base}/langflow/api/router.py (76%) rename src/backend/{ => base}/langflow/api/utils.py (55%) rename src/backend/{ => base}/langflow/api/v1/__init__.py (72%) rename src/backend/{ => base}/langflow/api/v1/api_key.py (89%) create mode 100644 src/backend/base/langflow/api/v1/base.py rename src/backend/{ => base}/langflow/api/v1/callback.py (69%) create mode 100644 src/backend/base/langflow/api/v1/chat.py create mode 100644 src/backend/base/langflow/api/v1/endpoints.py create mode 100644 src/backend/base/langflow/api/v1/files.py rename src/backend/{ => base}/langflow/api/v1/flows.py (67%) rename src/backend/{ => base}/langflow/api/v1/login.py (88%) create mode 100644 src/backend/base/langflow/api/v1/monitor.py create mode 100644 src/backend/base/langflow/api/v1/schemas.py rename src/backend/{ => base}/langflow/api/v1/store.py (100%) rename src/backend/{ => base}/langflow/api/v1/users.py (100%) create mode 100644 src/backend/base/langflow/api/v1/validate.py create mode 100644 src/backend/base/langflow/api/v1/variable.py rename src/backend/{langflow/interface/embeddings => base/langflow/base}/__init__.py (100%) rename src/backend/{langflow/interface/initialize => base/langflow/base/agents}/__init__.py (100%) create mode 100644 src/backend/base/langflow/base/agents/agent.py create mode 100644 src/backend/base/langflow/base/constants.py rename src/backend/{langflow/interface/output_parsers => base/langflow/base/data}/__init__.py (100%) create mode 100644 src/backend/base/langflow/base/data/utils.py rename src/backend/{langflow/interface/retrievers => base/langflow/base/io}/__init__.py (100%) create mode 100644 src/backend/base/langflow/base/io/chat.py create mode 100644 src/backend/base/langflow/base/io/text.py create mode 100644 src/backend/base/langflow/base/models/__init__.py create mode 100644 src/backend/base/langflow/base/models/model.py rename src/backend/{langflow/interface/toolkits => base/langflow/base/prompts}/__init__.py (100%) create mode 100644 src/backend/base/langflow/base/prompts/utils.py create mode 100644 src/backend/base/langflow/components/__init__.py rename src/backend/{ => base}/langflow/components/agents/AgentInitializer.py (96%) create mode 100644 src/backend/base/langflow/components/agents/CSVAgent.py rename src/backend/{ => base}/langflow/components/agents/JsonAgent.py (90%) rename src/backend/{ => base}/langflow/components/agents/OpenAIConversationalAgent.py (95%) rename src/backend/{ => base}/langflow/components/agents/SQLAgent.py (90%) rename src/backend/{ => base}/langflow/components/agents/VectorStoreAgent.py (87%) rename src/backend/{ => base}/langflow/components/agents/VectorStoreRouterAgent.py (91%) create mode 100644 src/backend/base/langflow/components/agents/XMLAgent.py create mode 100644 src/backend/base/langflow/components/agents/__init__.py create mode 100644 src/backend/base/langflow/components/chains/ConversationChain.py rename src/backend/{ => base}/langflow/components/chains/LLMChain.py (53%) create mode 100644 src/backend/base/langflow/components/chains/LLMCheckerChain.py rename src/backend/{ => base}/langflow/components/chains/LLMMathChain.py (56%) create mode 100644 src/backend/base/langflow/components/chains/RetrievalQA.py create mode 100644 src/backend/base/langflow/components/chains/RetrievalQAWithSourcesChain.py create mode 100644 src/backend/base/langflow/components/chains/SQLGenerator.py create mode 100644 src/backend/base/langflow/components/chains/__init__.py create mode 100644 src/backend/base/langflow/components/data/APIRequest.py create mode 100644 src/backend/base/langflow/components/data/Directory.py create mode 100644 src/backend/base/langflow/components/data/File.py create mode 100644 src/backend/base/langflow/components/data/URL.py create mode 100644 src/backend/base/langflow/components/data/__init__.py rename src/backend/{langflow/interface/utilities => base/langflow/components/documentloaders}/__init__.py (100%) rename src/backend/{ => base}/langflow/components/embeddings/AmazonBedrockEmbeddings.py (84%) rename src/backend/{ => base}/langflow/components/embeddings/AzureOpenAIEmbeddings.py (90%) rename src/backend/{ => base}/langflow/components/embeddings/CohereEmbeddings.py (83%) rename src/backend/{ => base}/langflow/components/embeddings/HuggingFaceEmbeddings.py (84%) rename src/backend/{ => base}/langflow/components/embeddings/HuggingFaceInferenceAPIEmbeddings.py (87%) rename src/backend/{ => base}/langflow/components/embeddings/OllamaEmbeddings.py (84%) rename src/backend/{ => base}/langflow/components/embeddings/OpenAIEmbeddings.py (78%) rename src/backend/{ => base}/langflow/components/embeddings/VertexAIEmbeddings.py (54%) create mode 100644 src/backend/base/langflow/components/embeddings/__init__.py create mode 100644 src/backend/base/langflow/components/experimental/ClearMessageHistory.py create mode 100644 src/backend/base/langflow/components/experimental/ExtractDataFromRecord.py create mode 100644 src/backend/base/langflow/components/experimental/FlowTool.py create mode 100644 src/backend/base/langflow/components/experimental/ListFlows.py create mode 100644 src/backend/base/langflow/components/experimental/Listen.py create mode 100644 src/backend/base/langflow/components/experimental/MergeRecords.py create mode 100644 src/backend/base/langflow/components/experimental/Notify.py create mode 100644 src/backend/base/langflow/components/experimental/PythonFunction.py create mode 100644 src/backend/base/langflow/components/experimental/RunFlow.py create mode 100644 src/backend/base/langflow/components/experimental/RunnableExecutor.py create mode 100644 src/backend/base/langflow/components/experimental/SQLExecutor.py create mode 100644 src/backend/base/langflow/components/experimental/SubFlow.py create mode 100644 src/backend/base/langflow/components/experimental/__init__.py create mode 100644 src/backend/base/langflow/components/helpers/CombineText.py create mode 100644 src/backend/base/langflow/components/helpers/CreateRecord.py create mode 100644 src/backend/base/langflow/components/helpers/CustomComponent.py create mode 100644 src/backend/base/langflow/components/helpers/DocumentToRecord.py create mode 100644 src/backend/base/langflow/components/helpers/IDGenerator.py create mode 100644 src/backend/base/langflow/components/helpers/MemoryComponent.py create mode 100644 src/backend/base/langflow/components/helpers/MessageHistory.py create mode 100644 src/backend/base/langflow/components/helpers/RecordsToText.py create mode 100644 src/backend/base/langflow/components/helpers/SplitText.py create mode 100644 src/backend/base/langflow/components/helpers/UpdateRecord.py create mode 100644 src/backend/base/langflow/components/helpers/__init__.py create mode 100644 src/backend/base/langflow/components/inputs/ChatInput.py create mode 100644 src/backend/base/langflow/components/inputs/Prompt.py create mode 100644 src/backend/base/langflow/components/inputs/TextInput.py create mode 100644 src/backend/base/langflow/components/inputs/__init__.py rename src/backend/{langflow/components/utilities => base/langflow/components/langchain_utilities}/BingSearchAPIWrapper.py (94%) rename src/backend/{langflow/components/utilities => base/langflow/components/langchain_utilities}/GoogleSearchAPIWrapper.py (91%) rename src/backend/{langflow/components/utilities => base/langflow/components/langchain_utilities}/GoogleSerperAPIWrapper.py (83%) rename src/backend/{langflow/components/utilities => base/langflow/components/langchain_utilities}/JSONDocumentBuilder.py (95%) create mode 100644 src/backend/base/langflow/components/langchain_utilities/SQLDatabase.py rename src/backend/{langflow/components/tools => base/langflow/components/langchain_utilities}/SearchApi.py (87%) rename src/backend/{langflow/components/utilities => base/langflow/components/langchain_utilities}/SearxSearchWrapper.py (90%) rename src/backend/{langflow/components/utilities => base/langflow/components/langchain_utilities}/SerpAPIWrapper.py (93%) rename src/backend/{langflow/components/utilities => base/langflow/components/langchain_utilities}/WikipediaAPIWrapper.py (93%) rename src/backend/{langflow/components/utilities => base/langflow/components/langchain_utilities}/WolframAlphaAPIWrapper.py (90%) rename src/backend/{langflow/interface/vector_store => base/langflow/components/memories}/__init__.py (100%) rename src/backend/{langflow/components/llms/AmazonBedrock.py => base/langflow/components/model_specs/AmazonBedrockSpecs.py} (93%) rename src/backend/{langflow/components/llms/AnthropicLLM.py => base/langflow/components/model_specs/AnthropicLLMSpecs.py} (96%) rename src/backend/{langflow/components/llms/Anthropic.py => base/langflow/components/model_specs/AnthropicSpecs.py} (93%) rename src/backend/{langflow/components/llms/AzureChatOpenAI.py => base/langflow/components/model_specs/AzureChatOpenAISpecs.py} (95%) rename src/backend/{langflow/components/llms/BaiduQianfanChatEndpoints.py => base/langflow/components/model_specs/BaiduQianfanChatEndpointsSpecs.py} (98%) rename src/backend/{langflow/components/llms/BaiduQianfanLLMEndpoints.py => base/langflow/components/model_specs/BaiduQianfanLLMEndpointsSpecs.py} (97%) rename src/backend/{langflow/components/llms/ChatAnthropic.py => base/langflow/components/model_specs/ChatAnthropicSpecs.py} (94%) rename src/backend/{langflow/components/llms/ChatLiteLLM.py => base/langflow/components/model_specs/ChatLiteLLMSpecs.py} (72%) rename src/backend/{langflow/components/llms/ChatOllamaEndpoint.py => base/langflow/components/model_specs/ChatOllamaEndpointSpecs.py} (98%) rename src/backend/{langflow/components/llms/ChatOpenAI.py => base/langflow/components/model_specs/ChatOpenAISpecs.py} (90%) rename src/backend/{langflow/components/llms/ChatVertexAI.py => base/langflow/components/model_specs/ChatVertexAISpecs.py} (96%) rename src/backend/{langflow/components/llms/Cohere.py => base/langflow/components/model_specs/CohereSpecs.py} (91%) create mode 100644 src/backend/base/langflow/components/model_specs/GoogleGenerativeAISpecs.py rename src/backend/{langflow/components/llms/HuggingFaceEndpoints.py => base/langflow/components/model_specs/HuggingFaceEndpointsSpecs.py} (93%) rename src/backend/{langflow/components/llms/OllamaLLM.py => base/langflow/components/model_specs/OllamaLLMSpecs.py} (98%) rename src/backend/{langflow/components/llms/VertexAI.py => base/langflow/components/model_specs/VertexAISpecs.py} (96%) create mode 100644 src/backend/base/langflow/components/model_specs/__init__.py create mode 100644 src/backend/base/langflow/components/models/AmazonBedrockModel.py create mode 100644 src/backend/base/langflow/components/models/AnthropicModel.py create mode 100644 src/backend/base/langflow/components/models/AzureOpenAIModel.py create mode 100644 src/backend/base/langflow/components/models/BaiduQianfanChatModel.py create mode 100644 src/backend/base/langflow/components/models/ChatLiteLLMModel.py create mode 100644 src/backend/base/langflow/components/models/CohereModel.py create mode 100644 src/backend/base/langflow/components/models/GoogleGenerativeAIModel.py create mode 100644 src/backend/base/langflow/components/models/HuggingFaceModel.py create mode 100644 src/backend/base/langflow/components/models/OllamaModel.py create mode 100644 src/backend/base/langflow/components/models/OpenAIModel.py create mode 100644 src/backend/base/langflow/components/models/VertexAiModel.py create mode 100644 src/backend/base/langflow/components/models/__init__.py create mode 100644 src/backend/base/langflow/components/outputs/ChatOutput.py create mode 100644 src/backend/base/langflow/components/outputs/TextOutput.py create mode 100644 src/backend/base/langflow/components/outputs/__init__.py rename src/backend/{ => base}/langflow/components/retrievers/AmazonKendra.py (91%) rename src/backend/{ => base}/langflow/components/retrievers/MetalRetriever.py (88%) rename src/backend/{ => base}/langflow/components/retrievers/MultiQueryRetriever.py (96%) rename src/backend/{ => base}/langflow/components/retrievers/VectaraSelfQueryRetriver.py (96%) rename src/backend/{ => base}/langflow/components/retrievers/VectorStoreRetriever.py (87%) create mode 100644 src/backend/base/langflow/components/retrievers/__init__.py rename src/backend/{ => base}/langflow/components/textsplitters/CharacterTextSplitter.py (54%) rename src/backend/{ => base}/langflow/components/textsplitters/LanguageRecursiveTextSplitter.py (81%) rename src/backend/{ => base}/langflow/components/textsplitters/RecursiveCharacterTextSplitter.py (75%) create mode 100644 src/backend/base/langflow/components/textsplitters/__init__.py rename src/backend/{ => base}/langflow/components/toolkits/JsonToolkit.py (87%) rename src/backend/{ => base}/langflow/components/toolkits/Metaphor.py (96%) rename src/backend/{ => base}/langflow/components/toolkits/OpenAPIToolkit.py (91%) rename src/backend/{ => base}/langflow/components/toolkits/VectorStoreInfo.py (91%) rename src/backend/{ => base}/langflow/components/toolkits/VectorStoreRouterToolkit.py (84%) rename src/backend/{ => base}/langflow/components/toolkits/VectorStoreToolkit.py (72%) create mode 100644 src/backend/base/langflow/components/toolkits/__init__.py rename src/backend/{ => base}/langflow/components/tools/RetrieverTool.py (92%) create mode 100644 src/backend/base/langflow/components/tools/SearchAPITool.py create mode 100644 src/backend/base/langflow/components/tools/SearchApi.py create mode 100644 src/backend/base/langflow/components/tools/__init__.py create mode 100644 src/backend/base/langflow/components/vectorsearch/AstraDBSearch.py create mode 100644 src/backend/base/langflow/components/vectorsearch/ChromaSearch.py create mode 100644 src/backend/base/langflow/components/vectorsearch/FAISSSearch.py create mode 100644 src/backend/base/langflow/components/vectorsearch/MongoDBAtlasVectorSearch.py create mode 100644 src/backend/base/langflow/components/vectorsearch/PineconeSearch.py create mode 100644 src/backend/base/langflow/components/vectorsearch/QdrantSearch.py create mode 100644 src/backend/base/langflow/components/vectorsearch/RedisSearch.py create mode 100644 src/backend/base/langflow/components/vectorsearch/SupabaseVectorStoreSearch.py create mode 100644 src/backend/base/langflow/components/vectorsearch/VectaraSearch.py create mode 100644 src/backend/base/langflow/components/vectorsearch/WeaviateSearch.py create mode 100644 src/backend/base/langflow/components/vectorsearch/__init__.py create mode 100644 src/backend/base/langflow/components/vectorsearch/pgvectorSearch.py create mode 100644 src/backend/base/langflow/components/vectorstores/AstraDB.py rename src/backend/{ => base}/langflow/components/vectorstores/Chroma.py (75%) create mode 100644 src/backend/base/langflow/components/vectorstores/FAISS.py create mode 100644 src/backend/base/langflow/components/vectorstores/MongoDBAtlasVector.py rename src/backend/{ => base}/langflow/components/vectorstores/Pinecone.py (65%) rename src/backend/{ => base}/langflow/components/vectorstores/Qdrant.py (82%) rename src/backend/{ => base}/langflow/components/vectorstores/Redis.py (84%) rename src/backend/{ => base}/langflow/components/vectorstores/SupabaseVectorStore.py (72%) rename src/backend/{ => base}/langflow/components/vectorstores/Vectara.py (78%) rename src/backend/{ => base}/langflow/components/vectorstores/Weaviate.py (73%) create mode 100644 src/backend/base/langflow/components/vectorstores/__init__.py create mode 100644 src/backend/base/langflow/components/vectorstores/base/__init__.py create mode 100644 src/backend/base/langflow/components/vectorstores/base/model.py rename src/backend/{ => base}/langflow/components/vectorstores/pgvector.py (84%) rename src/backend/{ => base}/langflow/config.yaml (74%) rename src/backend/{langflow/interface/wrappers => base/langflow/core}/__init__.py (100%) rename src/backend/{ => base}/langflow/core/celery_app.py (100%) rename src/backend/{ => base}/langflow/core/celeryconfig.py (100%) rename src/backend/{langflow/components/__init__.py => base/langflow/custom.py} (62%) rename src/backend/{ => base}/langflow/field_typing/__init__.py (97%) rename src/backend/{ => base}/langflow/field_typing/constants.py (95%) create mode 100644 src/backend/base/langflow/field_typing/range_spec.py rename src/backend/{ => base}/langflow/graph/__init__.py (93%) rename src/backend/{langflow/processing => base/langflow/graph/edge}/__init__.py (100%) rename src/backend/{ => base}/langflow/graph/edge/base.py (54%) create mode 100644 src/backend/base/langflow/graph/edge/schema.py create mode 100644 src/backend/base/langflow/graph/edge/utils.py rename src/backend/{langflow/services/auth => base/langflow/graph/graph}/__init__.py (100%) create mode 100644 src/backend/base/langflow/graph/graph/base.py rename src/backend/{ => base}/langflow/graph/graph/constants.py (89%) create mode 100644 src/backend/base/langflow/graph/graph/runnable_vertices_manager.py create mode 100644 src/backend/base/langflow/graph/graph/state_manager.py rename src/backend/{ => base}/langflow/graph/graph/utils.py (82%) create mode 100644 src/backend/base/langflow/graph/schema.py rename src/backend/{ => base}/langflow/graph/utils.py (53%) rename src/backend/{langflow/services/chat => base/langflow/graph/vertex}/__init__.py (100%) create mode 100644 src/backend/base/langflow/graph/vertex/base.py rename src/backend/{ => base}/langflow/graph/vertex/constants.py (100%) create mode 100644 src/backend/base/langflow/graph/vertex/types.py create mode 100644 src/backend/base/langflow/graph/vertex/utils.py create mode 100644 src/backend/base/langflow/helpers/__init__.py create mode 100644 src/backend/base/langflow/helpers/flow.py create mode 100644 src/backend/base/langflow/helpers/record.py rename src/backend/{langflow/services/credentials => base/langflow/initial_setup}/__init__.py (100%) create mode 100644 src/backend/base/langflow/initial_setup/setup.py create mode 100644 src/backend/base/langflow/initial_setup/starter_projects/Basic Prompting (Hello, world!).json create mode 100644 src/backend/base/langflow/initial_setup/starter_projects/Langflow Blog Writter.json create mode 100644 src/backend/base/langflow/initial_setup/starter_projects/Langflow Document QA.json create mode 100644 src/backend/base/langflow/initial_setup/starter_projects/Langflow Memory Conversation.json create mode 100644 src/backend/base/langflow/initial_setup/starter_projects/Langflow Prompt Chaining.json create mode 100644 src/backend/base/langflow/initial_setup/starter_projects/VectorStore-RAG-Flows.json rename src/backend/{langflow/services/database => base/langflow/interface}/__init__.py (100%) rename src/backend/{ => base}/langflow/interface/agents/__init__.py (100%) rename src/backend/{ => base}/langflow/interface/agents/base.py (97%) rename src/backend/{ => base}/langflow/interface/agents/custom.py (98%) rename src/backend/{ => base}/langflow/interface/agents/prebuilt.py (100%) rename src/backend/{ => base}/langflow/interface/base.py (100%) rename src/backend/{ => base}/langflow/interface/chains/__init__.py (100%) rename src/backend/{ => base}/langflow/interface/chains/base.py (98%) rename src/backend/{ => base}/langflow/interface/chains/custom.py (99%) rename src/backend/{ => base}/langflow/interface/custom/__init__.py (100%) create mode 100644 src/backend/base/langflow/interface/custom/attributes.py rename src/backend/{ => base}/langflow/interface/custom/base.py (85%) rename src/backend/{ => base}/langflow/interface/custom/code_parser/__init__.py (100%) rename src/backend/{ => base}/langflow/interface/custom/code_parser/code_parser.py (90%) rename src/backend/{ => base}/langflow/interface/custom/code_parser/utils.py (77%) rename src/backend/{ => base}/langflow/interface/custom/custom_component/__init__.py (100%) rename src/backend/{ => base}/langflow/interface/custom/custom_component/component.py (56%) create mode 100644 src/backend/base/langflow/interface/custom/custom_component/custom_component.py rename src/backend/{ => base}/langflow/interface/custom/directory_reader/__init__.py (100%) rename src/backend/{ => base}/langflow/interface/custom/directory_reader/directory_reader.py (86%) rename src/backend/{ => base}/langflow/interface/custom/directory_reader/utils.py (91%) create mode 100644 src/backend/base/langflow/interface/custom/eval.py rename src/backend/{ => base}/langflow/interface/custom/schema.py (80%) rename src/backend/{ => base}/langflow/interface/custom/utils.py (66%) rename src/backend/{ => base}/langflow/interface/custom_lists.py (100%) rename src/backend/{langflow/services/plugins => base/langflow/interface/document_loaders}/__init__.py (100%) rename src/backend/{ => base}/langflow/interface/document_loaders/base.py (100%) rename src/backend/{langflow/services/session => base/langflow/interface/embeddings}/__init__.py (100%) rename src/backend/{ => base}/langflow/interface/embeddings/base.py (100%) rename src/backend/{ => base}/langflow/interface/importing/__init__.py (54%) rename src/backend/{ => base}/langflow/interface/importing/utils.py (86%) rename src/backend/{langflow/services/store => base/langflow/interface/initialize}/__init__.py (100%) rename src/backend/{ => base}/langflow/interface/initialize/llm.py (100%) rename src/backend/{ => base}/langflow/interface/initialize/loading.py (84%) rename src/backend/{ => base}/langflow/interface/initialize/utils.py (100%) rename src/backend/{ => base}/langflow/interface/initialize/vector_store.py (100%) rename src/backend/{ => base}/langflow/interface/listing.py (89%) rename src/backend/{ => base}/langflow/interface/llms/__init__.py (100%) rename src/backend/{ => base}/langflow/interface/llms/base.py (97%) rename src/backend/{ => base}/langflow/interface/memories/__init__.py (100%) rename src/backend/{ => base}/langflow/interface/memories/base.py (97%) rename src/backend/{langflow/services/task => base/langflow/interface/output_parsers}/__init__.py (100%) rename src/backend/{ => base}/langflow/interface/output_parsers/base.py (99%) rename src/backend/{ => base}/langflow/interface/prompts/__init__.py (100%) rename src/backend/{ => base}/langflow/interface/prompts/base.py (97%) rename src/backend/{ => base}/langflow/interface/prompts/custom.py (100%) rename src/backend/{langflow/services/task/backends => base/langflow/interface/retrievers}/__init__.py (100%) rename src/backend/{ => base}/langflow/interface/retrievers/base.py (99%) rename src/backend/{ => base}/langflow/interface/run.py (79%) rename src/backend/{ => base}/langflow/interface/text_splitters/__init__.py (100%) rename src/backend/{ => base}/langflow/interface/text_splitters/base.py (100%) rename src/backend/{langflow/template => base/langflow/interface/toolkits}/__init__.py (100%) rename src/backend/{ => base}/langflow/interface/toolkits/base.py (79%) rename src/backend/{ => base}/langflow/interface/toolkits/custom.py (100%) rename src/backend/{ => base}/langflow/interface/tools/__init__.py (100%) rename src/backend/{ => base}/langflow/interface/tools/base.py (95%) rename src/backend/{ => base}/langflow/interface/tools/constants.py (86%) rename src/backend/{ => base}/langflow/interface/tools/custom.py (95%) rename src/backend/{ => base}/langflow/interface/tools/util.py (100%) rename src/backend/{ => base}/langflow/interface/types.py (75%) rename src/backend/{langflow/template/field => base/langflow/interface/utilities}/__init__.py (100%) rename src/backend/{ => base}/langflow/interface/utilities/base.py (97%) rename src/backend/{ => base}/langflow/interface/utils.py (71%) rename src/backend/{langflow/template/frontend_node/formatter => base/langflow/interface/vector_store}/__init__.py (100%) rename src/backend/{ => base}/langflow/interface/vector_store/base.py (100%) rename src/backend/{langflow/template/template => base/langflow/interface/wrappers}/__init__.py (100%) rename src/backend/{ => base}/langflow/interface/wrappers/base.py (51%) rename src/backend/{langflow/utils => base/langflow/legacy_custom}/__init__.py (100%) rename src/backend/{langflow/custom => base/langflow/legacy_custom}/customs.py (94%) create mode 100644 src/backend/base/langflow/load.py rename src/backend/{ => base}/langflow/main.py (74%) create mode 100644 src/backend/base/langflow/memory.py create mode 100644 src/backend/base/langflow/processing/__init__.py rename src/backend/{ => base}/langflow/processing/base.py (90%) create mode 100644 src/backend/base/langflow/processing/load.py create mode 100644 src/backend/base/langflow/processing/process.py create mode 100644 src/backend/base/langflow/py.typed create mode 100644 src/backend/base/langflow/schema/__init__.py create mode 100644 src/backend/base/langflow/schema/dotdict.py create mode 100644 src/backend/base/langflow/schema/schema.py rename src/backend/{ => base}/langflow/server.py (63%) rename src/backend/{ => base}/langflow/services/__init__.py (100%) create mode 100644 src/backend/base/langflow/services/auth/__init__.py rename src/backend/{ => base}/langflow/services/auth/factory.py (100%) rename src/backend/{ => base}/langflow/services/auth/service.py (99%) rename src/backend/{ => base}/langflow/services/auth/utils.py (94%) create mode 100644 src/backend/base/langflow/services/base.py create mode 100644 src/backend/base/langflow/services/cache/__init__.py create mode 100644 src/backend/base/langflow/services/cache/base.py rename src/backend/{ => base}/langflow/services/cache/factory.py (78%) rename src/backend/{ => base}/langflow/services/cache/service.py (73%) rename src/backend/{ => base}/langflow/services/cache/utils.py (100%) create mode 100644 src/backend/base/langflow/services/chat/__init__.py rename src/backend/{ => base}/langflow/services/chat/cache.py (99%) rename src/backend/{ => base}/langflow/services/chat/config.py (100%) rename src/backend/{ => base}/langflow/services/chat/factory.py (100%) create mode 100644 src/backend/base/langflow/services/chat/service.py rename src/backend/{ => base}/langflow/services/chat/utils.py (99%) create mode 100644 src/backend/base/langflow/services/database/__init__.py rename src/backend/{ => base}/langflow/services/database/factory.py (99%) create mode 100644 src/backend/base/langflow/services/database/models/__init__.py rename src/backend/{ => base}/langflow/services/database/models/api_key/__init__.py (100%) rename src/backend/{ => base}/langflow/services/database/models/api_key/crud.py (100%) rename src/backend/{ => base}/langflow/services/database/models/api_key/model.py (100%) rename src/backend/{ => base}/langflow/services/database/models/base.py (100%) rename src/backend/{ => base}/langflow/services/database/models/flow/__init__.py (100%) create mode 100644 src/backend/base/langflow/services/database/models/flow/model.py rename src/backend/{ => base}/langflow/services/database/models/user/__init__.py (100%) rename src/backend/{ => base}/langflow/services/database/models/user/crud.py (99%) rename src/backend/{ => base}/langflow/services/database/models/user/model.py (93%) create mode 100644 src/backend/base/langflow/services/database/models/variable/__init__.py create mode 100644 src/backend/base/langflow/services/database/models/variable/model.py rename src/backend/{ => base}/langflow/services/database/service.py (94%) rename src/backend/{ => base}/langflow/services/database/utils.py (100%) create mode 100644 src/backend/base/langflow/services/deps.py create mode 100644 src/backend/base/langflow/services/factory.py rename src/backend/{ => base}/langflow/services/manager.py (61%) create mode 100644 src/backend/base/langflow/services/monitor/__init__.py create mode 100644 src/backend/base/langflow/services/monitor/factory.py create mode 100644 src/backend/base/langflow/services/monitor/schema.py create mode 100644 src/backend/base/langflow/services/monitor/service.py create mode 100644 src/backend/base/langflow/services/monitor/utils.py create mode 100644 src/backend/base/langflow/services/plugins/__init__.py rename src/backend/{ => base}/langflow/services/plugins/base.py (100%) rename src/backend/{ => base}/langflow/services/plugins/factory.py (100%) rename src/backend/{ => base}/langflow/services/plugins/langfuse_plugin.py (99%) rename src/backend/{ => base}/langflow/services/plugins/service.py (99%) rename src/backend/{ => base}/langflow/services/schema.py (66%) create mode 100644 src/backend/base/langflow/services/session/__init__.py rename src/backend/{ => base}/langflow/services/session/factory.py (72%) rename src/backend/{ => base}/langflow/services/session/service.py (57%) rename src/backend/{ => base}/langflow/services/session/utils.py (100%) rename src/backend/{ => base}/langflow/services/settings/__init__.py (100%) rename src/backend/{ => base}/langflow/services/settings/auth.py (81%) rename src/backend/{ => base}/langflow/services/settings/base.py (98%) rename src/backend/{ => base}/langflow/services/settings/constants.py (100%) rename src/backend/{ => base}/langflow/services/settings/factory.py (99%) rename src/backend/{langflow/services/settings/service.py => base/langflow/services/settings/manager.py} (99%) create mode 100644 src/backend/base/langflow/services/settings/service.py rename src/backend/{ => base}/langflow/services/settings/utils.py (100%) create mode 100644 src/backend/base/langflow/services/socket/__init__.py create mode 100644 src/backend/base/langflow/services/socket/factory.py create mode 100644 src/backend/base/langflow/services/socket/service.py create mode 100644 src/backend/base/langflow/services/socket/utils.py create mode 100644 src/backend/base/langflow/services/state/__init__.py create mode 100644 src/backend/base/langflow/services/state/factory.py create mode 100644 src/backend/base/langflow/services/state/service.py create mode 100644 src/backend/base/langflow/services/storage/__init__.py create mode 100644 src/backend/base/langflow/services/storage/constants.py create mode 100644 src/backend/base/langflow/services/storage/factory.py create mode 100644 src/backend/base/langflow/services/storage/local.py create mode 100644 src/backend/base/langflow/services/storage/s3.py create mode 100644 src/backend/base/langflow/services/storage/service.py create mode 100644 src/backend/base/langflow/services/storage/utils.py create mode 100644 src/backend/base/langflow/services/store/__init__.py rename src/backend/{ => base}/langflow/services/store/exceptions.py (100%) rename src/backend/{ => base}/langflow/services/store/factory.py (99%) rename src/backend/{ => base}/langflow/services/store/schema.py (100%) rename src/backend/{ => base}/langflow/services/store/service.py (100%) rename src/backend/{ => base}/langflow/services/store/utils.py (100%) create mode 100644 src/backend/base/langflow/services/task/__init__.py create mode 100644 src/backend/base/langflow/services/task/backends/__init__.py rename src/backend/{ => base}/langflow/services/task/backends/anyio.py (100%) rename src/backend/{ => base}/langflow/services/task/backends/base.py (95%) rename src/backend/{ => base}/langflow/services/task/backends/celery.py (99%) rename src/backend/{ => base}/langflow/services/task/factory.py (100%) rename src/backend/{ => base}/langflow/services/task/service.py (76%) rename src/backend/{ => base}/langflow/services/task/utils.py (100%) rename src/backend/{ => base}/langflow/services/utils.py (71%) create mode 100644 src/backend/base/langflow/services/variable/__init__.py rename src/backend/{langflow/services/credentials => base/langflow/services/variable}/factory.py (55%) create mode 100644 src/backend/base/langflow/services/variable/service.py rename src/backend/{ => base}/langflow/settings.py (100%) create mode 100644 src/backend/base/langflow/template/__init__.py create mode 100644 src/backend/base/langflow/template/field/__init__.py rename src/backend/{ => base}/langflow/template/field/base.py (64%) create mode 100644 src/backend/base/langflow/template/field/prompt.py rename src/backend/{ => base}/langflow/template/frontend_node/__init__.py (95%) rename src/backend/{ => base}/langflow/template/frontend_node/agents.py (99%) rename src/backend/{ => base}/langflow/template/frontend_node/base.py (88%) rename src/backend/{ => base}/langflow/template/frontend_node/chains.py (90%) rename src/backend/{ => base}/langflow/template/frontend_node/constants.py (92%) rename src/backend/{ => base}/langflow/template/frontend_node/custom_components.py (92%) rename src/backend/{ => base}/langflow/template/frontend_node/documentloaders.py (100%) rename src/backend/{ => base}/langflow/template/frontend_node/embeddings.py (100%) create mode 100644 src/backend/base/langflow/template/frontend_node/formatter/__init__.py rename src/backend/{ => base}/langflow/template/frontend_node/formatter/base.py (99%) rename src/backend/{ => base}/langflow/template/frontend_node/formatter/field_formatters.py (100%) rename src/backend/{ => base}/langflow/template/frontend_node/llms.py (100%) rename src/backend/{ => base}/langflow/template/frontend_node/memories.py (97%) rename src/backend/{ => base}/langflow/template/frontend_node/output_parsers.py (99%) rename src/backend/{ => base}/langflow/template/frontend_node/prompts.py (100%) rename src/backend/{ => base}/langflow/template/frontend_node/retrievers.py (100%) rename src/backend/{ => base}/langflow/template/frontend_node/textsplitters.py (99%) rename src/backend/{ => base}/langflow/template/frontend_node/tools.py (100%) rename src/backend/{ => base}/langflow/template/frontend_node/utilities.py (100%) rename src/backend/{ => base}/langflow/template/frontend_node/vectorstores.py (100%) create mode 100644 src/backend/base/langflow/template/template/__init__.py rename src/backend/{ => base}/langflow/template/template/base.py (97%) create mode 100644 src/backend/base/langflow/utils/__init__.py rename src/backend/{ => base}/langflow/utils/constants.py (98%) rename src/backend/{ => base}/langflow/utils/lazy_load.py (100%) rename src/backend/{ => base}/langflow/utils/logger.py (93%) rename src/backend/{ => base}/langflow/utils/payload.py (100%) create mode 100644 src/backend/base/langflow/utils/schemas.py rename src/backend/{ => base}/langflow/utils/util.py (92%) rename src/backend/{ => base}/langflow/utils/validate.py (97%) create mode 100644 src/backend/base/langflow/worker.py create mode 100644 src/backend/base/poetry.lock create mode 100644 src/backend/base/pyproject.toml delete mode 100644 src/backend/langflow/__init__.py delete mode 100644 src/backend/langflow/api/v1/base.py delete mode 100644 src/backend/langflow/api/v1/chat.py delete mode 100644 src/backend/langflow/api/v1/credential.py delete mode 100644 src/backend/langflow/api/v1/endpoints.py delete mode 100644 src/backend/langflow/api/v1/schemas.py delete mode 100644 src/backend/langflow/api/v1/validate.py delete mode 100644 src/backend/langflow/components/agents/CSVAgent.py delete mode 100644 src/backend/langflow/components/chains/ConversationChain.py delete mode 100644 src/backend/langflow/components/chains/LLMCheckerChain.py delete mode 100644 src/backend/langflow/components/chains/PromptRunner.py delete mode 100644 src/backend/langflow/components/chains/RetrievalQA.py delete mode 100644 src/backend/langflow/components/chains/RetrievalQAWithSourcesChain.py delete mode 100644 src/backend/langflow/components/chains/SQLDatabaseChain.py delete mode 100644 src/backend/langflow/components/custom_components/CustomComponent.py delete mode 100644 src/backend/langflow/components/documentloaders/DirectoryLoader.py delete mode 100644 src/backend/langflow/components/documentloaders/FileLoader.py delete mode 100644 src/backend/langflow/components/documentloaders/UrlLoader.py delete mode 100644 src/backend/langflow/components/llms/CTransformers.py delete mode 100644 src/backend/langflow/components/llms/GoogleGenerativeAI.py delete mode 100644 src/backend/langflow/components/llms/LlamaCpp.py delete mode 100644 src/backend/langflow/components/utilities/GetRequest.py delete mode 100644 src/backend/langflow/components/utilities/PostRequest.py delete mode 100644 src/backend/langflow/components/utilities/UpdateRequest.py delete mode 100644 src/backend/langflow/components/vectorstores/FAISS.py delete mode 100644 src/backend/langflow/components/vectorstores/MongoDBAtlasVectorSearch.py delete mode 100644 src/backend/langflow/field_typing/range_spec.py delete mode 100644 src/backend/langflow/graph/graph/base.py delete mode 100644 src/backend/langflow/graph/vertex/base.py delete mode 100644 src/backend/langflow/graph/vertex/types.py delete mode 100644 src/backend/langflow/graph/vertex/utils.py delete mode 100644 src/backend/langflow/interface/custom/custom_component/custom_component.py delete mode 100644 src/backend/langflow/processing/load.py delete mode 100644 src/backend/langflow/processing/process.py delete mode 100644 src/backend/langflow/services/base.py delete mode 100644 src/backend/langflow/services/cache/__init__.py delete mode 100644 src/backend/langflow/services/cache/base.py delete mode 100644 src/backend/langflow/services/chat/service.py delete mode 100644 src/backend/langflow/services/credentials/service.py delete mode 100644 src/backend/langflow/services/database/models/__init__.py delete mode 100644 src/backend/langflow/services/database/models/component/__init__.py delete mode 100644 src/backend/langflow/services/database/models/component/model.py delete mode 100644 src/backend/langflow/services/database/models/credential/__init__.py delete mode 100644 src/backend/langflow/services/database/models/credential/model.py delete mode 100644 src/backend/langflow/services/database/models/credential/schema.py delete mode 100644 src/backend/langflow/services/database/models/flow/model.py delete mode 100644 src/backend/langflow/services/deps.py delete mode 100644 src/backend/langflow/services/factory.py delete mode 100644 src/backend/langflow/utils/types.py create mode 100644 src/backend/langflow/version/__init__.py create mode 100644 src/backend/langflow/version/version.py delete mode 100644 src/backend/langflow/worker.py create mode 100644 src/frontend/.eslintrc.json delete mode 100644 src/frontend/.github/workflows/playwright.yml delete mode 100644 src/frontend/harFiles/backend_12112023.har delete mode 100644 src/frontend/playwright-report/index.html delete mode 100644 src/frontend/src/assets/Gooey Ring-5s-271px.svg delete mode 100644 src/frontend/src/assets/froze-flow.png create mode 100644 src/frontend/src/assets/undraw_blog_post_re_fy5x.svg create mode 100644 src/frontend/src/assets/undraw_chat_bot_re_e2gj.svg create mode 100644 src/frontend/src/assets/undraw_cloud_docs_re_xjht.svg create mode 100644 src/frontend/src/assets/undraw_design_components_9vy6.svg create mode 100644 src/frontend/src/assets/undraw_mobile_messages_re_yx8w.svg create mode 100644 src/frontend/src/assets/undraw_real_time_analytics_re_yliv.svg create mode 100644 src/frontend/src/assets/undraw_short_bio_re_fmx0.svg create mode 100644 src/frontend/src/assets/undraw_team_collaboration_re_ow29.svg create mode 100644 src/frontend/src/assets/undraw_transfer_files_re_a2a9.svg delete mode 100644 src/frontend/src/components/LightTooltipComponent/index.tsx delete mode 100644 src/frontend/src/components/LoadingSpinner/index.tsx delete mode 100644 src/frontend/src/components/RadialProgress/index.tsx delete mode 100644 src/frontend/src/components/ReactTooltipComponent/index.tsx delete mode 100644 src/frontend/src/components/TooltipComponent/index.tsx create mode 100644 src/frontend/src/components/ViewTriggers/chat/index.tsx create mode 100644 src/frontend/src/components/addNewVariableButtonComponent/addNewVariableButton.tsx delete mode 100644 src/frontend/src/components/chatComponent/buildTrigger/index.tsx delete mode 100644 src/frontend/src/components/chatComponent/chatTrigger/index.tsx create mode 100644 src/frontend/src/components/exampleComponent/index.tsx create mode 100644 src/frontend/src/components/inputGlobalComponent/index.tsx delete mode 100644 src/frontend/src/components/stackedComponents/index.tsx create mode 100644 src/frontend/src/components/textInputComponent/index.tsx create mode 100644 src/frontend/src/components/textOutputComponent/index.tsx delete mode 100644 src/frontend/src/components/toggleComponent/index.tsx create mode 100644 src/frontend/src/components/ui/checkmark.tsx create mode 100644 src/frontend/src/components/ui/dialog-with-no-close.tsx create mode 100644 src/frontend/src/components/ui/refreshButton.tsx create mode 100644 src/frontend/src/components/ui/xmark.tsx create mode 100644 src/frontend/src/constants/alerts_constants.tsx create mode 100644 src/frontend/src/icons/AstraDB/AstraDB.jsx create mode 100644 src/frontend/src/icons/AstraDB/Favicon.svg create mode 100644 src/frontend/src/icons/AstraDB/index.tsx create mode 100644 src/frontend/src/icons/Azure/Azure.jsx create mode 100644 src/frontend/src/icons/Azure/index.tsx create mode 100644 src/frontend/src/icons/BotMessageSquare/BotMessageSquare.jsx create mode 100644 src/frontend/src/icons/BotMessageSquare/index.tsx create mode 100644 src/frontend/src/icons/GoogleGenerativeAI/Google Gemini icon.svg create mode 100644 src/frontend/src/icons/GoogleGenerativeAI/GoogleGemini.jsx create mode 100644 src/frontend/src/icons/GoogleGenerativeAI/index.tsx create mode 100644 src/frontend/src/icons/Ollama/Ollama.jsx create mode 100644 src/frontend/src/icons/Ollama/Ollama.svg create mode 100644 src/frontend/src/icons/Ollama/index.tsx create mode 100644 src/frontend/src/icons/Postgres/Postgres.jsx create mode 100644 src/frontend/src/icons/Postgres/Postgres.svg create mode 100644 src/frontend/src/icons/Postgres/index.tsx create mode 100644 src/frontend/src/icons/Python/Python.jsx create mode 100644 src/frontend/src/icons/Python/Python.svg create mode 100644 src/frontend/src/icons/Python/index.tsx create mode 100644 src/frontend/src/icons/QianFanChat/QianFanChat.jsx create mode 100644 src/frontend/src/icons/QianFanChat/QianFanChat.svg create mode 100644 src/frontend/src/icons/QianFanChat/index.tsx create mode 100644 src/frontend/src/icons/Redis/Redis.jsx create mode 100644 src/frontend/src/icons/Redis/Redis.svg create mode 100644 src/frontend/src/icons/Redis/index.tsx create mode 100644 src/frontend/src/modals/IOModal/components/IOFieldView/components/FileInput/index.tsx create mode 100644 src/frontend/src/modals/IOModal/components/IOFieldView/index.tsx create mode 100644 src/frontend/src/modals/IOModal/components/chatView/chatInput/index.tsx rename src/frontend/src/modals/{formModal => IOModal/components/chatView}/chatMessage/codeBlock/index.tsx (92%) create mode 100644 src/frontend/src/modals/IOModal/components/chatView/chatMessage/index.tsx rename src/frontend/src/modals/{formModal => IOModal/components/chatView}/fileComponent/index.tsx (94%) create mode 100644 src/frontend/src/modals/IOModal/components/chatView/index.tsx create mode 100644 src/frontend/src/modals/IOModal/index.tsx create mode 100644 src/frontend/src/modals/NewFlowModal/components/NewFlowCardComponent/index.tsx create mode 100644 src/frontend/src/modals/NewFlowModal/components/undrawCards/index.tsx create mode 100644 src/frontend/src/modals/NewFlowModal/index.tsx delete mode 100644 src/frontend/src/modals/formModal/chatInput/index.tsx delete mode 100644 src/frontend/src/modals/formModal/chatMessage/index.tsx delete mode 100644 src/frontend/src/modals/formModal/index.tsx create mode 100644 src/frontend/src/pages/FlowPage/components/ParentDisclosureComponent/index.tsx create mode 100644 src/frontend/src/pages/FlowPage/components/extraSidebarComponent/utils.tsx create mode 100644 src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/toolbarSelectItem/index.tsx create mode 100644 src/frontend/src/stores/globalVariables.ts create mode 100644 src/frontend/src/stores/shortcuts.ts create mode 100644 src/frontend/src/types/zustand/flowIOStore/index.ts create mode 100644 src/frontend/src/types/zustand/globalVariables/index.ts create mode 100644 src/frontend/src/utils/buildUtils.ts create mode 100644 src/frontend/src/utils/parameterUtils.ts create mode 100644 src/frontend/tests/end-to-end/assets/ChatTest.json rename src/frontend/tests/{onlyFront => end-to-end}/assets/collection.json (88%) rename src/frontend/tests/{onlyFront => end-to-end}/assets/flow.json (100%) create mode 100644 src/frontend/tests/end-to-end/assets/flow_group_test.json rename src/frontend/tests/{onlyFront => end-to-end}/assets/flowtest.json (54%) rename src/frontend/tests/{onlyFront => end-to-end}/auto_login.spec.ts (52%) create mode 100644 src/frontend/tests/end-to-end/chat_io.spec.ts create mode 100644 src/frontend/tests/end-to-end/curl_api_generation.spec.ts rename src/frontend/tests/{onlyFront => end-to-end}/dragAndDrop.spec.ts (68%) create mode 100644 src/frontend/tests/end-to-end/dropdownComponent.spec.ts rename src/frontend/tests/{onlyFront => end-to-end}/floatComponent.spec.ts (91%) rename src/frontend/tests/{onlyFront => end-to-end}/flowPage.spec.ts (62%) create mode 100644 src/frontend/tests/end-to-end/group.spec.ts rename src/frontend/tests/{onlyFront => end-to-end}/inputComponent.spec.ts (62%) create mode 100644 src/frontend/tests/end-to-end/intComponent.spec.ts rename src/frontend/tests/{onlyFront => end-to-end}/keyPairListComponent.spec.ts (55%) create mode 100644 src/frontend/tests/end-to-end/langflowShortcuts.spec.ts rename src/frontend/tests/{onlyFront => end-to-end}/nestedComponent.spec.ts (80%) create mode 100644 src/frontend/tests/end-to-end/python_api_generation.spec.ts rename src/frontend/tests/{onlyFront => end-to-end}/saveComponents.spec.ts (73%) rename src/frontend/tests/{onlyFront => end-to-end}/toggleComponent.spec.ts (67%) create mode 100644 src/frontend/tests/end-to-end/tweaks_test.spec.ts create mode 100644 src/frontend/tests/globalTeardown.ts delete mode 100644 src/frontend/tests/onlyFront/dropdownComponent.spec.ts delete mode 100644 src/frontend/tests/onlyFront/group.spec.ts delete mode 100644 src/frontend/tests/onlyFront/intComponent.spec.ts delete mode 100644 src/frontend/tests/onlyFront/login.spec.ts create mode 100644 tests/data/ChatInputTest.json create mode 100644 tests/data/TwoOutputsTest.json create mode 100644 tests/test_data_components.py delete mode 100644 tests/test_embeddings_template.py create mode 100644 tests/test_files.py create mode 100644 tests/test_helper_components.py create mode 100644 tests/test_initial_setup.py delete mode 100644 tests/test_prompts_template.py create mode 100644 tests/test_record.py delete mode 100644 tests/test_websocket.py create mode 100644 tests/text_experimental_components.py diff --git a/.dockerignore b/.dockerignore index 130ca4c2c..7cae75457 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,6 +1,6 @@ .venv/ **/aws -# node_modules +node_modules **/node_modules/ dist/ **/build/ diff --git a/.env.example b/.env.example index 29a7259b0..26f6e3a29 100644 --- a/.env.example +++ b/.env.example @@ -56,6 +56,13 @@ LANGFLOW_REMOVE_API_KEYS= # LANGFLOW_REDIS_CACHE_EXPIRE (default: 3600) LANGFLOW_CACHE_TYPE= + +# Set AUTO_LOGIN to false if you want to disable auto login +# and use the login form to login. LANGFLOW_SUPERUSER and LANGFLOW_SUPERUSER_PASSWORD +# must be set if AUTO_LOGIN is set to false +# Values: true, false +LANGFLOW_AUTO_LOGIN= + # Superuser username # Example: LANGFLOW_SUPERUSER=admin LANGFLOW_SUPERUSER= diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index d4eaafb95..c78ba4c71 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -14,7 +14,7 @@ on: - "src/backend/**" env: - POETRY_VERSION: "1.7.0" + POETRY_VERSION: "1.8.2" jobs: lint: @@ -22,7 +22,6 @@ jobs: strategy: matrix: python-version: - - "3.9" - "3.10" - "3.11" steps: @@ -32,12 +31,15 @@ jobs: pipx install poetry==$POETRY_VERSION - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 + id: setup-python with: python-version: ${{ matrix.python-version }} cache: poetry - - name: Install dependencies + - name: Install Python dependencies run: | + poetry env use ${{ matrix.python-version }} poetry install + if: ${{ steps.setup-python.outputs.cache-hit != 'true' }} - name: Analysing the code with our lint run: | make lint diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release-base.yml similarity index 86% rename from .github/workflows/pre-release.yml rename to .github/workflows/pre-release-base.yml index 58bdd219e..60872def3 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release-base.yml @@ -1,4 +1,4 @@ -name: pre-release +name: Langflow Base Pre-release on: pull_request: @@ -11,7 +11,7 @@ on: workflow_dispatch: env: - POETRY_VERSION: "1.5.1" + POETRY_VERSION: "1.8.2" jobs: if_release: @@ -27,7 +27,7 @@ jobs: python-version: "3.10" cache: "poetry" - name: Build project for distribution - run: make build + run: make build base=true - name: Check Version id: check-version run: | @@ -46,7 +46,7 @@ jobs: env: POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_API_TOKEN }} run: | - poetry publish + poetry publish base=true - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx @@ -61,5 +61,6 @@ jobs: with: context: . push: true - file: ./build_and_push.Dockerfile - tags: logspace/langflow:${{ steps.check-version.outputs.version }} + file: ./build_and_push_base.Dockerfile + tags: | + logspace/langflow:base-${{ steps.check-version.outputs.version }} diff --git a/.github/workflows/pre-release-langflow.yml b/.github/workflows/pre-release-langflow.yml new file mode 100644 index 000000000..57f3b3e1a --- /dev/null +++ b/.github/workflows/pre-release-langflow.yml @@ -0,0 +1,70 @@ +name: Langflow Pre-release + +on: + pull_request: + types: + - closed + branches: + - dev + paths: + - "pyproject.toml" + workflow_dispatch: + workflow_run: + workflows: ["pre-release-base"] + types: [completed] + branches: [dev] + +env: + POETRY_VERSION: "1.8.2" + +jobs: + if_release: + if: ${{ (github.event.pull_request.merged == true) && contains(github.event.pull_request.labels.*.name, 'pre-release') }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install poetry + run: pipx install poetry==$POETRY_VERSION + - name: Set up Python 3.10 + uses: actions/setup-python@v5 + with: + python-version: "3.10" + cache: "poetry" + - name: Build project for distribution + run: make build main=true + - name: Check Version + id: check-version + run: | + echo version=$(poetry version --short) >> $GITHUB_OUTPUT + - name: Create Release + uses: ncipollo/release-action@v1 + with: + artifacts: "dist/*" + token: ${{ secrets.GITHUB_TOKEN }} + draft: false + generateReleaseNotes: true + prerelease: true + tag: v${{ steps.check-version.outputs.version }} + commit: dev + - name: Publish to PyPI + env: + POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_API_TOKEN }} + run: | + poetry publish main=true + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: . + push: true + file: ./build_and_push.Dockerfile + tags: | + logspace/langflow:${{ steps.check-version.outputs.version }} diff --git a/.github/workflows/test.yml b/.github/workflows/python_test.yml similarity index 76% rename from .github/workflows/test.yml rename to .github/workflows/python_test.yml index 10ab9b324..a04a208f3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/python_test.yml @@ -15,7 +15,7 @@ on: - "src/backend/**" env: - POETRY_VERSION: "1.5.0" + POETRY_VERSION: "1.8.2" jobs: build: @@ -33,11 +33,15 @@ jobs: run: pipx install poetry==$POETRY_VERSION - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 + id: setup-python with: python-version: ${{ matrix.python-version }} cache: "poetry" - - name: Install dependencies - run: poetry install + - name: Install Python dependencies + run: | + poetry env use ${{ matrix.python-version }} + poetry install + if: ${{ steps.setup-python.outputs.cache-hit != 'true' }} - name: Run unit tests run: | make tests diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 21d8d27eb..8004618f6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,7 +10,7 @@ on: - "pyproject.toml" env: - POETRY_VERSION: "1.5.1" + POETRY_VERSION: "1.8.2" jobs: if_release: diff --git a/.github/workflows/typescript_test.yml b/.github/workflows/typescript_test.yml new file mode 100644 index 000000000..a75327785 --- /dev/null +++ b/.github/workflows/typescript_test.yml @@ -0,0 +1,149 @@ +name: Run Frontend Tests + +on: + pull_request: + paths: + - "src/frontend/**" + +env: + POETRY_VERSION: "1.8.2" + NODE_VERSION: "21" + PYTHON_VERSION: "3.10" + # Define the directory where Playwright browsers will be installed. + # Adjust if your project uses a different path. + PLAYWRIGHT_BROWSERS_PATH: "ms-playwright" + +jobs: + setup-and-test: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + shardIndex: [1, 2, 3, 4] + shardTotal: [4] + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v3 + id: setup-node + with: + node-version: ${{ env.NODE_VERSION }} + cache: "npm" + + - name: Install Node.js dependencies + run: | + cd src/frontend + npm ci + if: ${{ steps.setup-node.outputs.cache-hit != 'true' }} + + # Attempt to restore the correct Playwright browser binaries based on the + # currently installed version of Playwright (The browser binary versions + # may change with Playwright versions). + # Note: Playwright's cache directory is hard coded because that's what it + # says to do in the docs. There doesn't appear to be a command that prints + # it out for us. + # - uses: actions/cache@v4 + # id: playwright-cache + # with: + # path: ${{ env.PLAYWRIGHT_BROWSERS_PATH }} + # key: "${{ runner.os }}-playwright-${{ hashFiles('src/frontend/package-lock.json') }}" + # # As a fallback, if the Playwright version has changed, try use the + # # most recently cached version. There's a good chance that at least one + # # of the browser binary versions haven't been updated, so Playwright can + # # skip installing that in the next step. + # # Note: When falling back to an old cache, `cache-hit` (used below) + # # will be `false`. This allows us to restore the potentially out of + # # date cache, but still let Playwright decide if it needs to download + # # new binaries or not. + # restore-keys: | + # ${{ runner.os }}-playwright- + - name: Cache playwright binaries + uses: actions/cache@v4 + id: playwright-cache + with: + path: | + ~/.cache/ms-playwright + key: ${{ runner.os }}-playwright-${{ hashFiles('src/frontend/package-lock.json') }} + - name: Install Frontend dependencies + run: | + cd src/frontend + npm ci + + - name: Install Playwright's browser binaries + run: | + cd src/frontend + npx playwright install --with-deps + if: steps.playwright-cache.outputs.cache-hit != 'true' + - name: Install Playwright's dependencies + run: | + cd src/frontend + npx playwright install-deps + if: steps.playwright-cache.outputs.cache-hit != 'true' + + # If the Playwright browser binaries weren't able to be restored, we tell + # paywright to install everything for us. + # - name: Install Playwright's dependencies + # if: steps.playwright-cache.outputs.cache-hit != 'true' + # run: npx playwright install --with-deps + + - name: Install Poetry + run: pipx install "poetry==${{ env.POETRY_VERSION }}" + + - name: Set up Python + uses: actions/setup-python@v5 + id: setup-python + with: + python-version: ${{ env.PYTHON_VERSION }} + cache: "poetry" + + - name: Install Python dependencies + run: | + poetry env use ${{ env.PYTHON_VERSION }} + poetry install + if: ${{ steps.setup-python.outputs.cache-hit != 'true' }} + + - name: Run Playwright Tests + run: | + cd src/frontend + npx playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} + + - name: Upload blob report to GitHub Actions Artifacts + if: always() + uses: actions/upload-artifact@v4 + with: + name: blob-report-${{ matrix.shardIndex }} + path: src/frontend/blob-report + retention-days: 1 + + merge-reports: + needs: setup-and-test + runs-on: ubuntu-latest + if: always() + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Download blob reports from GitHub Actions Artifacts + uses: actions/download-artifact@v4 + with: + path: all-blob-reports + pattern: blob-report-* + merge-multiple: true + + - name: Merge into HTML Report + run: | + npx playwright merge-reports --reporter html ./all-blob-reports + + - name: Upload HTML report + uses: actions/upload-artifact@v4 + with: + name: html-report--attempt-${{ github.run_attempt }} + path: playwright-report + retention-days: 14 diff --git a/.gitignore b/.gitignore index 744817491..0d74c2208 100644 --- a/.gitignore +++ b/.gitignore @@ -258,5 +258,10 @@ langflow.db /tmp/* src/backend/langflow/frontend/ +src/backend/base/langflow/frontend/ .docker scratchpad* +chroma*/* +stuff/* +src/frontend/playwright-report/index.html +*.bak \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index a8229b155..962599449 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -13,10 +13,32 @@ "7860", "--reload", "--log-level", - "debug" + "debug", + "--loop", + "asyncio" ], "jinja": true, - "justMyCode": true, + "justMyCode": false, + "env": { + "LANGFLOW_LOG_LEVEL": "debug" + }, + "envFile": "${workspaceFolder}/.env" + }, + { + "name": "Debug CLI", + "type": "python", + "request": "launch", + "module": "langflow", + "args": [ + "run", + "--path", + "${workspaceFolder}/src/backend/langflow/frontend" + ], + "jinja": true, + "justMyCode": false, + "env": { + "LANGFLOW_LOG_LEVEL": "debug" + }, "envFile": "${workspaceFolder}/.env" }, { diff --git a/Makefile b/Makefile index 7f0f998ae..e5d886652 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,31 @@ .PHONY: all init format lint build build_frontend install_frontend run_frontend run_backend dev help tests coverage all: help +log_level ?= debug +host ?= 0.0.0.0 +port ?= 7860 +env ?= .env +open_browser ?= true +path = src/backend/base/langflow/frontend + +setup_poetry: + pipx install poetry + +add: + @echo 'Adding dependencies' +ifdef devel + cd src/backend/base && poetry add --group dev $(devel) +endif + +ifdef main + poetry add $(main) +endif + +ifdef base + cd src/backend/base && poetry add $(base) +endif init: - @echo 'Installing pre-commit hooks' - git config core.hooksPath .githooks - @echo 'Making pre-commit hook executable' - chmod +x .githooks/pre-commit @echo 'Installing backend dependencies' make install_backend @echo 'Installing frontend dependencies' @@ -32,12 +51,15 @@ format: lint: make install_backend - poetry run mypy src/backend/langflow + poetry run mypy --namespace-packages -p "langflow" poetry run ruff . --fix install_frontend: cd src/frontend && npm install +install_frontendci: + cd src/frontend && npm ci + install_frontendc: cd src/frontend && rm -rf node_modules package-lock.json && npm install @@ -47,22 +69,57 @@ run_frontend: tests_frontend: ifeq ($(UI), true) - cd src/frontend && ./run-tests.sh --ui + cd src/frontend && npx playwright test --ui --project=chromium else - cd src/frontend && ./run-tests.sh + cd src/frontend && npx playwright test --project=chromium endif run_cli: - poetry run langflow run --path src/frontend/build + @echo 'Running the CLI' + @make install_frontend > /dev/null + @echo 'Install backend dependencies' + @make install_backend > /dev/null + @echo 'Building the frontend' + @make build_frontend > /dev/null +ifdef env + @make start env=$(env) host=$(host) port=$(port) log_level=$(log_level) +else + @make start host=$(host) port=$(port) log_level=$(log_level) +endif run_cli_debug: - poetry run langflow run --path src/frontend/build --log-level debug + @echo 'Running the CLI in debug mode' + @make install_frontend > /dev/null + @echo 'Building the frontend' + @make build_frontend > /dev/null + @echo 'Install backend dependencies' + @make install_backend > /dev/null +ifdef env + @make start env=$(env) host=$(host) port=$(port) log_level=debug +else + @make start host=$(host) port=$(port) log_level=debug +endif + +start: + @echo 'Running the CLI' + +ifeq ($(open_browser),false) + @make install_backend && poetry run langflow run --path $(path) --log-level $(log_level) --host $(host) --port $(port) --env-file $(env) --no-open-browser +else + @make install_backend && poetry run langflow run --path $(path) --log-level $(log_level) --host $(host) --port $(port) --env-file $(env) +endif + + setup_devcontainer: make init make build_frontend poetry run langflow --path src/frontend/build +setup_env: + @sh ./scripts/setup/update_poetry.sh 1.8.2 + @sh ./scripts/setup/setup_env.sh + frontend: make install_frontend make run_frontend @@ -72,38 +129,67 @@ frontendc: make run_frontend install_backend: - poetry install --extras deploy + @echo 'Setting up the environment' + @make setup_env + @echo 'Installing backend dependencies' + @poetry install --extras deploy backend: make install_backend @-kill -9 `lsof -t -i:7860` -ifeq ($(login),1) - @echo "Running backend without autologin"; - poetry run langflow run --backend-only --port 7860 --host 0.0.0.0 --no-open-browser --env-file .env +ifdef login + @echo "Running backend autologin is $(login)"; + LANGFLOW_AUTO_LOGIN=$(login) poetry run uvicorn --factory langflow.main:create_app --host 0.0.0.0 --port 7860 --reload --env-file .env --loop asyncio else - @echo "Running backend with autologin"; - LANGFLOW_AUTO_LOGIN=True poetry run langflow run --backend-only --port 7860 --host 0.0.0.0 --no-open-browser --env-file .env + @echo "Running backend respecting the .env file"; + poetry run uvicorn --factory langflow.main:create_app --host 0.0.0.0 --port 7860 --reload --env-file .env --loop asyncio endif build_and_run: - echo 'Removing dist folder' + @echo 'Removing dist folder' + @make setup_env rm -rf dist - make build && poetry run pip install dist/*.tar.gz && poetry run langflow run + rm -rf src/backend/base/dist + make build + poetry run pip install dist/*.tar.gz + poetry run langflow run build_and_install: - echo 'Removing dist folder' + @echo 'Removing dist folder' rm -rf dist - make build && poetry run pip install dist/*.tar.gz + rm -rf src/backend/base/dist + make build && poetry run pip install dist/*.whl && pip install src/backend/base/dist/*.whl --force-reinstall build_frontend: cd src/frontend && CI='' npm run build - cp -r src/frontend/build src/backend/langflow/frontend + cp -r src/frontend/build src/backend/base/langflow/frontend build: - make install_frontend + @echo 'Building the project' + @make setup_env +ifdef base + make install_frontendci make build_frontend - poetry build --format sdist - rm -rf src/backend/langflow/frontend + make build_langflow_base +endif + +ifdef main + make build_langflow +endif + +build_langflow_base: + cd src/backend/base && poetry build + rm -rf src/backend/base/langflow/frontend + +build_langflow_backup: + poetry lock && poetry build + +build_langflow: + cd ./scripts && poetry run python update_dependencies.py + poetry lock + poetry build + mv pyproject.toml.bak pyproject.toml + mv poetry.lock.bak poetry.lock dev: make install_frontend @@ -115,10 +201,36 @@ else docker compose $(if $(debug),-f docker-compose.debug.yml) up endif -publish: - make build +lock_base: + cd src/backend/base && poetry lock + +lock_langflow: + poetry lock + +lock: +# Run both in parallel + @echo 'Locking dependencies' + cd src/backend/base && poetry lock + poetry lock + +publish_base: + make build_langflow_base + cd src/backend/base && poetry publish + +publish_langflow: + make build_langflow poetry publish +publish: + @echo 'Publishing the project' +ifdef base + -make publish_base +endif + +ifdef main + -make publish_langflow +endif + help: @echo '----' @echo 'format - run code formatters' diff --git a/README.md b/README.md index 1431194e1..b9680aa97 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ # ⛓️ Langflow ### Discover a simpler & smarter way to build around Foundation Models + # [![Langflow](https://github.com/logspace-ai/langflow/blob/dev/docs/static/img/new_langflow_demo.gif)](https://www.langflow.org) # 📦 Installation @@ -38,11 +39,9 @@ Once you’re done, you can export your flow as a JSON file. Load the flow with: ```python -from langflow import load_flow_from_json +from langflow.load import run_flow_from_json -flow = load_flow_from_json("path/to/flow.json") -# Now you can use it -flow("Hey, have you heard of Langflow?") +results = run_flow_from_json("path/to/flow.json", input_value="Hello, World!") ``` # 🖥️ Command Line Interface (CLI) diff --git a/base.Dockerfile b/base.Dockerfile index 2293c35dd..936943cd1 100644 --- a/base.Dockerfile +++ b/base.Dockerfile @@ -23,7 +23,7 @@ ENV PYTHONUNBUFFERED=1 \ \ # poetry # https://python-poetry.org/docs/configuration/#using-environment-variables - POETRY_VERSION=1.7.1 \ + POETRY_VERSION=1.8.2 \ # make poetry install to this location POETRY_HOME="/opt/poetry" \ # make poetry create the virtual environment in the project's root diff --git a/build_and_push.Dockerfile b/build_and_push.Dockerfile index f296d83aa..1c595e180 100644 --- a/build_and_push.Dockerfile +++ b/build_and_push.Dockerfile @@ -23,7 +23,7 @@ ENV PYTHONUNBUFFERED=1 \ \ # poetry # https://python-poetry.org/docs/configuration/#using-environment-variables - POETRY_VERSION=1.7.1 \ + POETRY_VERSION=1.8.2 \ # make poetry install to this location POETRY_HOME="/opt/poetry" \ # make poetry create the virtual environment in the project's root @@ -62,10 +62,14 @@ RUN apt-get update \ WORKDIR /app COPY pyproject.toml poetry.lock ./ COPY src ./src +COPY scripts ./scripts COPY Makefile ./ COPY README.md ./ -RUN curl -sSL https://install.python-poetry.org | python3 - && make build - +RUN --mount=type=cache,target=/root/.cache \ + curl -sSL https://install.python-poetry.org | python3 - +RUN python -m pip install requests && cd ./scripts && python update_dependencies.py +RUN $POETRY_HOME/bin/poetry lock +RUN $POETRY_HOME/bin/poetry build # Final stage for the application FROM python-base as final diff --git a/build_and_push_base.Dockerfile b/build_and_push_base.Dockerfile new file mode 100644 index 000000000..f5092c81c --- /dev/null +++ b/build_and_push_base.Dockerfile @@ -0,0 +1,91 @@ + + +# syntax=docker/dockerfile:1 +# Keep this syntax directive! It's used to enable Docker BuildKit + +# Based on https://github.com/python-poetry/poetry/discussions/1879?sort=top#discussioncomment-216865 +# but I try to keep it updated (see history) + +################################ +# PYTHON-BASE +# Sets up all our shared environment variables +################################ +FROM python:3.10-slim as python-base + +# python +ENV PYTHONUNBUFFERED=1 \ + # prevents python creating .pyc files + PYTHONDONTWRITEBYTECODE=1 \ + \ + # pip + PIP_DISABLE_PIP_VERSION_CHECK=on \ + PIP_DEFAULT_TIMEOUT=100 \ + \ + # poetry + # https://python-poetry.org/docs/configuration/#using-environment-variables + POETRY_VERSION=1.8.2 \ + # make poetry install to this location + POETRY_HOME="/opt/poetry" \ + # make poetry create the virtual environment in the project's root + # it gets named `.venv` + POETRY_VIRTUALENVS_IN_PROJECT=true \ + # do not ask any interactive question + POETRY_NO_INTERACTION=1 \ + \ + # paths + # this is where our requirements + virtual environment will live + PYSETUP_PATH="/opt/pysetup" \ + VENV_PATH="/opt/pysetup/.venv" + + +# prepend poetry and venv to path +ENV PATH="$POETRY_HOME/bin:$VENV_PATH/bin:$PATH" + + +################################ +# BUILDER-BASE +# Used to build deps + create our virtual environment +################################ +FROM python-base as builder-base +RUN apt-get update \ + && apt-get install --no-install-recommends -y \ + # deps for installing poetry + curl \ + # deps for building python deps + build-essential \ + # npm + npm \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +RUN --mount=type=cache,target=/root/.cache \ + curl -sSL https://install.python-poetry.org | python3 - + +# Now we need to copy the entire project into the image +COPY pyproject.toml poetry.lock ./ +COPY src/frontend/package.json /tmp/package.json +RUN cd /tmp && npm install +WORKDIR /app +COPY src/frontend ./src/frontend +RUN rm -rf src/frontend/node_modules +RUN cp -a /tmp/node_modules /app/src/frontend +COPY scripts ./scripts +COPY Makefile ./ +COPY README.md ./ +RUN cd src/frontend && npm run build +COPY src/backend ./src/backend +RUN cp -r src/frontend/build src/backend/base/langflow/frontend +RUN rm -rf src/backend/base/dist +RUN cd src/backend/base && $POETRY_HOME/bin/poetry build --format sdist + +# Final stage for the application +FROM python-base as final + +# Copy virtual environment and built .tar.gz from builder base +COPY --from=builder-base /app/src/backend/base/dist/*.tar.gz ./ + +# Install the package from the .tar.gz +RUN pip install *.tar.gz + +WORKDIR /app +CMD ["python", "-m", "langflow", "run", "--host", "0.0.0.0", "--port", "7860"] diff --git a/deploy/base.Dockerfile b/deploy/base.Dockerfile index 323663283..58fae3dab 100644 --- a/deploy/base.Dockerfile +++ b/deploy/base.Dockerfile @@ -23,7 +23,7 @@ ENV PYTHONUNBUFFERED=1 \ \ # poetry # https://python-poetry.org/docs/configuration/#using-environment-variables - POETRY_VERSION=1.5.1 \ + POETRY_VERSION=1.8.2 \ # make poetry install to this location POETRY_HOME="/opt/poetry" \ # make poetry create the virtual environment in the project's root diff --git a/docs/docs/components/custom.mdx b/docs/docs/components/custom.mdx index d8c6ff2f5..b07f953fa 100644 --- a/docs/docs/components/custom.mdx +++ b/docs/docs/components/custom.mdx @@ -70,7 +70,6 @@ The CustomComponent class serves as the foundation for creating custom component | Key | Description | | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | - | _`field_type: str`_ | The type of the field (can be any of the types supported by the _`build`_ method). | | _`is_list: bool`_ | If the field can be a list of values, meaning that the user can manually add more inputs to the same field. | | _`options: List[str]`_ | When defined, the field becomes a dropdown menu where a list of strings defines the options to be displayed. If the _`value`_ attribute is set to one of the options, that option becomes default. For this parameter to work, _`field_type`_ should invariably be _`str`_. | | _`multiline: bool`_ | Defines if a string field opens a text editor. Useful for longer texts. | @@ -78,20 +77,20 @@ The CustomComponent class serves as the foundation for creating custom component | _`display_name: str`_ | Defines the name of the field. | | _`advanced: bool`_ | Hide the field in the canvas view (displayed component settings only). Useful when a field is for advanced users. | | _`password: bool`_ | To mask the input text. Useful to hide sensitive text (e.g. API keys). | - | _`required: bool`_ | Makes the field required. | + | _`required: bool`_ | This is determined automatically but can be used to override the default behavior. | | _`info: str`_ | Adds a tooltip to the field. | | _`file_types: List[str]`_ | This is a requirement if the _`field_type`_ is _file_. Defines which file types will be accepted. For example, _json_, _yaml_ or _yml_. | | _`range_spec: langflow.field_typing.RangeSpec`_ | This is a requirement if the _`field_type`_ is _`float`_. Defines the range of values accepted and the step size. If none is defined, the default is _`[-1, 1, 0.1]`_. | | _`title_case: bool`_ | Formats the name of the field when _`display_name`_ is not defined. Set it to False to keep the name as you set it in the _`build`_ method. | + | _`refresh_button: bool`_ | If set to True a button will appear to the right of the field, and when clicked, it will call the _`update_build_config`_ method which takes in the _`build_config`_, the name of the field (_`field_name`_) and the latest value of the field (_`field_value`_). This is useful when you want to update the _`build_config`_ based on the value of the field. | + | _`real_time_refresh: bool`_ | If set to True, the _`update_build_config`_ method will be called every time the field value changes. | + | _`field_type: str`_ | You should never define this key. It is automatically set based on the type hint of the _`build`_ method. | - - - Keys _`options`_ and _`value`_ can receive a method or function that returns a list of strings or a string, respectively. This is useful when you want to dynamically generate the options or the default value of a field. A refresh button will appear next to the field in the component, allowing the user to update the options or the default value. - - - + +By using the _`update_build_config`_ method, you can update the _`build_config`_ in whatever way you want based on the value of the field or not. + - The CustomComponent class also provides helpful methods for specific tasks (e.g., to load and use other flows from the Langflow platform): diff --git a/docs/docs/components/data.mdx b/docs/docs/components/data.mdx new file mode 100644 index 000000000..94620d047 --- /dev/null +++ b/docs/docs/components/data.mdx @@ -0,0 +1,87 @@ +import Admonition from '@theme/Admonition'; + +# Data + +### API Request + +This component makes HTTP requests to the specified URLs. + +**Params** + +- **URLs:** URLs to make requests to. +- **Method:** The HTTP method to use. +- **Headers:** The headers to send with the request. +- **Body:** The body to send with the request (for POST, PATCH, PUT). +- **Timeout:** The timeout to use for the request. + + +

+ Use this component to make HTTP requests to external APIs or services and retrieve data. +

+

+ Ensure that you provide valid URLs and configure the method, headers, body, and timeout appropriately. +

+
+ +--- + +### Directory + +This component recursively loads files from a directory. + +**Params** + +- **Path:** The path to the directory. +- **Types:** File types to load. Leave empty to load all types. +- **Depth:** Depth to search for files. +- **Max Concurrency:** The maximum number of concurrent file loading operations. +- **Load Hidden:** If true, hidden files will be loaded. +- **Recursive:** If true, the search will be recursive. +- **Silent Errors:** If true, errors will not raise an exception. +- **Use Multithreading:** If true, use multithreading for loading files. + + +

+ Use this component to load files from a directory, such as text files, JSON files, etc. +

+

+ Ensure that you provide the correct path to the directory and configure other parameters as needed. +

+
+ + +--- + +### File + +This component loads a generic file. + +**Params** + +- **Path:** The path to the file. +- **Silent Errors:** If true, errors will not raise an exception. + + +

+ Use this component to load a generic file, such as a text file, JSON file, etc. +

+

+ Ensure that you provide the correct path to the file and configure other parameters as needed. +

+
+ +--- + +### URL + +This component fetches content from one or more URLs. + +**Params** + +- **URLs:** The URLs from which content will be fetched. + + +

+ Ensure that you provide valid URLs and configure other parameters as needed. +

+
diff --git a/docs/docs/components/embeddings.mdx b/docs/docs/components/embeddings.mdx index d4ad17542..9a20e5821 100644 --- a/docs/docs/components/embeddings.mdx +++ b/docs/docs/components/embeddings.mdx @@ -2,19 +2,7 @@ import Admonition from "@theme/Admonition"; # Embeddings - -

- We appreciate your understanding as we polish our documentation – it may - contain some rough edges. Share your feedback or report issues to help us - improve! 🛠️📝 -

-
- -Embeddings are vector representations of text that capture the semantic meaning of the text. They are created using text embedding models and allow us to think about the text in a vector space, enabling us to perform tasks like semantic search, where we look for pieces of text that are most similar in the vector space. - ---- - -### BedrockEmbeddings +### Amazon Bedrock Embeddings Used to load [Amazon Bedrocks’s](https://aws.amazon.com/bedrock/) embedding models. @@ -30,7 +18,7 @@ Used to load [Amazon Bedrocks’s](https://aws.amazon.com/bedrock/) embedding mo --- -### CohereEmbeddings +### Cohere Embeddings Used to load [Cohere’s](https://cohere.com/) embedding models. @@ -44,57 +32,93 @@ Used to load [Cohere’s](https://cohere.com/) embedding models. --- -### HuggingFaceEmbeddings +### Azure OpenAI Embeddings + +Generate embeddings using Azure OpenAI models. + +**Params** + +- **Azure Endpoint:** Your Azure endpoint, including the resource. Example: `https://example-resource.azure.openai.com/` +- **Deployment Name:** The name of the deployment. +- **API Version:** The API version to use. (Options: 2022-12-01, 2023-03-15-preview, 2023-05-15, 2023-06-01-preview, 2023-07-01-preview, 2023-08-01-preview) +- **API Key:** The API key to access the Azure OpenAI service. + +--- + +### Hugging Face API Embeddings + +Generate embeddings using Hugging Face Inference API models. + +**Params** + +- **API Key:** API key for accessing the Hugging Face Inference API. (Type: str) +- **API URL:** URL of the Hugging Face Inference API. (Default: http://localhost:8080) +- **Model Name:** Name of the model to use. (Default: BAAI/bge-large-en-v1.5) +- **Cache Folder:** Folder path to cache Hugging Face models. (Advanced) +- **Encode Kwargs:** Additional arguments for the encoding process. (Type: dict, Advanced) +- **Model Kwargs:** Additional arguments for the model. (Type: dict, Advanced) +- **Multi Process:** Whether to use multiple processes. (Default: False, Advanced) + +--- + +### Hugging Face Embeddings Used to load [HuggingFace’s](https://huggingface.co) embedding models. **Params** -- **cache_folder:** Used to specify the folder where the embeddings will be cached. When embeddings are computed for a text, they can be stored in the cache folder so that they can be reused later without the need to recompute them. This can improve the performance of the application by avoiding redundant computations. - -- **encode_kwargs:** Used to pass additional keyword arguments to the encoding method of the underlying HuggingFace model. These keyword arguments can be used to customize the encoding process, such as specifying the maximum length of the input sequence or enabling truncation or padding. - -- **model_kwargs:** Used to customize the behavior of the model, such as specifying the model architecture, the tokenizer, or any other model-specific configuration options. By using `model_kwargs`, the user can configure the HuggingFace model according to specific needs and preferences. - -- **model_name:** Used to specify the name or identifier of the HuggingFace model that will be used for generating embeddings. It allows users to choose a specific pre-trained model from the Hugging Face model hub — defaults to `sentence-transformers/all-mpnet-base-v2`. +- **Cache Folder:** Folder path to cache HuggingFace models. +- **Encode Kwargs:** Additional arguments for the encoding process. (Type: dict) +- **Model Kwargs:** Additional arguments for the model. (Type: dict) +- **Model Name:** Name of the HuggingFace model to use. (Default: sentence-transformers/all-mpnet-base-v2) +- **Multi Process:** Whether to use multiple processes. (Default: False) --- -### OpenAIEmbeddings +### Ollama Embeddings + +Generate embeddings using Ollama models. + +**Params** + +- **Ollama Model:** Name of the Ollama model to use. (Default: llama2) +- **Ollama Base URL:** Base URL of the Ollama API. (Default: http://localhost:11434) +- **Model Temperature:** Temperature parameter for the model. (Type: float) + +--- + +### OpenAI Embeddings Used to load [OpenAI’s](https://openai.com/) embedding models. **Params** -- **chunk_size:** Determines the maximum size of each chunk of text that is processed for embedding. If any of the incoming text chunks exceeds `chunk_size` characters, it will be split into multiple chunks of size `chunk_size` or less before being embedded — defaults to `1000`. - -- **deployment:** Used to specify the deployment name or identifier of the text embedding model. It allows the user to choose a specific deployment of the model to use for embedding. When the deployment is provided, this can be useful when the user has multiple deployments of the same model with different configurations or versions — defaults to `text-embedding-ada-002`. - -- **embedding_ctx_length:** This parameter determines the maximum context length for the text embedding model. It specifies the number of tokens that the model considers when generating embeddings for a piece of text — defaults to `8191` (this means that the model will consider up to 8191 tokens when generating embeddings). - -- **max_retries:** Determines the maximum number of times to retry a request if the model provider returns an error from their API — defaults to `6`. - -- **model:** Defines which pre-trained text embedding model to use — defaults to `text-embedding-ada-002`. - -- **openai_api_base:** Refers to the base URL for the Azure OpenAI resource. It is used to configure the API to connect to the Azure OpenAI service. The base URL can be found in the Azure portal under the user Azure OpenAI resource. - -- **openai_api_key:** Is used to authenticate and authorize access to the OpenAI service. - -- **openai_api_type:** Is used to specify the type of OpenAI API being used, either the regular OpenAI API or the Azure OpenAI API. This parameter allows the `OpenAIEmbeddings` class to connect to the appropriate API service. - -- **openai_api_version:** Is used to specify the version of the OpenAI API being used. This parameter allows the `OpenAIEmbeddings` class to connect to the appropriate version of the OpenAI API service. - -- **openai_organization:** Is used to specify the organization associated with the OpenAI API key. If not provided, the default organization associated with the API key will be used. - -- **openai_proxy:** Proxy enables better budgeting and cost management for making OpenAI API calls, including more transparency into pricing. - -- **request_timeout:** Used to specify the maximum amount of time, in milliseconds, to wait for a response from the OpenAI API when generating embeddings for a given text. - -- **tiktoken_model_name:** Used to count the number of tokens in documents to constrain them to be under a certain limit. By default, when set to None, this will be the same as the embedding model name. +- **OpenAI API Key:** The API key to use for accessing the OpenAI API. (Type: str) +- **Default Headers:** Default headers for the HTTP requests. (Type: Dict[str, str], Optional) +- **Default Query:** Default query parameters for the HTTP requests. (Type: NestedDict, Optional) +- **Allowed Special:** Special tokens allowed for processing. (Type: List[str], Default: []) +- **Disallowed Special:** Special tokens disallowed for processing. (Type: List[str], Default: ["all"]) +- **Chunk Size:** Chunk size for processing. (Type: int, Default: 1000) +- **Client:** HTTP client for making requests. (Type: Any, Optional) +- **Deployment:** Deployment name for the model. (Type: str, Default: "text-embedding-3-small") +- **Embedding Context Length:** Length of embedding context. (Type: int, Default: 8191) +- **Max Retries:** Maximum number of retries for failed requests. (Type: int, Default: 6) +- **Model:** Name of the model to use. (Type: str, Default: "text-embedding-3-small") +- **Model Kwargs:** Additional keyword arguments for the model. (Type: NestedDict, Optional) +- **OpenAI API Base:** Base URL of the OpenAI API. (Type: str, Optional) +- **OpenAI API Type:** Type of the OpenAI API. (Type: str, Optional) +- **OpenAI API Version:** Version of the OpenAI API. (Type: str, Optional) +- **OpenAI Organization:** Organization associated with the API key. (Type: str, Optional) +- **OpenAI Proxy:** Proxy server for the requests. (Type: str, Optional) +- **Request Timeout:** Timeout for the HTTP requests. (Type: float, Optional) +- **Show Progress Bar:** Whether to show a progress bar for processing. (Type: bool, Default: False) +- **Skip Empty:** Whether to skip empty inputs. (Type: bool, Default: False) +- **TikToken Enable:** Whether to enable TikToken. (Type: bool, Default: True) +- **TikToken Model Name:** Name of the TikToken model. (Type: str, Optional) --- -### VertexAIEmbeddings +### VertexAI Embeddings Wrapper around [Google Vertex AI](https://cloud.google.com/vertex-ai) [Embeddings API](https://cloud.google.com/vertex-ai/docs/generative-ai/embeddings/get-text-embeddings). @@ -113,11 +137,3 @@ Vertex AI is a cloud computing platform offered by Google Cloud Platform (GCP). - **top_p:** Tokens are selected from most probable to least until the sum of their – defaults to `0.95`. - **tuned_model_name:** The name of a tuned model. If provided, model_name is ignored. - **verbose:** This parameter is used to control the level of detail in the output of the chain. When set to True, it will print out some internal states of the chain while it is being run, which can help debug and understand the chain's behavior. If set to False, it will suppress the verbose output – defaults to `False`. - -### OllamaEmbeddings - -Used to load [Ollama’s](https://ollama.ai/) embedding models. Wrapper around LangChain's [Ollama API](https://python.langchain.com/docs/integrations/text_embedding/ollama). - -- **model** The name of the Ollama model to use – defaults to `llama2`. -- **base_url** The base URL for the Ollama API – defaults to `http://localhost:11434`. -- **temperature** Tunes the degree of randomness in text generations. Should be a non-negative value – defaults to `0`. diff --git a/docs/docs/components/experimental.mdx b/docs/docs/components/experimental.mdx new file mode 100644 index 000000000..d81f28ca3 --- /dev/null +++ b/docs/docs/components/experimental.mdx @@ -0,0 +1,250 @@ +import Admonition from '@theme/Admonition'; + +# Experimental + +Experimental are components that are currently in a beta phase. This means they have undergone initial development and testing but have not yet reached a stable or fully supported status. Users are encouraged to explore these components, provide feedback, and report any issues encountered during their usage. + +### Clear Message History Component + +This component is designed to clear the message history associated with a specific session ID. + +**Beta:** This component is currently in beta. + +**Parameters** + +- **Session ID:** + - **Display Name:** Session ID + - **Info:** The session ID to clear the message history. + +**Usage** + +To use this component, provide the session ID for which you want to clear the message history. + +--- + +### Extract Key From Record + +This component extracts specified keys from a record. + +**Parameters** + +- **Record:** + - **Display Name:** Record + - **Info:** The record from which to extract the keys. + +- **Keys:** + - **Display Name:** Keys + - **Info:** The keys to extract from the record. + +- **Silent Errors:** + - **Display Name:** Silent Errors + - **Info:** If True, errors will not be raised. + - **Advanced:** True + +**Usage** + +To use this component, provide the record from which you want to extract keys, specify the keys to extract, and optionally set whether to raise errors for missing keys. + +--- + +### Flow as Tool + +This component constructs a Tool from a function that runs the loaded Flow. + +**Parameters** + +- **Flow Name:** + - **Display Name:** Flow Name + - **Info:** The name of the flow to run. + - **Options:** List of available flow names. + - **Real-time Refresh:** True + - **Refresh Button:** True + +- **Name:** + - **Display Name:** Name + - **Description:** The name of the tool. + +- **Description:** + - **Display Name:** Description + - **Description:** The description of the tool. + +- **Return Direct:** + - **Display Name:** Return Direct + - **Description:** Return the result directly from the Tool. + - **Advanced:** True + +**Usage** + +To use this component, select the desired flow from the available options, provide a name and description for the tool, and specify whether to return the result directly from the tool. + +--- + +### Listen + +This component listens for a notification. + +**Parameters** + +- **Name:** + - **Display Name:** Name + - **Info:** The name of the notification to listen for. + +**Usage** + +To use this component, specify the name of the notification to listen for. + +--- + +### List Flows + +This component lists all available flows. + +**Usage** + +To use this component, simply call it without any parameters. + +--- + +### Merge Records + +**Parameters** + +- **Records:** + - **Display Name:** Records + +**Usage** + +To use this component, provide a list of records to merge. + +--- + +### Notify + +This component generates a notification to the Get Notified component. + +**Parameters** + +- **Name:** + - **Display Name:** Name + - **Info:** The name of the notification. + +- **Record:** + - **Display Name:** Record + - **Info:** The record to store. + +- **Append:** + - **Display Name:** Append + - **Info:** If True, the record will be appended to the notification. + +**Usage** + +To use this component, specify the name of the notification, provide an optional record to store, and indicate whether to append the record to the notification. + +--- + +### Run Flow + +This component runs a flow. + +**Parameters** + +- **Input Value:** + - **Display Name:** Input Value + - **Multiline:** True + +- **Flow Name:** + - **Display Name:** Flow Name + - **Info:** The name of the flow to run. + - **Options:** List of available flow names. + - **Refresh Button:** True + +- **Tweaks:** + - **Display Name:** Tweaks + - **Info:** Tweaks to apply to the flow. + +**Usage** + +To use this component, provide the input value, specify the flow name to run, and optionally provide tweaks to apply to the flow. + +--- + +### Runnable Executor + +This component executes a runnable. + +**Parameters** + +- **Input Key:** + - **Display Name:** Input Key + - **Info:** The key to use for the input. + +- **Inputs:** + - **Display Name:** Inputs + - **Info:** The inputs to pass to the runnable. + +- **Runnable:** + - **Display Name:** Runnable + - **Info:** The runnable to execute. + +- **Output Key:** + - **Display Name:** Output Key + - **Info:** The key to use for the output. + +**Usage** + +To use this component, specify the input key, provide the inputs to pass to the runnable, select the runnable to execute, and optionally specify the output key. + +--- + +### SQL Executor + + This component executes an SQL query. + +**Parameters** + +- **Database URL:** + - **Display Name:** Database URL + - **Info:** The URL of the database. + +- **Include Columns:** + - **Display Name:** Include Columns + - **Info:** Include columns in the result. + +- **Passthrough:** + - **Display Name:** Passthrough + - **Info:** If an error occurs, return the query instead of raising an exception. + +- **Add Error:** + - **Display Name:** Add Error + - **Info:** Add the error to the result. + +**Usage** + +To use this component, provide the SQL query, specify the database URL, and optionally configure include columns, passthrough, and add error settings. + +--- + +### SubFlow + +This component dynamically generates a component from a flow. The output is a list of records with keys 'result' and 'message'. + +**Parameters** + +- **Input Value:** + - **Display Name:** Input Value + - **Multiline:** True + +- **Flow Name:** + - **Display Name:** Flow Name + - **Info:** The name of the flow to run. + - **Options:** List of available flow names. + - **Real Time Refresh:** True + - **Refresh Button:** True + +- **Tweaks:** + - **Display Name:** Tweaks + - **Info:** Tweaks to apply to the flow. + +**Usage** + +To use this component, specify the flow name and provide any necessary tweaks to apply to the flow. diff --git a/docs/docs/components/helpers.mdx b/docs/docs/components/helpers.mdx new file mode 100644 index 000000000..d965761aa --- /dev/null +++ b/docs/docs/components/helpers.mdx @@ -0,0 +1,127 @@ +import Admonition from '@theme/Admonition'; + +# Helpers + +### Chat Memory + +This component retrieves stored chat messages given a specific Session ID. + +**Params** + +- **Sender Type:** Choose the sender type from options like "Machine", "User", or "Machine and User". +- **Sender Name:** (Optional) The name of the sender. +- **Number of Messages:** Number of messages to retrieve. +- **Session ID:** The Session ID of the chat history. +- **Order:** Choose the order of the messages, either "Ascending" or "Descending". +- **Record Template:** (Optional) Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key. + +--- + +### Combine Text + +This component concatenates two text sources into a single text chunk using a specified delimiter. + +**Params** + +- **First Text:** The first text input to concatenate. +- **Second Text:** The second text input to concatenate. +- **Delimiter:** A string used to separate the two text inputs. Defaults to a whitespace. + +--- + +### Create Record + +This component dynamically creates a Record with a specified number of fields. + +**Params** + +- **Number of Fields:** Number of fields to be added to the record. +- **Text Key:** Key to be used as text. + +--- + +### Custom Component + +Use this component as a template to create your own custom component. + +**Params** + +- **Parameter:** Describe the purpose of this parameter. + + +

+ Customize the build_config and build methods according to your requirements. +

+
+ +Learn more about [Custom Component](http://docs.langflow.org/components/custom). + +--- + +### Documents to Records + +Convert LangChain Documents into Records. + +**Parameters** + +- **Documents:** Documents to be converted into Records. + +--- + +### ID Generator + +Generates a unique ID. + +**Parameters** + +- **Value:** Unique ID generated. + +--- + +### Message History + +Retrieves stored chat messages given a specific Session ID. + +**Parameters** + +- **Sender Type:** Options for the sender type. +- **Sender Name:** Sender name. +- **Number of Messages:** Number of messages to retrieve. +- **Session ID:** Session ID of the chat history. +- **Order:** Order of the messages. + +--- + +### Records to Text + +Convert Records into plain text following a specified template. + +**Parameters** + +- **Records:** The records to convert to text. +- **Template:** The template to use for formatting the records. It can contain the keys `{text}`, `{data}` or any other key in the Record. + +--- + +### Split Text + +Split text into chunks of a specified length. + +**Parameters** + +- **Texts:** Texts to split. +- **Separators:** The characters to split on. Defaults to [" "]. +- **Max Chunk Size:** The maximum length (in number of characters) of each chunk. +- **Chunk Overlap:** The amount of character overlap between chunks. +- **Recursive:** Whether to split recursively. + +--- + +### Update Record + +Update Record with text-based key/value pairs, similar to updating a Python dictionary. + +**Parameters** + +- **Record:** The record to update. +- **New Data:** The new data to update the record with. diff --git a/docs/docs/components/inputs.mdx b/docs/docs/components/inputs.mdx new file mode 100644 index 000000000..fe8804e43 --- /dev/null +++ b/docs/docs/components/inputs.mdx @@ -0,0 +1,164 @@ +import Admonition from "@theme/Admonition"; +import ZoomableImage from "/src/theme/ZoomableImage.js"; + +# Inputs + +### Chat Input + +This component is designed to get user input from the chat. + +**Params** + +- **Sender Type:** specifies the sender type. Defaults to _`"User"`_. Options are _`"Machine"`_ and _`"User"`_. + +- **Sender Name:** specifies the name of the sender. Defaults to _`"User"`_. + +- **Message:** specifies the message text. It is a multiline text input. + +- **Session ID:** specifies the session ID of the chat history. If provided, the message will be saved in the Message History. + + +

+ If _`As Record`_ is _`true`_ and the _`Message`_ is a _`Record`_, the data + of the _`Record`_ will be updated with the _`Sender`_, _`Sender Name`_, and + _`Session ID`_. +

+
+ +When you get it from the sidebar, it will look like the image below but that is because some fields are in the advanced section. + + + +If you expose all its fields, it will look like the image below. + + + +One key capability of the Chat Input component is how it transforms the Interaction Panel into a chat window. This feature is particularly useful for scenarios where user input is required to initiate or influence the flow. + + + +--- + +### Prompt + +Create a prompt template with dynamic variables. This is a very useful component for structuring prompts and passing dynamic data to a language model. + +**Parameters** + +- **Template:** the template for the prompt. This field allows you to create other fields dynamically by using curly brackets `{}`. For example, if you have a template like this: _`"Hello {name}, how are you?"`_, a new field called _`name`_ will be created. + + +

+ Prompt variables can be created with any chosen name inside curly brackets, + e.g. `{variable_name}` +

+
+ +Here is how it looks when you get it from the sidebar. + + + +And here when you add a Template with the value _`Hello {name}, how are you?`_. + + + +--- + +### Text Input + +This component is designed for simple text input, allowing users to pass textual data to subsequent components in the workflow. It's particularly useful for scenarios where a brief user input is required to initiate or influence the flow. + +**Params** + +- **Value:** Specifies the text input value. This is where the user can input the text data that will be passed to the next component in the sequence. If no value is provided, it defaults to an empty string. +- **Record Template:** Specifies how a Record should be converted into Text. + + +

+ The `TextInput` component serves as a straightforward means for setting Text + input values in the chat window. It ensures that textual data can be + seamlessly passed to subsequent components in the flow. +

+
+ +It should look like this when dropped directly from the sidebar. + + + +And when you expose all its fields, it will look like the image below. + +The **Record Template** field is used to specify how a Record should be converted into Text. This is particularly useful when you want to extract specific information from a Record and pass it as text to the next component in the sequence. + +For example, if you have a Record with the following structure: + +```json +{ + "name": "John Doe", + "age": 30, + "email": "johndoe@email.com" +} +``` + +You can use a template like this: _`"Name: {name}, Age: {age}"`_ to convert the Record into a text string like this: _`"Name: John Doe, Age: 30"`_, and if you pass more than one Record, the text will be concatenated with a new line separator. + + + +The Text Input component gives you the possibility to add an Input field on the Interaction Panel. This is useful because it allows you to define parameters while running and testing your flow. + + diff --git a/docs/docs/components/memories.mdx b/docs/docs/components/memories.mdx index 3bf9a957c..b92538134 100644 --- a/docs/docs/components/memories.mdx +++ b/docs/docs/components/memories.mdx @@ -12,6 +12,26 @@ Memory is a concept in chat-based applications that allows the system to remembe --- +### MessageHistory + +This component is designed to retrieve stored messages based on various filters such as sender type, sender name, session ID, and a specific file path where messages are stored. It allows for a flexible retrieval of chat history, providing insights into past interactions. + +**Params** + +- **Sender Type:** (Optional) Specifies the type of the sender. Options are _`"Machine"`_, _`"User"`_, or _`"Machine and User"`_. Filters the messages by the type of the sender. + +- **Sender Name:** (Optional) Specifies the name of the sender. Filters the messages by the name of the sender. + +- **Session ID:** (Optional) Specifies the session ID of the chat history. Filters the messages belonging to a specific session. + +- **Number of Messages:** Specifies the number of messages to retrieve. Defaults to _`5`_. Determines how many recent messages from the chat history to fetch. + + +

+ The component retrieves messages based on the provided criteria, including the specific file path for stored messages. If no specific criteria are provided, it will return the most recent messages up to the specified limit. This component can be used to review past interactions and analyze the flow of conversations. +

+
+ ### ConversationBufferMemory The `ConversationBufferMemory` component is a type of memory system that plainly stores the last few inputs and outputs of a conversation. @@ -27,7 +47,7 @@ The `ConversationBufferMemory` component is a type of memory system that plainly ### ConversationBufferWindowMemory -`ConversationBufferWindowMemory` is a variation of the `ConversationBufferMemory` that maintains a list of the recent interactions in a conversation. It only keeps the last K interactions in memory, which can be useful for maintaining a sliding window of the most recent interactions without letting the buffer get too large. +`ConversationBufferWindowMemory` is a variation of the `ConversationBufferMemory` that maintains a list of the recent interactions in a conversation. It only keeps the last K interactions in memory, which can be useful for maintaining a sliding window of the most recent interactions without letting the buffer get too large. **Params** @@ -72,7 +92,7 @@ The `ConversationEntityMemory` component incorporates intricate memory structure ### ConversationSummaryMemory -The `ConversationSummaryMemory` is a memory component that creates a summary of the conversation over time. It condenses information from the conversation and stores the current summary in memory. It is particularly useful for longer conversations where keeping the entire message history in the prompt would take up too many tokens. +The `ConversationSummaryMemory` is a memory component that creates a summary of the conversation over time. It condenses information from the conversation and stores the current summary in memory. It is particularly useful for longer conversations where keeping the entire message history in the prompt would take up too many tokens. **Params** diff --git a/docs/docs/components/llms.mdx b/docs/docs/components/model_specs.mdx similarity index 100% rename from docs/docs/components/llms.mdx rename to docs/docs/components/model_specs.mdx diff --git a/docs/docs/components/models.mdx b/docs/docs/components/models.mdx new file mode 100644 index 000000000..1c3b404b5 --- /dev/null +++ b/docs/docs/components/models.mdx @@ -0,0 +1,346 @@ +import Admonition from '@theme/Admonition'; + +# Models + +### Amazon Bedrock + +This component facilitates the generation of text using the LLM (Large Language Model) model from Amazon Bedrock. + +**Params** + +- **Input Value:** Specifies the input text for text generation. + +- **System Message (Optional):** A system message to pass to the model. + +- **Model ID (Optional):** Specifies the model ID to be used for text generation. Defaults to _`"anthropic.claude-instant-v1"`_. Available options include: + - _`"ai21.j2-grande-instruct"`_ + - _`"ai21.j2-jumbo-instruct"`_ + - _`"ai21.j2-mid"`_ + - _`"ai21.j2-mid-v1"`_ + - _`"ai21.j2-ultra"`_ + - _`"ai21.j2-ultra-v1"`_ + - _`"anthropic.claude-instant-v1"`_ + - _`"anthropic.claude-v1"`_ + - _`"anthropic.claude-v2"`_ + - _`"cohere.command-text-v14"`_ + +- **Credentials Profile Name (Optional):** Specifies the name of the credentials profile. + +- **Region Name (Optional):** Specifies the region name. + +- **Model Kwargs (Optional):** Additional keyword arguments for the model. + +- **Endpoint URL (Optional):** Specifies the endpoint URL. + +- **Streaming (Optional):** Specifies whether to stream the response from the model. Defaults to _`False`_. + +- **Cache (Optional):** Specifies whether to cache the response. + +- **Stream (Optional):** Specifies whether to stream the response from the model. Defaults to _`False`_. + + +

+ Ensure that necessary credentials are provided to connect to the Amazon Bedrock API. If connection fails, a ValueError will be raised. +

+
+ + +--- + +### Anthropic + +This component allows the generation of text using Anthropic Chat&Completion large language models. + +**Params** + +- **Model Name:** Specifies the name of the Anthropic model to be used for text generation. Available options include: + - _`"claude-2.1"`_ + - _`"claude-2.0"`_ + - _`"claude-instant-1.2"`_ + - _`"claude-instant-1"`_ + +- **Anthropic API Key:** Your Anthropic API key. + +- **Max Tokens (Optional):** Specifies the maximum number of tokens to generate. Defaults to _`256`_. + +- **Temperature (Optional):** Specifies the sampling temperature. Defaults to _`0.7`_. + +- **API Endpoint (Optional):** Specifies the endpoint of the Anthropic API. Defaults to _`"https://api.anthropic.com"`_ if not specified. + +- **Input Value:** Specifies the input text for text generation. + +- **Stream (Optional):** Specifies whether to stream the response from the model. Defaults to _`False`_. + +- **System Message (Optional):** A system message to pass to the model. + +For detailed documentation and integration guides, please refer to the [Anthropic Component Documentation](https://python.langchain.com/docs/integrations/chat/anthropic). + +--- + +### Azure OpenAI + +This component allows the generation of text using the LLM (Large Language Model) model from Azure OpenAI. + +**Params** + +- **Model Name:** Specifies the name of the Azure OpenAI model to be used for text generation. Available options include: + - _`"gpt-35-turbo"`_ + - _`"gpt-35-turbo-16k"`_ + - _`"gpt-35-turbo-instruct"`_ + - _`"gpt-4"`_ + - _`"gpt-4-32k"`_ + - _`"gpt-4-vision"`_ + +- **Azure Endpoint:** Your Azure endpoint, including the resource. Example: `https://example-resource.azure.openai.com/`. + +- **Deployment Name:** Specifies the name of the deployment. + +- **API Version:** Specifies the version of the Azure OpenAI API to be used. Available options include: + - _`"2023-03-15-preview"`_ + - _`"2023-05-15"`_ + - _`"2023-06-01-preview"`_ + - _`"2023-07-01-preview"`_ + - _`"2023-08-01-preview"`_ + - _`"2023-09-01-preview"`_ + - _`"2023-12-01-preview"`_ + +- **API Key:** Your Azure OpenAI API key. + +- **Temperature (Optional):** Specifies the sampling temperature. Defaults to _`0.7`_. + +- **Max Tokens (Optional):** Specifies the maximum number of tokens to generate. Defaults to _`1000`_. + +- **Input Value:** Specifies the input text for text generation. + +- **Stream (Optional):** Specifies whether to stream the response from the model. Defaults to _`False`_. + +- **System Message (Optional):** A system message to pass to the model. + +For detailed documentation and integration guides, please refer to the [Azure OpenAI Component Documentation](https://python.langchain.com/docs/integrations/llms/azure_openai). + + +--- + +### Cohere + +This component enables text generation using Cohere large language models. + +**Params** + +- **Cohere API Key:** Your Cohere API key. + +- **Max Tokens (Optional):** Specifies the maximum number of tokens to generate. Defaults to _`256`_. + +- **Temperature (Optional):** Specifies the sampling temperature. Defaults to _`0.75`_. + +- **Input Value:** Specifies the input text for text generation. + +- **Stream (Optional):** Specifies whether to stream the response from the model. Defaults to _`False`_. + +- **System Message (Optional):** A system message to pass to the model. + +--- + +### Google Generative AI + +This component enables text generation using Google Generative AI. + +**Params** + +- **Google API Key:** Your Google API key to use for the Google Generative AI. + +- **Model:** The name of the model to use. Supported examples are _`"gemini-pro"`_ and _`"gemini-pro-vision"`_. + +- **Max Output Tokens (Optional):** The maximum number of tokens to generate. + +- **Temperature:** Run inference with this temperature. Must be in the closed interval [0.0, 1.0]. + +- **Top K (Optional):** Decode using top-k sampling: consider the set of top_k most probable tokens. Must be positive. + +- **Top P (Optional):** The maximum cumulative probability of tokens to consider when sampling. + +- **N (Optional):** Number of chat completions to generate for each prompt. Note that the API may not return the full n completions if duplicates are generated. + +- **Input Value:** The input to the model. + +- **Stream (Optional):** Specifies whether to stream the response from the model. Defaults to _`False`_. + +- **System Message (Optional):** A system message to pass to the model. + +--- + +### Hugging Face API + +This component facilitates text generation using LLM models from the Hugging Face Inference API. + +**Params** + +- **Endpoint URL:** The URL of the Hugging Face Inference API endpoint. Should be provided along with necessary authentication credentials. + +- **Task:** Specifies the task for text generation. Options include _`"text2text-generation"`_, _`"text-generation"`_, and _`"summarization"`_. + +- **API Token:** The API token required for authentication with the Hugging Face Hub. + +- **Model Keyword Arguments (Optional):** Additional keyword arguments for the model. Should be provided as a Python dictionary. + +- **Input Value:** The input text for text generation. + +- **Stream (Optional):** Specifies whether to stream the response from the model. Defaults to _`False`_. + +- **System Message (Optional):** A system message to pass to the model. + +--- + +### LiteLLM Model + +Generates text using the `LiteLLM` collection of large language models. + +**Parameters** + +- **Model name:** The name of the model to use. For example, `gpt-3.5-turbo`. (Type: str) +- **API key:** The API key to use for accessing the provider's API. (Type: str, Optional) +- **Provider:** The provider of the API key. (Type: str, Choices: "OpenAI", "Azure", "Anthropic", "Replicate", "Cohere", "OpenRouter") +- **Temperature:** Controls the randomness of the text generation. (Type: float, Default: 0.7) +- **Model kwargs:** Additional keyword arguments for the model. (Type: Dict, Optional) +- **Top p:** Filter responses to keep the cumulative probability within the top p tokens. (Type: float, Optional) +- **Top k:** Filter responses to only include the top k tokens. (Type: int, Optional) +- **N:** Number of chat completions to generate for each prompt. (Type: int, Default: 1) +- **Max tokens:** The maximum number of tokens to generate for each chat completion. (Type: int, Default: 256) +- **Max retries:** Maximum number of retries for failed requests. (Type: int, Default: 6) +- **Verbose:** Whether to print verbose output. (Type: bool, Default: False) +- **Input:** The input prompt for text generation. (Type: str) +- **Stream:** Whether to stream the output. (Type: bool, Default: False) +- **System message:** System message to pass to the model. (Type: str, Optional) + +--- + +### Ollama + +Generate text using Ollama Local LLMs. + +**Parameters** + +- **Base URL:** Endpoint of the Ollama API. Defaults to 'http://localhost:11434' if not specified. +- **Model Name:** The model name to use. Refer to [Ollama Library](https://ollama.ai/library) for more models. +- **Temperature:** Controls the creativity of model responses. (Default: 0.8) +- **Cache:** Enable or disable caching. (Default: False) +- **Format:** Specify the format of the output (e.g., json). (Advanced) +- **Metadata:** Metadata to add to the run trace. (Advanced) +- **Mirostat:** Enable/disable Mirostat sampling for controlling perplexity. (Default: Disabled) +- **Mirostat Eta:** Learning rate for Mirostat algorithm. (Default: None) (Advanced) +- **Mirostat Tau:** Controls the balance between coherence and diversity of the output. (Default: None) (Advanced) +- **Context Window Size:** Size of the context window for generating tokens. (Default: None) (Advanced) +- **Number of GPUs:** Number of GPUs to use for computation. (Default: None) (Advanced) +- **Number of Threads:** Number of threads to use during computation. (Default: None) (Advanced) +- **Repeat Last N:** How far back the model looks to prevent repetition. (Default: None) (Advanced) +- **Repeat Penalty:** Penalty for repetitions in generated text. (Default: None) (Advanced) +- **TFS Z:** Tail free sampling value. (Default: None) (Advanced) +- **Timeout:** Timeout for the request stream. (Default: None) (Advanced) +- **Top K:** Limits token selection to top K. (Default: None) (Advanced) +- **Top P:** Works together with top-k. (Default: None) (Advanced) +- **Verbose:** Whether to print out response text. +- **Tags:** Tags to add to the run trace. (Advanced) +- **Stop Tokens:** List of tokens to signal the model to stop generating text. (Advanced) +- **System:** System to use for generating text. (Advanced) +- **Template:** Template to use for generating text. (Advanced) +- **Input:** The input text. +- **Stream:** Whether to stream the response. +- **System Message:** System message to pass to the model. (Advanced) + +--- + +### OpenAI + +This component facilitates text generation using OpenAI's models. + +**Params** + +- **Input Value:** The input text for text generation. + +- **Max Tokens (Optional):** The maximum number of tokens to generate. Defaults to _`256`_. + +- **Model Kwargs (Optional):** Additional keyword arguments for the model. Should be provided as a nested dictionary. + +- **Model Name (Optional):** The name of the model to use. Defaults to _`gpt-4-1106-preview`_. Supported options include: _`gpt-4-turbo-preview`_, _`gpt-4-0125-preview`_, _`gpt-4-1106-preview`_, _`gpt-4-vision-preview`_, _`gpt-3.5-turbo-0125`_, _`gpt-3.5-turbo-1106`_. + +- **OpenAI API Base (Optional):** The base URL of the OpenAI API. Defaults to _`https://api.openai.com/v1`_. + +- **OpenAI API Key (Optional):** The API key for accessing the OpenAI API. + +- **Temperature:** Controls the creativity of model responses. Defaults to _`0.7`_. + +- **Stream (Optional):** Specifies whether to stream the response from the model. Defaults to _`False`_. + +- **System Message (Optional):** System message to pass to the model. + +--- + +### Qianfan + +This component facilitates the generation of text using Baidu Qianfan chat models. + +**Params** + +- **Model Name:** Specifies the name of the Qianfan chat model to be used for text generation. Available options include: + - _`"ERNIE-Bot"`_ + - _`"ERNIE-Bot-turbo"`_ + - _`"BLOOMZ-7B"`_ + - _`"Llama-2-7b-chat"`_ + - _`"Llama-2-13b-chat"`_ + - _`"Llama-2-70b-chat"`_ + - _`"Qianfan-BLOOMZ-7B-compressed"`_ + - _`"Qianfan-Chinese-Llama-2-7B"`_ + - _`"ChatGLM2-6B-32K"`_ + - _`"AquilaChat-7B"`_ + +- **Qianfan Ak:** Your Baidu Qianfan access key, obtainable from [here](https://cloud.baidu.com/product/wenxinworkshop). + +- **Qianfan Sk:** Your Baidu Qianfan secret key, obtainable from [here](https://cloud.baidu.com/product/wenxinworkshop). + +- **Top p (Optional):** Model parameter. Specifies the top-p value. Only supported in ERNIE-Bot and ERNIE-Bot-turbo models. Defaults to _`0.8`_. + +- **Temperature (Optional):** Model parameter. Specifies the sampling temperature. Only supported in ERNIE-Bot and ERNIE-Bot-turbo models. Defaults to _`0.95`_. + +- **Penalty Score (Optional):** Model parameter. Specifies the penalty score. Only supported in ERNIE-Bot and ERNIE-Bot-turbo models. Defaults to _`1.0`_. + +- **Endpoint (Optional):** Endpoint of the Qianfan LLM, required if custom model is used. + +- **Input Value:** Specifies the input text for text generation. + +- **Stream (Optional):** Specifies whether to stream the response from the model. Defaults to _`False`_. + +- **System Message (Optional):** A system message to pass to the model. + +--- + +### Vertex AI + +The `ChatVertexAI` is a component for generating text using Vertex AI Chat large language models API. + +**Params** + +- **Credentials:** The JSON file containing the credentials for accessing the Vertex AI Chat API. + +- **Project:** The name of the project associated with the Vertex AI Chat API. + +- **Examples (Optional):** List of examples to provide context for text generation. + +- **Location:** The location of the Vertex AI Chat API service. Defaults to _`us-central1`_. + +- **Max Output Tokens:** The maximum number of tokens to generate. Defaults to _`128`_. + +- **Model Name:** The name of the model to use. Defaults to _`chat-bison`_. + +- **Temperature:** Controls the creativity of model responses. Defaults to _`0.0`_. + +- **Input Value:** The input text for text generation. + +- **Top K:** Limits token selection to top K. Defaults to _`40`_. + +- **Top P:** Works together with top-k. Defaults to _`0.95`_. + +- **Verbose:** Whether to print out response text. Defaults to _`False`_. + +- **Stream (Optional):** Specifies whether to stream the response from the model. Defaults to _`False`_. + +- **System Message (Optional):** System message to pass to the model. \ No newline at end of file diff --git a/docs/docs/components/outputs.mdx b/docs/docs/components/outputs.mdx new file mode 100644 index 000000000..6fe3f9d2a --- /dev/null +++ b/docs/docs/components/outputs.mdx @@ -0,0 +1,37 @@ +import Admonition from '@theme/Admonition'; + +# Outputs + +### Chat Output + +This component is designed to send a message to the chat. + +**Params** + +- **Sender Type:** specifies the sender type. Defaults to _`"Machine"`_. Options are _`"Machine"`_ and _`"User"`_. + +- **Sender Name:** specifies the name of the sender. Defaults to _`"AI"`_. + +- **Session ID:** specifies the session ID of the chat history. If provided, the message will be saved in the Message History. + +- **Message:** specifies the message text. + + +

+ If _`As Record`_ is _`true`_ and the _`Message`_ is a _`Record`_, the data of the _`Record`_ will be updated with the _`Sender`_, _`Sender Name`_, and _`Session ID`_. +

+
+ +### Text Output + +This component is designed to display text data to the user. It's particularly useful for scenarios where you don't want to send the text data to the chat, but still want to display it. + +**Params** + +- **Value:** Specifies the text data to be displayed. This is where the text data to be displayed is provided. If no value is provided, it defaults to an empty string. + + +

+ The `TextOutput` component serves as a straightforward means for displaying text data. It ensures that textual data can be seamlessly observed in the chat window throughout your flow. +

+
\ No newline at end of file diff --git a/docs/docs/components/prompts.mdx b/docs/docs/components/prompts.mdx index 3aafc9b96..0b1ad705c 100644 --- a/docs/docs/components/prompts.mdx +++ b/docs/docs/components/prompts.mdx @@ -21,7 +21,7 @@ The `PromptTemplate` component allows users to create prompts and define variabl Once a variable is defined in the prompt template, it becomes a component input of its own. Check out [Prompt - Customization](../docs/guidelines/prompt-customization.mdx) to learn more. + Customization](../guidelines/prompt-customization) to learn more. - **template:** Template used to format an individual request. diff --git a/docs/docs/components/utilities.mdx b/docs/docs/components/utilities.mdx index 593864213..e8c2ba216 100644 --- a/docs/docs/components/utilities.mdx +++ b/docs/docs/components/utilities.mdx @@ -74,3 +74,23 @@ Build a Document containing a JSON object using a key and another Document page **Output** - **List of Documents:** A list containing the Document with the JSON object. + +## Unique ID Generator + +Generates a unique identifier (UUID) for each instance it is invoked, providing a distinct and reliable identifier suitable for a variety of applications. + +**Params** + +- **Value:** This field displays the generated unique identifier (UUID). The UUID is generated dynamically for each instance of the component, ensuring uniqueness across different uses. + +**Output** + +- Returns a unique identifier (UUID) as a string. This UUID is generated using Python's `uuid` module, ensuring that each identifier is unique and can be used as a reliable reference in your application. + + +

+ The Unique ID Generator is crucial for scenarios requiring distinct identifiers, such as session management, transaction tracking, or any context where different instances or entities must be uniquely identified. The generated UUID is provided as a hexadecimal string, offering a high level of uniqueness and security for identification purposes. +

+
+ +For additional information and examples, please consult the [Langflow Components Custom Documentation](http://docs.langflow.org/components/custom). diff --git a/docs/docs/components/vector-stores.mdx b/docs/docs/components/vector-stores.mdx index 133984cda..103d755b4 100644 --- a/docs/docs/components/vector-stores.mdx +++ b/docs/docs/components/vector-stores.mdx @@ -1,9 +1,635 @@ -import Admonition from '@theme/Admonition'; +import Admonition from "@theme/Admonition"; # Vector Stores - +### Astra DB + +The `Astra DB` is a component for initializing an Astra DB Vector Store from Records. It facilitates the creation of Astra DB-based vector indexes for efficient document storage and retrieval. + +**Params** + +- **Input:** The input documents or records. + +- **Embedding:** The embedding model used by Astra DB. + +- **Collection Name:** The name of the collection in Astra DB. + +- **Token:** The token for Astra DB. + +- **API Endpoint:** The API endpoint for Astra DB. + +- **Namespace:** The namespace in Astra DB. + +- **Metric:** The metric to use in Astra DB. + +- **Batch Size:** The batch size for Astra DB. + +- **Bulk Insert Batch Concurrency:** The bulk insert batch concurrency for Astra DB. + +- **Bulk Insert Overwrite Concurrency:** The bulk insert overwrite concurrency for Astra DB. + +- **Bulk Delete Concurrency:** The bulk delete concurrency for Astra DB. + +- **Setup Mode:** The setup mode for the vector store. + +- **Pre Delete Collection:** Pre delete collection. + +- **Metadata Indexing Include:** Metadata indexing include. + +- **Metadata Indexing Exclude:** Metadata indexing exclude. + +- **Collection Indexing Policy:** Collection indexing policy. + +

- We appreciate your understanding as we polish our documentation – it may contain some rough edges. Share your feedback or report issues to help us improve! 🛠️📝 + Ensure that the required Astra DB token and API endpoint are properly configured.

-
\ No newline at end of file + +
+ +--- + +### Astra DB Search + +The `Astra DBSearch` is a component for searching an existing Astra DB Vector Store for similar documents. It extends the functionality of the `Astra DB` component to provide efficient document retrieval based on similarity metrics. + +**Params** + +- **Search Type:** The type of search to perform (e.g., Similarity, MMR). + +- **Input Value:** The input value to search for. + +- **Embedding:** The embedding model used by Astra DB. + +- **Collection Name:** The name of the collection in Astra DB. + +- **Token:** The token for Astra DB. + +- **API Endpoint:** The API endpoint for Astra DB. + +- **Namespace:** The namespace in Astra DB. + +- **Metric:** The metric to use in Astra DB. + +- **Batch Size:** The batch size for Astra DB. + +- **Bulk Insert Batch Concurrency:** The bulk insert batch concurrency for Astra DB. + +- **Bulk Insert Overwrite Concurrency:** The bulk insert overwrite concurrency for Astra DB. + +- **Bulk Delete Concurrency:** The bulk delete concurrency for Astra DB. + +- **Setup Mode:** The setup mode for the vector store. + +- **Pre Delete Collection:** Pre delete collection. + +- **Metadata Indexing Include:** Metadata indexing include. + +- **Metadata Indexing Exclude:** Metadata indexing exclude. + +- **Collection Indexing Policy:** Collection indexing policy. + +--- + +### Chroma + +The `Chroma` is a component designed for implementing a Vector Store using Chroma. This component allows users to utilize Chroma for efficient vector storage and retrieval within their language processing workflows. + +**Params** + +- **Collection Name:** The name of the collection. + +- **Persist Directory:** The directory to persist the Vector Store to. + +- **Server CORS Allow Origins (Optional):** The CORS allow origins for the Chroma server. + +- **Server Host (Optional):** The host for the Chroma server. + +- **Server Port (Optional):** The port for the Chroma server. + +- **Server gRPC Port (Optional):** The gRPC port for the Chroma server. + +- **Server SSL Enabled (Optional):** Whether to enable SSL for the Chroma server. + +- **Input:** Input data for creating the Vector Store. + +- **Embedding:** The embeddings to use for the Vector Store. + +For detailed documentation and integration guides, please refer to the [Chroma Component Documentation](https://python.langchain.com/docs/integrations/vectorstores/chroma). + +--- + +### Chroma Search + +The `ChromaSearch` is a component designed for searching a Chroma collection for similar documents. This component integrates with Chroma to facilitate efficient document retrieval based on similarity metrics. + +**Params** + +- **Input:** The input text to search for similar documents. + +- **Search Type:** The type of search to perform ("Similarity" or "MMR"). + +- **Collection Name:** The name of the Chroma collection. + +- **Index Directory:** The directory where the Chroma index is stored. + +- **Embedding:** The embedding model used to vectorize inputs (make sure to use the same as the index). + +- **Server CORS Allow Origins (Optional):** The CORS allow origins for the Chroma server. + +- **Server Host (Optional):** The host for the Chroma server. + +- **Server Port (Optional):** The port for the Chroma server. + +- **Server gRPC Port (Optional):** The gRPC port for the Chroma server. + +- **Server SSL Enabled (Optional):** Whether SSL is enabled for the Chroma server. + +--- + +### FAISS + +The `FAISS` is a component designed for ingesting documents into a FAISS Vector Store. It facilitates efficient document indexing and retrieval using the FAISS library. + +**Params** + +- **Embedding:** The embedding model used to vectorize inputs. + +- **Input:** The input documents to ingest into the FAISS Vector Store. + +- **Folder Path:** The path to save the FAISS index. It will be relative to where Langflow is running. + +- **Index Name:** The name of the FAISS index. + +For detailed documentation and integration guides, please refer to the [FAISS Component Documentation](https://faiss.ai/index.html). + +--- + +### FAISS Search + +The `FAISSSearch` is a component for searching a FAISS Vector Store for similar documents. It enables efficient document retrieval based on similarity metrics using FAISS. + +**Params** + +- **Embedding:** The embedding model used by the FAISS Vector Store. + +- **Folder Path:** The path from which to load the FAISS index. It will be relative to where Langflow is running. + +- **Input:** The input value to search for similar documents. + +- **Index Name:** The name of the FAISS index. + +--- + +### MongoDB Atlas + +The `MongoDBAtlas` is a component used to construct a MongoDB Atlas Vector Search vector store from Records. It facilitates the creation of MongoDB Atlas-based vector stores for efficient document storage and retrieval. + +**Params** + +- **Embedding:** The embedding model used by the MongoDB Atlas Vector Search. + +- **Input:** The input documents or records. + +- **Collection Name:** The name of the collection in the MongoDB Atlas database. + +- **Database Name:** The name of the database in MongoDB Atlas. + +- **Index Name:** The name of the index in MongoDB Atlas. + +- **MongoDB Atlas Cluster URI:** The URI of the MongoDB Atlas cluster. + +- **Search Kwargs:** Additional search arguments for MongoDB Atlas. + + +

Ensure that pymongo is installed to use MongoDB Atlas Vector Store.

+
+ +--- + +### MongoDB Atlas Search + +The `MongoDBAtlasSearch` is a component for searching a MongoDB Atlas Vector Store for similar documents. It extends the functionality of the MongoDBAtlasComponent to provide efficient document retrieval based on similarity metrics. + +**Params** + +- **Search Type:** The type of search to perform. Options: "Similarity", "MMR". + +- **Input:** The input value to search for. + +- **Embedding:** The embedding model used by the MongoDB Atlas Vector Store. + +- **Collection Name:** The name of the collection in the MongoDB Atlas database. + +- **Database Name:** The name of the database in MongoDB Atlas. + +- **Index Name:** The name of the index in MongoDB Atlas. + +- **MongoDB Atlas Cluster URI:** The URI of the MongoDB Atlas cluster. + +- **Search Kwargs:** Additional search arguments for MongoDB Atlas. + +--- + +### PGVector + +The `PGVector` is a component for implementing a Vector Store using PostgreSQL. It allows users to store and retrieve vectors efficiently within a PostgreSQL database. + +**Params** + +- **Input:** The input value to use for the Vector Store. + +- **Embedding:** The embedding model used by the Vector Store. + +- **PostgreSQL Server Connection String:** The URL for the PostgreSQL server. + +- **Table:** The name of the table in the PostgreSQL database. + +For detailed documentation and integration guides, please refer to the [PGVector Component Documentation](https://python.langchain.com/docs/integrations/vectorstores/pgvector). + + +

+ Ensure that the required PostgreSQL server is accessible and properly + configured. +

+
+ +--- + +### PGVector Search + +The `PGVectorSearch` is a component for searching a PGVector Store for similar documents. It extends the functionality of the PGVectorComponent to provide efficient document retrieval based on similarity metrics. + +**Params** + +- **Input:** The input value to search for. + +- **Embedding:** The embedding model used by the Vector Store. + +- **PostgreSQL Server Connection String:** The URL for the PostgreSQL server. + +- **Table:** The name of the table in the PostgreSQL database. + +- **Search Type:** The type of search to perform (e.g., "Similarity", "MMR"). + +--- + +### Pinecone + +The `Pinecone` is a component used to construct a Pinecone wrapper from Records. It facilitates the creation of Pinecone-based vector indexes for efficient document storage and retrieval. + +**Params** + +- **Input:** The input documents or records. + +- **Embedding:** The embedding model used by Pinecone. + +- **Index Name:** The name of the index in Pinecone. + +- **Namespace:** The namespace in Pinecone. + +- **Pinecone API Key:** The API key for Pinecone. + +- **Pinecone Environment:** The environment for Pinecone. + +- **Search Kwargs:** Additional search keyword arguments for Pinecone. + +- **Pool Threads:** The number of threads to use for Pinecone. + + +

+ Ensure that the required Pinecone API key and environment are properly + configured. +

+
+ +--- + +### Pinecone Search + +The `PineconeSearch` is a component used to search a Pinecone Vector Store for similar documents. It extends the functionality of the `PineconeComponent` to provide efficient document retrieval based on similarity metrics. + +**Params** + +- **Search Type:** The type of search to perform (e.g., Similarity, MMR). + +- **Input Value:** The input value to search for. + +- **Embedding:** The embedding model used by Pinecone. + +- **Index Name:** The name of the index in Pinecone. + +- **Namespace:** The namespace in Pinecone. + +- **Pinecone API Key:** The API key for Pinecone. + +- **Pinecone Environment:** The environment for Pinecone. + +- **Search Kwargs:** Additional search keyword arguments for Pinecone. + +- **Pool Threads:** The number of threads to use for Pinecone. + +--- + +### Qdrant + +The `Qdrant` is a component used to construct a Qdrant wrapper from a list of texts. It allows for efficient similarity search and retrieval operations based on the provided embeddings. + +**Params** + +- **Input:** The input documents or records. + +- **Embedding:** The embedding model used by Qdrant. + +- **API Key:** The API key for Qdrant (password field). + +- **Collection Name:** The name of the collection in Qdrant. + +- **Content Payload Key:** The key for the content payload in the documents (advanced). + +- **Distance Function:** The distance function to use in Qdrant (advanced). + +- **gRPC Port:** The gRPC port for Qdrant (advanced). + +- **Host:** The host for Qdrant (advanced). + +- **HTTPS:** Enable HTTPS for Qdrant (advanced). + +- **Location:** The location for Qdrant (advanced). + +- **Metadata Payload Key:** The key for the metadata payload in the documents (advanced). + +- **Path:** The path for Qdrant (advanced). + +- **Port:** The port for Qdrant (advanced). + +- **Prefer gRPC:** Prefer gRPC for Qdrant (advanced). + +- **Prefix:** The prefix for Qdrant (advanced). + +- **Search Kwargs:** Additional search keyword arguments for Qdrant (advanced). + +- **Timeout:** The timeout for Qdrant (advanced). + +- **URL:** The URL for Qdrant (advanced). + +--- + +### Qdrant Search + +The `QdrantSearch` is a component used to search a Qdrant Vector Store for similar documents. It extends the functionality of the `QdrantComponent` to provide efficient document retrieval based on similarity metrics. + +**Params** + +- **Search Type:** The type of search to perform (e.g., Similarity, MMR). + +- **Input Value:** The input value to search for. + +- **Embedding:** The embedding model used by Qdrant. + +- **API Key:** The API key for Qdrant (password field). + +- **Collection Name:** The name of the collection in Qdrant. + +- **Content Payload Key:** The key for the content payload in the documents (advanced). + +- **Distance Function:** The distance function to use in Qdrant (advanced). + +- **gRPC Port:** The gRPC port for Qdrant (advanced). + +- **Host:** The host for Qdrant (advanced). + +- **HTTPS:** Enable HTTPS for Qdrant (advanced). + +- **Location:** The location for Qdrant (advanced). + +- **Metadata Payload Key:** The key for the metadata payload in the documents (advanced). + +- **Path:** The path for Qdrant (advanced). + +- **Port:** The port for Qdrant (advanced). + +- **Prefer gRPC:** Prefer gRPC for Qdrant (advanced). + +- **Prefix:** The prefix for Qdrant (advanced). + +- **Search Kwargs:** Additional search keyword arguments for Qdrant (advanced). + +- **Timeout:** The timeout for Qdrant (advanced). + +- **URL:** The URL for Qdrant (advanced). + +--- + +### Redis + +The `Redis` is a component for implementing a Vector Store using Redis. It provides functionality to store and retrieve vectors efficiently from a Redis database. + +**Params** + +- **Index Name:** The name of the index in Redis (default: your_index). + +- **Input:** The input data to build the Redis Vector Store (input types: Document, Record). + +- **Embedding:** The embedding model used by Redis. + +- **Schema:** The schema file (.yaml) to define the structure of the documents (optional). + +- **Redis Server Connection String:** The connection string for the Redis server. + +- **Redis Index:** The name of the Redis index (optional). + +For detailed documentation, please refer to the [Redis Documentation](https://python.langchain.com/docs/integrations/vectorstores/redis). + + +

+ Ensure that the required Redis server connection URL and index name are + properly configured. If no documents are provided, a schema must be + provided. +

+
+ +--- + +### Redis Search + +The `RedisSearch` is a component for searching a Redis Vector Store for similar documents. + +**Params** + +- **Search Type:** The type of search to perform (e.g., Similarity, MMR). + +- **Input Value:** The input value to search for. + +- **Index Name:** The name of the index in Redis (default: your_index). + +- **Embedding:** The embedding model used by Redis. + +- **Schema:** The schema file (.yaml) to define the structure of the documents (optional). + +- **Redis Server Connection String:** The connection string for the Redis server. + +- **Redis Index:** The name of the Redis index (optional). + +--- + +### Supabase + +The `Supabase` is a component for initializing a Supabase Vector Store from texts and embeddings. + +**Params** + +- **Input:** The input documents or records. + +- **Embedding:** The embedding model used by Supabase. + +- **Query Name:** The name of the query (optional). + +- **Search Kwargs:** Additional search keyword arguments for Supabase (advanced). + +- **Supabase Service Key:** The service key for Supabase. + +- **Supabase URL:** The URL for the Supabase instance. + +- **Table Name:** The name of the table in Supabase (advanced). + + +

+ Ensure that the required Supabase service key, Supabase URL, and table name + are properly configured. +

+
+ +--- + +### Supabase Search + +The `SupabaseSearch` is a component for searching a Supabase Vector Store for similar documents. + +**Params** + +- **Search Type:** The type of search to perform (e.g., Similarity, MMR). + +- **Input Value:** The input value to search for. + +- **Embedding:** The embedding model used by Supabase. + +- **Query Name:** The name of the query (optional). + +- **Search Kwargs:** Additional search keyword arguments for Supabase (advanced). + +- **Supabase Service Key:** The service key for Supabase. + +- **Supabase URL:** The URL for the Supabase instance. + +- **Table Name:** The name of the table in Supabase (advanced). + +--- + +### Vectara + +The `Vectara` is a component for implementing a Vector Store using Vectara. + +**Params** + +- **Vectara Customer ID:** The customer ID for Vectara. + +- **Vectara Corpus ID:** The corpus ID for Vectara. + +- **Vectara API Key:** The API key for Vectara. + +- **Files Url:** The URL(s) of the file(s) to be used for initializing the Vectara Vector Store (optional). + +- **Input:** The input data to be upserted to the corpus (optional). + +For detailed documentation and integration guides, please refer to the [Vectara Component Documentation](https://python.langchain.com/docs/integrations/vectorstores/vectara). + + +

+ If `inputs` are provided, they will be upserted to the corpus. If + `files_url` are provided, Vectara will process the files from the URLs. +

+
+ +--- + +### Vectara Search + +The `VectaraSearch` is a component for searching a Vectara Vector Store for similar documents. + +**Params** + +- **Search Type:** The type of search to perform (e.g., Similarity, MMR). + +- **Input Value:** The input value to search for. + +- **Vectara Customer ID:** The customer ID for Vectara. + +- **Vectara Corpus ID:** The corpus ID for Vectara. + +- **Vectara API Key:** The API key for Vectara. + +- **Files Url:** The URL(s) of the file(s) to be used for initializing the Vectara Vector Store (optional). + +--- + +### Weaviate + +The `Weaviate` is a component for implementing a Vector Store using Weaviate. + +**Params** + +- **Weaviate URL:** The URL of the Weaviate instance (default: http://localhost:8080). + +- **Search By Text:** Boolean indicating whether to search by text (default: False). + +- **API Key:** The API key for authentication (optional). + +- **Index name:** The name of the index in Weaviate (optional). + +- **Text Key:** The key used to extract text from documents (default: "text"). + +- **Input:** The input document or record. + +- **Embedding:** The embedding model used by Weaviate. + +- **Attributes:** Additional attributes to consider during indexing (optional). + +For detailed documentation and integration guides, please refer to the [Weaviate Component Documentation](https://python.langchain.com/docs/integrations/vectorstores/weaviate). + + +

+ Before using the Weaviate Vector Store component, ensure that you have a + Weaviate instance running and accessible at the specified URL. Additionally, + make sure to provide the correct API key for authentication if required. + Adjust the index name, text key, and attributes according to your dataset + and indexing requirements. Finally, ensure that the provided embeddings are + compatible with Weaviate's requirements. +

+
+ +--- + +### Weaviate Search + +The `WeaviateSearch` component facilitates searching a Weaviate Vector Store for similar documents. + +**Params** + +- **Search Type:** The type of search to perform (e.g., Similarity, MMR). + +- **Input Value:** The input value to search for. + +- **Weaviate URL:** The URL of the Weaviate instance (default: http://localhost:8080). + +- **Search By Text:** Boolean indicating whether to search by text (default: False). + +- **API Key:** The API key for authentication (optional). + +- **Index name:** The name of the index in Weaviate (optional). + +- **Text Key:** The key used to extract text from documents (default: "text"). + +- **Embedding:** The embedding model used by Weaviate. + +- **Attributes:** Additional attributes to consider during indexing (optional). diff --git a/docs/docs/components/wrappers.mdx b/docs/docs/components/wrappers.mdx deleted file mode 100644 index 4b1251b60..000000000 --- a/docs/docs/components/wrappers.mdx +++ /dev/null @@ -1,20 +0,0 @@ -import Admonition from '@theme/Admonition'; - -# Wrappers - - -

- We appreciate your understanding as we polish our documentation – it may contain some rough edges. Share your feedback or report issues to help us improve! 🛠️📝 -

-
- - -### TextRequestsWrapper - -This component is designed to work with the Python Requests module, which is a popular tool for making web requests. Used to fetch data from a particular website. - -**Params** - -- **header:** specifies the headers to be included in the HTTP request. Defaults to `{'Authorization': 'Bearer '}`. - - Headers are key-value pairs that provide additional information about the request or the client making the request. They can be used to send authentication credentials, specify the content type of the request, set cookies, and more. They allow the client and the server to communicate additional information beyond the basic request. \ No newline at end of file diff --git a/docs/docs/examples/buffer-memory.mdx b/docs/docs/examples/buffer-memory.mdx index 3167081a5..b196f9031 100644 --- a/docs/docs/examples/buffer-memory.mdx +++ b/docs/docs/examples/buffer-memory.mdx @@ -16,6 +16,12 @@ import ZoomableImage from "/src/theme/ZoomableImage.js"; light: "img/buffer-memory.png", dark: "img/buffer-memory.png", }} + style={{ + width: "80%", + margin: "20px auto", + display: "flex", + justifyContent: "center", + }} /> #### Download Flow diff --git a/docs/docs/examples/conversation-chain.mdx b/docs/docs/examples/conversation-chain.mdx index 1cd59ca55..294d1b440 100644 --- a/docs/docs/examples/conversation-chain.mdx +++ b/docs/docs/examples/conversation-chain.mdx @@ -22,6 +22,13 @@ import ZoomableImage from "/src/theme/ZoomableImage.js"; light: "img/basic-chat.png", dark: "img/basic-chat.png", }} + +style={{ + width: "80%", + margin: "20px auto", + display: "flex", + justifyContent: "center", + }} /> #### Download Flow diff --git a/docs/docs/examples/csv-loader.mdx b/docs/docs/examples/csv-loader.mdx index 351e99440..25f3bb444 100644 --- a/docs/docs/examples/csv-loader.mdx +++ b/docs/docs/examples/csv-loader.mdx @@ -34,6 +34,12 @@ import ZoomableImage from "/src/theme/ZoomableImage.js"; light: "img/csv-loader.png", dark: "img/csv-loader.png", }} + style={{ + width: "80%", + margin: "20px auto", + display: "flex", + justifyContent: "center", + }} /> #### Download Flow diff --git a/docs/docs/examples/flow-runner.mdx b/docs/docs/examples/flow-runner.mdx index e20dc39f7..8a07adb0a 100644 --- a/docs/docs/examples/flow-runner.mdx +++ b/docs/docs/examples/flow-runner.mdx @@ -3,9 +3,6 @@ description: Custom Components hide_table_of_contents: true --- -import ZoomableImage from "/src/theme/ZoomableImage.js"; -import Admonition from "@theme/Admonition"; - # FlowRunner Component The CustomComponent class allows us to create components that interact with Langflow itself. In this example, we will make a component that runs other flows available in "My Collection". @@ -18,7 +15,7 @@ The CustomComponent class allows us to create components that interact with Lang }} style={{ width: "30%", - margin: "0 auto", + margin: "20px auto", display: "flex", justifyContent: "center", }} @@ -35,7 +32,7 @@ We will cover how to: Example Code ```python -from langflow import CustomComponent +from langflow.custom import CustomComponent from langchain.schema import Document class FlowRunner(CustomComponent): @@ -75,7 +72,7 @@ class FlowRunner(CustomComponent): ```python -from langflow import CustomComponent +from langflow.custom import CustomComponent class MyComponent(CustomComponent): @@ -95,7 +92,7 @@ The typical structure of a Custom Component is composed of _`display_name`_ and --- ```python -from langflow import CustomComponent +from langflow.custom import CustomComponent # focus @@ -118,7 +115,7 @@ Let's start by defining our component's _`display_name`_ and _`description`_. --- ```python -from langflow import CustomComponent +from langflow.custom import CustomComponent # focus from langchain.schema import Document @@ -140,7 +137,7 @@ Second, we will import _`Document`_ from the [_langchain.schema_](https://docs.l --- ```python -from langflow import CustomComponent +from langflow.custom import CustomComponent # focus from langchain.schema import Document @@ -167,7 +164,7 @@ Now, let's add the [parameters](focus://11[20:55]) and the [return type](focus:/ --- ```python focus=13:14 -from langflow import CustomComponent +from langflow.custom import CustomComponent from langchain.schema import Document @@ -189,7 +186,7 @@ We can now start writing the _`build`_ method. Let's list available flows in "My --- ```python focus=15:18 -from langflow import CustomComponent +from langflow.custom import CustomComponent from langchain.schema import Document @@ -222,7 +219,7 @@ And retrieve a flow that matches the selected name (we'll make a dropdown input --- ```python -from langflow import CustomComponent +from langflow.custom import CustomComponent from langchain.schema import Document @@ -250,7 +247,7 @@ You can load this flow using _`get_flow`_ and set a _`tweaks`_ dictionary to cus --- ```python -from langflow import CustomComponent +from langflow.custom import CustomComponent from langchain.schema import Document @@ -287,7 +284,7 @@ The content of a document can be extracted using the _`page_content`_ attribute, --- ```python focus=9:16 -from langflow import CustomComponent +from langflow.custom import CustomComponent from langchain.schema import Document @@ -366,3 +363,6 @@ Done! This is what our script and custom component looks like: /> + +import ZoomableImage from "/src/theme/ZoomableImage.js"; +import Admonition from "@theme/Admonition"; diff --git a/docs/docs/examples/how-upload-examples.mdx b/docs/docs/examples/how-upload-examples.mdx deleted file mode 100644 index 4f54558eb..000000000 --- a/docs/docs/examples/how-upload-examples.mdx +++ /dev/null @@ -1,28 +0,0 @@ -import ThemedImage from "@theme/ThemedImage"; -import useBaseUrl from "@docusaurus/useBaseUrl"; -import ZoomableImage from "/src/theme/ZoomableImage.js"; - -# 📚 How to Upload Examples? - -We welcome all examples that can help our community learn and explore Langflow's capabilities. -Langflow Examples is a repository on [GitHub](https://github.com/logspace-ai/langflow_examples) that contains examples of flows that people can use for inspiration and learning. - -{" "} - - -To upload examples, please follow these steps: - -1. **Create a Flow:** First, create a flow using Langflow. You can use any of the available templates or create a new flow from scratch. - -2. **Export the Flow:** Once you have created a flow, export it as a JSON file. Make sure to give your file a descriptive name and include a brief description of what it does. - -3. **Submit a Pull Request:** Finally, submit a pull request (PR) to the examples repo. Make sure to include your JSON file in the PR. - -If your example uses any third-party libraries or packages, please include them in your PR and make sure that your example follows the [**⛓️ Langflow Code Of Conduct**](https://github.com/logspace-ai/langflow/blob/dev/CODE_OF_CONDUCT.md). diff --git a/docs/docs/examples/midjourney-prompt-chain.mdx b/docs/docs/examples/midjourney-prompt-chain.mdx deleted file mode 100644 index 9df732026..000000000 --- a/docs/docs/examples/midjourney-prompt-chain.mdx +++ /dev/null @@ -1,46 +0,0 @@ -import Admonition from "@theme/Admonition"; - -# MidJourney Prompt Chain - -The `MidJourneyPromptChain` can be used to generate imaginative and detailed MidJourney prompts. - -For example, type something like: - -```bash -Dragon -``` - -And get a response such as: - -```text -Imagine a mysterious forest, the trees are tall and ancient, their branches reaching up to the sky. Through the darkness, a dragon emerges from the shadows, its scales shimmering in the moonlight. Its wingspan is immense, and its eyes glow with a fierce intensity. It is a majestic and powerful creature, one that commands both respect and fear. -``` - - - Notice that the `ConversationSummaryMemory` stores a summary of the - conversation over time. Try using it to create better prompts as the - conversation goes on. - - -## ⛓️ Langflow Example - -import ThemedImage from "@theme/ThemedImage"; -import useBaseUrl from "@docusaurus/useBaseUrl"; -import ZoomableImage from "/src/theme/ZoomableImage.js"; - - - -#### Download Flow - - - -- [`OpenAI`](https://python.langchain.com/docs/modules/model_io/models/llms/integrations/openai) -- [`ConversationSummaryMemory`](https://python.langchain.com/docs/modules/memory/types/summary) - - diff --git a/docs/docs/examples/multiple-vectorstores.mdx b/docs/docs/examples/multiple-vectorstores.mdx deleted file mode 100644 index 2e554bbf1..000000000 --- a/docs/docs/examples/multiple-vectorstores.mdx +++ /dev/null @@ -1,58 +0,0 @@ -import Admonition from "@theme/Admonition"; - -# Multiple Vector Stores - -The example below shows an agent operating with two vector stores built upon different data sources. - -The `TextLoader` loads a TXT file, while the `WebBaseLoader` pulls text from webpages into a document format to accessed downstream. The `Chroma` vector stores are created analogous to what we have demonstrated in our [CSV Loader](/examples/csv-loader.mdx) example. Finally, the `VectorStoreRouterAgent` constructs an agent that routes between the vector stores. - - - Get the TXT file used - [here](https://github.com/hwchase17/chat-your-data/blob/master/state_of_the_union.txt). - - -URL used by the `WebBaseLoader`: - -```text -https://pt.wikipedia.org/wiki/Harry_Potter -``` - - - When you build the flow, request information about one of the sources. The - agent should be able to use the correct source to generate a response. - - - - Learn more about Multiple Vector Stores - [here](https://python.langchain.com/docs/modules/data_connection/vectorstores/). - - -## ⛓️ Langflow Example - -import ThemedImage from "@theme/ThemedImage"; -import useBaseUrl from "@docusaurus/useBaseUrl"; -import ZoomableImage from "/src/theme/ZoomableImage.js"; - - - -#### Download Flow - - - -- [`WebBaseLoader`](https://python.langchain.com/docs/integrations/document_loaders/web_base) -- [`TextLoader`](https://python.langchain.com/docs/modules/data_connection/document_loaders/) -- [`CharacterTextSplitter`](https://python.langchain.com/docs/modules/data_connection/document_transformers/text_splitters/character_text_splitter) -- [`OpenAIEmbedding`](https://python.langchain.com/docs/integrations/text_embedding/openai) -- [`Chroma`](https://python.langchain.com/docs/integrations/vectorstores/chroma) -- [`VectorStoreInfo`](https://python.langchain.com/docs/modules/data_connection/vectorstores/) -- [`OpenAI`](https://python.langchain.com/docs/modules/model_io/models/llms/integrations/openai) -- [`VectorStoreRouterToolkit`](https://js.langchain.com/docs/modules/agents/tools/how_to/agents_with_vectorstores) -- [`VectorStoreRouterAgent`](https://js.langchain.com/docs/modules/agents/tools/how_to/agents_with_vectorstores) - - diff --git a/docs/docs/examples/python-function.mdx b/docs/docs/examples/python-function.mdx index 9eadd7273..2bb4b93e1 100644 --- a/docs/docs/examples/python-function.mdx +++ b/docs/docs/examples/python-function.mdx @@ -43,6 +43,12 @@ import ZoomableImage from "/src/theme/ZoomableImage.js"; light: "img/python-function.png", dark: "img/python-function.png", }} + style={{ + width: "80%", + margin: "20px auto", + display: "flex", + justifyContent: "center", + }} /> #### Download Flow diff --git a/docs/docs/examples/serp-api-tool.mdx b/docs/docs/examples/serp-api-tool.mdx index 7e8d95936..175b6f1be 100644 --- a/docs/docs/examples/serp-api-tool.mdx +++ b/docs/docs/examples/serp-api-tool.mdx @@ -37,6 +37,12 @@ import ZoomableImage from "/src/theme/ZoomableImage.js"; light: "img/serp-api-tool.png", dark: "img/serp-api-tool.png", }} + style={{ + width: "80%", + margin: "20px auto", + display: "flex", + justifyContent: "center", + }} /> #### Download Flow diff --git a/src/backend/langflow/components/agents/__init__.py b/docs/docs/getting-started/basic-prompting.mdx similarity index 100% rename from src/backend/langflow/components/agents/__init__.py rename to docs/docs/getting-started/basic-prompting.mdx diff --git a/src/backend/langflow/components/chains/__init__.py b/docs/docs/getting-started/blog-writer.mdx similarity index 100% rename from src/backend/langflow/components/chains/__init__.py rename to docs/docs/getting-started/blog-writer.mdx diff --git a/docs/docs/getting-started/cli.mdx b/docs/docs/getting-started/cli.mdx new file mode 100644 index 000000000..050c4ab50 --- /dev/null +++ b/docs/docs/getting-started/cli.mdx @@ -0,0 +1,44 @@ +# 🖥️ Command Line Interface (CLI) + + +## Overview + +Langflow's Command Line Interface (CLI) is a powerful tool that allows you to interact with the Langflow server from the command line. The CLI provides a wide range of commands to help you shape Langflow to your needs. + +Running the CLI without any arguments will display a list of available commands and options. + +```bash +langflow --help +# or +langflow +``` + +Each option is detailed below: + +- `--help`: Displays all available options. +- `--host`: Defines the host to bind the server to. Can be set using the `LANGFLOW_HOST` environment variable. The default is `127.0.0.1`. +- `--workers`: Sets the number of worker processes. Can be set using the `LANGFLOW_WORKERS` environment variable. The default is `1`. +- `--timeout`: Sets the worker timeout in seconds. The default is `60`. +- `--port`: Sets the port to listen on. Can be set using the `LANGFLOW_PORT` environment variable. The default is `7860`. +- `--config`: Defines the path to the configuration file. The default is `config.yaml`. +- `--env-file`: Specifies the path to the .env file containing environment variables. The default is `.env`. +- `--log-level`: Defines the logging level. Can be set using the `LANGFLOW_LOG_LEVEL` environment variable. The default is `critical`. +- `--components-path`: Specifies the path to the directory containing custom components. Can be set using the `LANGFLOW_COMPONENTS_PATH` environment variable. The default is `langflow/components`. +- `--log-file`: Specifies the path to the log file. Can be set using the `LANGFLOW_LOG_FILE` environment variable. The default is `logs/langflow.log`. +- `--cache`: Select the type of cache to use. Options are `InMemoryCache` and `SQLiteCache`. Can be set using the `LANGFLOW_LANGCHAIN_CACHE` environment variable. The default is `SQLiteCache`. +- `--dev/--no-dev`: Toggles the development mode. The default is `no-dev`. +- `--path`: Specifies the path to the frontend directory containing build files. This option is for development purposes only. Can be set using the `LANGFLOW_FRONTEND_PATH` environment variable. +- `--open-browser/--no-open-browser`: Toggles the option to open the browser after starting the server. Can be set using the `LANGFLOW_OPEN_BROWSER` environment variable. The default is `open-browser`. +- `--remove-api-keys/--no-remove-api-keys`: Toggles the option to remove API keys from the projects saved in the database. Can be set using the `LANGFLOW_REMOVE_API_KEYS` environment variable. The default is `no-remove-api-keys`. +- `--install-completion [bash|zsh|fish|powershell|pwsh]`: Installs completion for the specified shell. +- `--show-completion [bash|zsh|fish|powershell|pwsh]`: Shows completion for the specified shell, allowing you to copy it or customize the installation. +- `--backend-only`: This parameter, with a default value of `False`, allows running only the backend server without the frontend. It can also be set using the `LANGFLOW_BACKEND_ONLY` environment variable. +- `--store`: This parameter, with a default value of `True`, enables the store features, use `--no-store` to deactivate it. It can be configured using the `LANGFLOW_STORE` environment variable. + +These parameters are important for users who need to customize the behavior of Langflow, especially in development or specialized deployment scenarios. + +### Environment Variables + +You can configure many of the CLI options using environment variables. These can be exported in your operating system or added to a `.env` file and loaded using the `--env-file` option. + +A sample `.env` file named `.env.example` is included with the project. Copy this file to a new file named `.env` and replace the example values with your actual settings. If you're setting values in both your OS and the `.env` file, the `.env` settings will take precedence. diff --git a/docs/docs/getting-started/creating-flows.mdx b/docs/docs/getting-started/creating-flows.mdx deleted file mode 100644 index aecc3ea16..000000000 --- a/docs/docs/getting-started/creating-flows.mdx +++ /dev/null @@ -1,38 +0,0 @@ -import ThemedImage from "@theme/ThemedImage"; -import useBaseUrl from "@docusaurus/useBaseUrl"; -import ZoomableImage from "/src/theme/ZoomableImage.js"; -import ReactPlayer from "react-player"; - -# 🎨 Creating Flows - -## Compose - -Creating flows with Langflow is easy. Drag sidebar components onto the canvas and connect them together to create your pipeline. Langflow provides a range of [LangChain components](https://python.langchain.com/docs/modules/) to choose from, including LLMs, prompt serializers, agents, and chains. - - - -## Fork - -The easiest way to start with Langflow is by forking a **community example**. Forking an example stores a copy in your project collection, allowing you to edit and save the modified version as a new flow. - -
- -
- -## Build - -Building a flow means validating if the components have prerequisites fulfilled and are properly instantiated. When a chat message is sent, the flow will run for the first time, executing the pipeline. - -
- -
diff --git a/src/backend/langflow/components/custom_components/__init__.py b/docs/docs/getting-started/document-qa.mdx similarity index 100% rename from src/backend/langflow/components/custom_components/__init__.py rename to docs/docs/getting-started/document-qa.mdx diff --git a/docs/docs/getting-started/hugging-face-spaces.mdx b/docs/docs/getting-started/hugging-face-spaces.mdx deleted file mode 100644 index 4759ea398..000000000 --- a/docs/docs/getting-started/hugging-face-spaces.mdx +++ /dev/null @@ -1,20 +0,0 @@ -# 🤗 HuggingFace Spaces - -A fully featured version of Langflow can be accessed via HuggingFace spaces with no installation required. - -import ThemedImage from "@theme/ThemedImage"; -import useBaseUrl from "@docusaurus/useBaseUrl"; -import ZoomableImage from "/src/theme/ZoomableImage.js"; - -{" "} - - - -Check out Langflow on [HuggingFace Spaces](https://huggingface.co/spaces/Logspace/Langflow). diff --git a/docs/docs/getting-started/installation.md b/docs/docs/getting-started/installation.md deleted file mode 100644 index c3ad54239..000000000 --- a/docs/docs/getting-started/installation.md +++ /dev/null @@ -1,15 +0,0 @@ -# 📦 How to install? - -## Installation - -You can install Langflow from pip: - -```bash -pip install langflow -``` - -Next, run: - -```bash -langflow -``` \ No newline at end of file diff --git a/src/backend/langflow/components/documentloaders/__init__.py b/docs/docs/getting-started/memory-chatbot.mdx similarity index 100% rename from src/backend/langflow/components/documentloaders/__init__.py rename to docs/docs/getting-started/memory-chatbot.mdx diff --git a/docs/docs/getting-started/rag-with-astradb.mdx b/docs/docs/getting-started/rag-with-astradb.mdx new file mode 100644 index 000000000..01daa7b6f --- /dev/null +++ b/docs/docs/getting-started/rag-with-astradb.mdx @@ -0,0 +1,195 @@ +import ThemedImage from "@theme/ThemedImage"; +import useBaseUrl from "@docusaurus/useBaseUrl"; +import ZoomableImage from "/src/theme/ZoomableImage.js"; +import Admonition from "@theme/Admonition"; + +# 🌟 RAG with Astra DB + +This guide will walk you through how to build a RAG (Retrieval Augmented Generation) application using **Astra DB** and **Langflow**. + +[Astra DB](https://www.datastax.com/products/datastax-astra?utm_source=langflow-pre-release&utm_medium=referral&utm_campaign=langflow-announcement&utm_content=astradb) is a cloud-native database built on Apache Cassandra that is optimized for the cloud. It is a fully managed database-as-a-service that simplifies operations and reduces costs. Astra DB is built on the same technology that powers the largest Cassandra deployments in the world. + +In this guide, we will use Astra DB as a vector store to store and retrieve the documents that will be used by the RAG application to generate responses. + + + This guide assumes that you have Langflow up and running. If you are new to + Langflow, you can check out the [Getting Started](/) guide. + + +TLDR; + +- [Create a free Astra DB account](https://astra.datastax.com/signup?utm_source=langflow-pre-release&utm_medium=referral&utm_campaign=langflow-announcement&utm_content=create-a-free-astra-db-account) +- Duplicate our [Langflow 1.0 Space](https://huggingface.co/spaces/Langflow/Langflow-Preview?duplicate=true) +- Create a new database, get a **Token** and the **API Endpoint** +- Click on the **New Project** button and look for Vector Store RAG. This will create a new project with the necessary components +- Import the project into Langflow by dropping it on the Canvas or My Collection page +- Update the **Token** and **API Endpoint** in the **Astra DB** components +- Update the OpenAI API key in the **OpenAI** components +- Run the ingestion flow which is the one that uses the **Astra DB** component +- Click on the ⚡ _Run_ button and start interacting with your RAG application + +# First things first + +## Create an Astra DB Database + +To get started, you will need to [create an Astra DB database](https://astra.datastax.com/signup?utm_source=langflow-pre-release&utm_medium=referral&utm_campaign=langflow-announcement&utm_content=create-an-astradb-database). + +Once you have created an account, you will be taken to the Astra DB dashboard. Click on the **Create Database** button. + + + +Now you will need to configure your database. Choose the **Serverless (Vector)** deployment type, and pick a Database name, provider and region. + +After you have configured your database, click on the **Create Database** button. + + + +Once your database is initialized, to the right of the page, you will see the _Database Details_ section which contains a button for you to copy the **API Endpoint** and another to generate a **Token**. + + + +Now we are all set to start building our RAG application using Astra DB and Langflow. + +## (Optional) Duplicate the Langflow 1.0 HuggingFace Space + +If you haven't already, now is the time to launch Langflow. To make things easier, you can duplicate our [Langflow 1.0 Space](https://huggingface.co/spaces/Langflow/Langflow-Preview?duplicate=true) which sets up a Langflow instance just for you. + +## Open the Vector Store RAG Project + +To get started, click on the **New Project** button and look for the **Vector Store RAG** project. This will open a starter project with the necessary components to run a RAG application using Astra DB. + + + +This project consists of two flows. The simpler one is the **Ingestion Flow** which is responsible for ingesting the documents into the Astra DB database. + +Your first step should be to understand what each flow does and how they interact with each other. + +The ingestion flow consists of: + +- **Files** component that uploads a text file to Langflow +- **Recursive Character Text Splitter** component that splits the text into smaller chunks +- **OpenAIEmbeddings** component that generates embeddings for the text chunks +- **Astra DB** component that stores the text chunks in the Astra DB database + + + +Now, let's update the **Astra DB** and **Astra DB Search** components with the **Token** and **API Endpoint** that we generated earlier, and the OpenAI Embeddings components with your OpenAI API key. + + + +And run it! This will ingest the Text data from your file into the Astra DB database. + + + +Now, on to the **RAG Flow**. This flow is responsible for generating responses to your queries. It will define all of the steps from getting the User's input to generating a response and displaying it in the Interaction Panel. + +The RAG flow is a bit more complex. It consists of: + +- **Chat Input** component that defines where to put the user input coming from the Interaction Panel +- **OpenAI Embeddings** component that generates embeddings from the user input +- **Astra DB Search** component that retrieves the most relevant Records from the Astra DB database +- **Text Output** component that turns the Records into Text by concatenating them and also displays it in the Interaction Panel + - One interesting point you'll see here is that this component is named `Extracted Chunks`, and that is how it will appear in the Interaction Panel +- **Prompt** component that takes in the user input and the retrieved Records as text and builds a prompt for the OpenAI model +- **OpenAI** component that generates a response to the prompt +- **Chat Output** component that displays the response in the Interaction Panel + + + +To run it all we have to do is click on the ⚡ _Run_ button and start interacting with your RAG application. + + + +This opens the Interaction Panel where you can chat your data. + +Because this flow has a **Chat Input** and a **Text Output** component, the Panel displays a chat input at the bottom and the Extracted Chunks section on the left. + + + +Once we interact with it we get a response and the Extracted Chunks section is updated with the retrieved records. + + + +And that's it! You have successfully ran a RAG application using Astra DB and Langflow. + +# Conclusion + +In this guide, we have learned how to run a RAG application using Astra DB and Langflow. +We have seen how to create an Astra DB database, import the Astra DB RAG Flows project into Langflow, and run the ingestion and RAG flows. diff --git a/docs/docs/guidelines/api.mdx b/docs/docs/guidelines/api.mdx index 8bba633fb..25dbeb31e 100644 --- a/docs/docs/guidelines/api.mdx +++ b/docs/docs/guidelines/api.mdx @@ -1,5 +1,6 @@ import useBaseUrl from "@docusaurus/useBaseUrl"; import ZoomableImage from "/src/theme/ZoomableImage.js"; +import Admonition from "@theme/Admonition"; # API Keys @@ -7,12 +8,17 @@ import ZoomableImage from "/src/theme/ZoomableImage.js"; Langflow offers an API Key functionality that allows users to access their individual components and flows without going through traditional login authentication. The API Key is a user-specific token that can be included in the request's header or query parameter to authenticate API calls. The following documentation outlines how to generate, use, and manage these API Keys in Langflow. + + This feature requires the `LANGFLOW_AUTO_LOGIN` environment variable to be set + to `False`. The default user and password are set using _`LANGFLOW_SUPERUSER`_ + and _`LANGFLOW_SUPERUSER_PASSWORD`_ environment variables. Default values are + _`langflow`_ and _`langflow`_ respectively. + + ## Generating an API Key ### Through Langflow UI -{/* add image img/api-key.png */} - \ + http://localhost:3000/api/v1/run/ \ -H 'Content-Type: application/json'\ -H 'x-api-key: '\ -d '{"inputs": {"text":""}, "tweaks": {}}' diff --git a/docs/docs/guidelines/async-api.mdx b/docs/docs/guidelines/async-api.mdx deleted file mode 100644 index c5473812e..000000000 --- a/docs/docs/guidelines/async-api.mdx +++ /dev/null @@ -1,73 +0,0 @@ -import Admonition from "@theme/Admonition"; - -# Asynchronous Processing - -## Introduction - -Starting from version 0.5, Langflow introduces a new feature to its API: the _`sync`_ flag. This flag allows users to opt for asynchronous processing of their flows, freeing up resources and enabling better control over long-running tasks. -This feature supports running tasks in a Celery worker queue and AnyIO task groups for now. - - - This is an experimental feature. The default behavior of the API is still - synchronous processing. The API may change in the future. - - -## The _`sync`_ Flag - -The _`sync`_ flag can be included in the payload of your POST request to the _`/api/v1/process/`_ endpoint. -When set to _`false`_, the API will initiate an asynchronous task instead of processing the flow synchronously. - -### API Request with _`sync`_ flag - -```bash -curl -X POST \ - http://localhost:3000/api/v1/process/ \ - -H 'Content-Type: application/json' \ - -H 'x-api-key: ' \ - -d '{"inputs": {"text": ""}, "tweaks": {}, "sync": false}' -``` - -Response: - -```json -{ - "result": { - "output": "..." - }, - "task": { - "id": "...", - "href": "api/v1/task/" - }, - "session_id": "...", - "backend": "..." // celery or anyio -} -``` - -## Checking Task Status - -You can check the status of an asynchronous task by making a GET request to the `/task/{task_id}` endpoint. - -```bash -curl -X GET \ - http://localhost:3000/api/v1/task/ \ - -H 'x-api-key: ' -``` - -### Response - -The endpoint will return the current status of the task and, if completed, the result of the task. Possible statuses include: - -- _`PENDING`_: The task is waiting for execution. -- _`SUCCESS`_: The task has completed successfully. -- _`FAILURE`_: The task has failed. - -Example response for a completed task: - -```json -{ - "status": "SUCCESS", - "result": { - "output": "..." - } -} -``` diff --git a/docs/docs/guidelines/components.mdx b/docs/docs/guidelines/components.mdx index 32ec00615..16aa83eff 100644 --- a/docs/docs/guidelines/components.mdx +++ b/docs/docs/guidelines/components.mdx @@ -26,13 +26,14 @@ Components are the building blocks of the flows. They are made of inputs, output {" "} +
diff --git a/docs/docs/guidelines/custom-component.mdx b/docs/docs/guidelines/custom-component.mdx index 99106d400..daf47987f 100644 --- a/docs/docs/guidelines/custom-component.mdx +++ b/docs/docs/guidelines/custom-component.mdx @@ -30,7 +30,7 @@ Here is an example: ```python -from langflow import CustomComponent +from langflow.custom import CustomComponent from langchain.schema import Document class DocumentProcessor(CustomComponent): @@ -92,7 +92,7 @@ The Python script for every Custom Component should follow a set of rules. Let's The script must contain a **single class** that inherits from _`CustomComponent`_. ```python -from langflow import CustomComponent +from langflow.custom import CustomComponent from langchain.schema import Document class MyComponent(CustomComponent): @@ -113,7 +113,7 @@ class MyComponent(CustomComponent): This class requires a _`build`_ method used to run the component and define its fields. ```python -from langflow import CustomComponent +from langflow.custom import CustomComponent from langchain.schema import Document class MyComponent(CustomComponent): @@ -134,7 +134,7 @@ class MyComponent(CustomComponent): The [Return Type Annotation](https://docs.python.org/3/library/typing.html) of the _`build`_ method defines the component type (e.g., Chain, BaseLLM, or basic Python types). Check out all supported types in the [component reference](../components/custom). ```python -from langflow import CustomComponent +from langflow.custom import CustomComponent from langchain.schema import Document class MyComponent(CustomComponent): @@ -153,7 +153,7 @@ class MyComponent(CustomComponent): --- ```python -from langflow import CustomComponent +from langflow.custom import CustomComponent from langchain.schema import Document class MyComponent(CustomComponent): @@ -179,7 +179,7 @@ Check out the [component reference](../components/custom) for more details on th --- ```python -from langflow import CustomComponent +from langflow.custom import CustomComponent from langchain.schema import Document class MyComponent(CustomComponent): @@ -204,7 +204,7 @@ Let's create a custom component that processes a document (_`langchain.schema.Do To start, let's choose a name for our component by adding a _`display_name`_ attribute. This name will appear on the canvas. The name of the class is not relevant, but let's call it _`DocumentProcessor`_. ```python -from langflow import CustomComponent +from langflow.custom import CustomComponent from langchain.schema import Document # focus @@ -227,7 +227,7 @@ class DocumentProcessor(CustomComponent): We can also write a description for it using a _`description`_ attribute. ```python -from langflow import CustomComponent +from langflow.custom import CustomComponent from langchain.schema import Document class DocumentProcessor(CustomComponent): @@ -244,7 +244,7 @@ class DocumentProcessor(CustomComponent): --- ```python -from langflow import CustomComponent +from langflow.custom import CustomComponent from langchain.schema import Document class DocumentProcessor(CustomComponent): @@ -283,11 +283,11 @@ The return type is _`Document`_. The _`build_config`_ method is here defined to customize the component fields. - _`options`_ determines that the field will be a dropdown menu. The list values and field type must be _`str`_. -- _`value`_ is the default option of the dropdown menu. +- _`value`_ is the default value of the field. - _`display_name`_ is the name of the field to be displayed. ```python -from langflow import CustomComponent +from langflow.custom import CustomComponent from langchain.schema import Document class DocumentProcessor(CustomComponent): diff --git a/docs/docs/guidelines/features.mdx b/docs/docs/guidelines/features.mdx index 19837430d..932607c30 100644 --- a/docs/docs/guidelines/features.mdx +++ b/docs/docs/guidelines/features.mdx @@ -1,9 +1,3 @@ -import ThemedImage from "@theme/ThemedImage"; -import useBaseUrl from "@docusaurus/useBaseUrl"; -import ZoomableImage from "/src/theme/ZoomableImage.js"; -import ReactPlayer from "react-player"; -import Admonition from "@theme/Admonition"; - # Features
@@ -14,13 +8,14 @@ import Admonition from "@theme/Admonition";
{" "} +
@@ -46,14 +41,12 @@ The Code button shows snippets to use your flow as a Python object or an API. **Python Code** -Through the Langflow package, you can load a flow from a JSON file and use it as a LangChain object. +Through the Langflow package, you can run your flow from a JSON file. The example below shows how to run a flow from a JSON file. -```py -from langflow import load_flow_from_json +```python +from langflow.load import run_flow_from_json -flow = load_flow_from_json("path/to/flow.json") -# Now you can use it like any chain -flow("Hey, have you heard of Langflow?") +results = run_flow_from_json("path/to/flow.json", input_value="Hello, World!") ``` **API** @@ -67,3 +60,9 @@ The example below shows a Python script making a POST request to a local API end >
+ +import ThemedImage from "@theme/ThemedImage"; +import useBaseUrl from "@docusaurus/useBaseUrl"; +import ZoomableImage from "/src/theme/ZoomableImage.js"; +import ReactPlayer from "react-player"; +import Admonition from "@theme/Admonition"; diff --git a/docs/docs/guidelines/login.mdx b/docs/docs/guidelines/login.mdx index fde7cd09a..1d5a1d031 100644 --- a/docs/docs/guidelines/login.mdx +++ b/docs/docs/guidelines/login.mdx @@ -105,7 +105,7 @@ Users can change their profile settings by clicking on the profile icon in the t light: useBaseUrl("img/my-account.png"), dark: useBaseUrl("img/my-account.png"), }} - style={{ width: "50%", maxWidth: "600px", margin: "0 auto" }} + style={{ width: "50%", maxWidth: "600px", margin: "20px auto" }} /> By clicking on **Profile Settings**, the user is taken to the profile settings page, where they can change their password and their profile picture. @@ -116,10 +116,11 @@ By clicking on **Profile Settings**, the user is taken to the profile settings p light: useBaseUrl("img/profile-settings.png"), dark: useBaseUrl("img/profile-settings.png"), }} - style={{ maxWidth: "600px", margin: "0 auto" }} + style={{ maxWidth: "600px", margin: "20px auto" }} /> -By clicking on **Admin Page**, the superuser is taken to the admin page, where they can manage users and groups. +By clicking on **Admin Page**, the superuser is taken to the admin page, where they +can manage users and groups. - This implementation is still in development. Contributions are welcome! - - -The Async API is an implementation of the Langflow API that uses [Celery](https://docs.celeryproject.org/en/stable/) -to run the tasks asynchronously, using a message broker to send and receive messages, a result backend to store the results and a cache to store the task states and session data. - -### Configuration - -The folder _`./deploy`_ in the [Github repository](https://github.com/logspace-ai/langflow) contains a _`.env.example`_ file that can be used to configure a Langflow deployment. -The file contains the variables required to configure a Celery worker queue, Redis cache and result backend and a RabbitMQ message broker. - -To set it up locally you can copy the file to _`.env`_ and run the following command: - -```bash -docker compose up -d -``` - -This will set up the following containers: - -- Langflow API -- Celery worker -- RabbitMQ message broker -- Redis cache -- PostgreSQL database -- PGAdmin -- Flower -- Traefik -- Grafana -- Prometheus - -### Testing - -To run the tests for the Async API, you can run the following command: - -```bash -docker compose -f docker-compose.with_tests.yml up --exit-code-from tests tests result_backend broker celeryworker db --build -``` diff --git a/docs/docs/guides/superuser.mdx b/docs/docs/guides/superuser.mdx deleted file mode 100644 index 04e0f96af..000000000 --- a/docs/docs/guides/superuser.mdx +++ /dev/null @@ -1,7 +0,0 @@ -import ThemedImage from "@theme/ThemedImage"; -import useBaseUrl from "@docusaurus/useBaseUrl"; -import ZoomableImage from "/src/theme/ZoomableImage.js"; -import ReactPlayer from "react-player"; - -Now, we need to explain what are the permissions the superuser gets. Once logged in, they can activate new users, -edit them, diff --git a/docs/docs/index.mdx b/docs/docs/index.mdx index 840f10f10..9357a8fdf 100644 --- a/docs/docs/index.mdx +++ b/docs/docs/index.mdx @@ -1,11 +1,13 @@ -# 👋 Welcome to Langflow - -Langflow is an easy way to create flows. The drag-and-drop feature allows quick and effortless experimentation, while the built-in chat interface facilitates real-time interaction. It provides options to edit prompt parameters, create chains and agents, track thought processes, and export flows. - import ThemedImage from "@theme/ThemedImage"; import useBaseUrl from "@docusaurus/useBaseUrl"; import ZoomableImage from "/src/theme/ZoomableImage.js"; +# 👋 Welcome to Langflow + +Langflow is an easy way to build from simple to complex AI applications. It is a low-code platform that allows you to integrate AI into everything you do. + +{" "} + {" "} + +## 🚀 First steps + +## Installation + +Make sure you have **Python 3.10** installed on your system. + +You can install **Langflow** with [pipx](https://pipx.pypa.io/stable/installation/) or with pip. + +Pipx can fetch the missing Python version for you, but you can also install it manually. + +```bash +pip install langflow -U +# or +pipx install langflow --python python3.10 --fetch-missing-python +``` + +Or you can install a pre-release version using: + +```bash +pip install langflow --pre --force-reinstall +# or +pipx install langflow --python python3.10 --fetch-missing-python --pip-args="--pre --force-reinstall" +``` + +We recommend using --force-reinstall to ensure you have the latest version of Langflow and its dependencies. + +### ⛓️ Running Langflow + +Langflow can be run in a variety of ways, including using the command-line interface (CLI) or HuggingFace Spaces. + +```bash +langflow run # or langflow --help +``` + +#### 🤗 HuggingFace Spaces + +Hugging Face provides a great alternative for running Langflow in their Spaces environment. This means you can run Langflow without any local installation required. + +The first step is to go to the [Langflow Space](https://huggingface.co/spaces/Logspace/Langflow?duplicate=true). + +Remember to use a Chromium-based browser for the best experience. You'll be presented with the following screen: + + + +From here, just name your Space, define the visibility (Public or Private), and click on `Duplicate Space` to start the installation process. When that is done, you'll be redirected to the Space's main page to start using Langflow right away! + +Once you get Langflow running, click on New Project in the top right corner of the screen. Langflow provides a range of example flows to help you get started. + +To quickly try one of them, open a starter example, set up your API keys and click ⚡ Run, on the bottom right corner of the canvas. This will open up Langflow's Interaction Panel with the chat console, text inputs, and outputs. + +### 🖥️ Command Line Interface (CLI) + +Langflow provides a command-line interface (CLI) for easy management and configuration. + +#### Usage + +You can run the Langflow using the following command: + +```bash +langflow run [OPTIONS] +``` + +Find more information about the available options by running: + +```bash +langflow --help +``` diff --git a/src/backend/langflow/components/embeddings/__init__.py b/docs/docs/migration/api.mdx similarity index 100% rename from src/backend/langflow/components/embeddings/__init__.py rename to docs/docs/migration/api.mdx diff --git a/docs/docs/migration/compatibility.mdx b/docs/docs/migration/compatibility.mdx new file mode 100644 index 000000000..8223bcceb --- /dev/null +++ b/docs/docs/migration/compatibility.mdx @@ -0,0 +1,44 @@ +import Admonition from '@theme/Admonition'; + +# Compatibility with Previous Versions + + +## TLDR; + +- You'll need to add a few components to your flow to make it compatible with the new version of Langflow. +- Add a Runnable Executor, connect it to the last component (a Chain or an Agent) in your flow, and connect a Chat Input and a Chat Output to the Runnable Executor. This should work *most of the time*. +- You might also need to update the Chain or Agent component to the latest version. +- Most Components will work as they are, but you'll need to add an Input and an Output to your flow. +- You can use the Runnable Executor to run a LangChain runnable (which is the output of many components before 1.0) +- We need your feedback on this, so please let us know how it goes and what you think. + +## Introduction + +Langflow now works best with a flow that has an Input and an Output and that is mostly what you'll need to add to your existing flows. + +Hopefully, you'll find that even though you still can work with your current flows, updating all your components to the new version of Langflow will be worth it. + +We've tried to make it as easy as possible for you to adapt your existing flows to work seamlessly in the new version of Langflow. + +## How to Adapt Your Existing Flows + + +The steps to take are few but not always simple. Here's how you can adapt your existing flows to work seamlessly in the new version of Langflow: + + +

**Caution:**

+

While this should work most of the time, it might not work for all flows. You might need to update the Chain or Agent component to the latest version. Please let us know if you encounter any issues.

+
+ +1. **Check if your flow ends with a Chain or Agent component**. + - If it does not, it *should* work as it is because it probably was not a chat flow. +2. **Add a Runnable Executor**. + - Add a Runnable Executor to the end of your flow. + - Connect the last component (a Chain or an Agent) in your flow to the Runnable Executor. +3. **Add a Chat Input and a Chat Output**. + - Add a Chat Input and a Chat Output to your flow. + - Connect the Chat Input to the Runnable Executor. + - Connect the Chat Output to the Runnable Executor. + +{/* Add picture of the flow */} + diff --git a/src/backend/langflow/components/llms/__init__.py b/docs/docs/migration/component-status-and-data-passing.mdx similarity index 100% rename from src/backend/langflow/components/llms/__init__.py rename to docs/docs/migration/component-status-and-data-passing.mdx diff --git a/src/backend/langflow/components/retrievers/__init__.py b/docs/docs/migration/connecting-output-components.mdx similarity index 100% rename from src/backend/langflow/components/retrievers/__init__.py rename to docs/docs/migration/connecting-output-components.mdx diff --git a/src/backend/langflow/components/textsplitters/__init__.py b/docs/docs/migration/custom-component.mdx similarity index 100% rename from src/backend/langflow/components/textsplitters/__init__.py rename to docs/docs/migration/custom-component.mdx diff --git a/src/backend/langflow/components/toolkits/__init__.py b/docs/docs/migration/experimental-components.mdx similarity index 100% rename from src/backend/langflow/components/toolkits/__init__.py rename to docs/docs/migration/experimental-components.mdx diff --git a/src/backend/langflow/components/tools/__init__.py b/docs/docs/migration/flow-of-data.mdx similarity index 100% rename from src/backend/langflow/components/tools/__init__.py rename to docs/docs/migration/flow-of-data.mdx diff --git a/docs/docs/migration/global-variables.mdx b/docs/docs/migration/global-variables.mdx new file mode 100644 index 000000000..ce6d15a5f --- /dev/null +++ b/docs/docs/migration/global-variables.mdx @@ -0,0 +1,65 @@ +import ZoomableImage from "/src/theme/ZoomableImage.js"; +import Admonition from "@theme/Admonition"; + +# Global Variables + +Global Variables are a really useful feature of Langflow. +They allow you to define reusable variables that can be accessed from any Text field in your project. + +The first thing you need to do is find a **Text field** in a Component, so let's talk about what a Text field is. + +## Text Fields + +Text fields are the fields in a Component where you can write text but that does not allow you to open a Text Area. + +The easiest way to find fields that are Text fields, though, is to look for fields that have a 🌐 button. + + + +## Creating a Global Variable + +To create a Global Variable, you need to click on the 🌐 button in a Text field and that will open a dropdown showing your currently available variables and at the end of it **+ Add New Variable**. + + + +Click on **+ Add New Variable** and a window will open where you can define your new Global Variable. + +In it, you can define the **Name** of the variable, the optional **Type** of the variable, and the **Value** of the variable. + +The **Name** is the name that you will use to refer to the variable in your Text fields. + +The **Type** is optional for now but will be used in the future to allow for more advanced features. + +The **Value** is the value that the variable will have. +{/* say that all variables are encrypted */} + + + All Global Variables are encrypted and cannot be accessed by anyone but you. + + + + +After you have defined your variable, click on **Save Variable** and your variable will be created. + +After that, once you click on the 🌐 button in a Text field, you will see your new variable in the dropdown. diff --git a/docs/docs/migration/inputs-and-outputs.mdx b/docs/docs/migration/inputs-and-outputs.mdx new file mode 100644 index 000000000..5db3f3af2 --- /dev/null +++ b/docs/docs/migration/inputs-and-outputs.mdx @@ -0,0 +1,36 @@ +# Inputs and Outputs + +TL;DR: Inputs and Outputs are a category of components that are used to define where data comes in and out of your flow. They also +dynamically change the Interaction Panel and can be renamed to make it easier to build and maintain your flows. + +## Introduction + +Langflow 1.0 introduces new categories of components called Inputs and Outputs. They are used to make it easier to understand and interact with your flows. + +Let's start with what they have in common: + +- Components in these categories connect to components that have Text or Record inputs or outputs. Some can connect to both but you have to pick what type of data you want to output or input. +- They can be renamed to help you identify them more easily in the Interaction Panel and while using the API. +- They dynamically change the Interaction Panel to make it easier to understand and interact with your flows. + +Native Langflow Components were created to be powerful tools that work around Langflow's features. They are designed to be easy to use and understand, and to help you build your flows faster. + +Let's dive into Inputs and Outputs. + +## Inputs + +Inputs are components that are used to define where data comes into your flow. They can be used to receive data from the user, from a database, or from any other source that can be converted to Text or Record. + +The difference between Chat Input and other Input components is the format of the output, the number of configurable fields, and the way they are displayed in the Interaction Panel. + +Chat Input components can output Text or Record. When you want to pass the sender name, or sender to the next component, you can use the Record output, and when you want to pass the message only you can use the Text output. This is useful when saving the message to a database or a memory system like Zep. + +You can find out more about it and the other Inputs [here](../components/inputs). + +## Outputs + +Outputs are components that are used to define where data comes out of your flow. They can be used to send data to the user, to the Interaction Panel, or to define how the data will be displayed in the Interaction Panel. + +The Chat Output works similarly to the Chat Input but does not have a field that allows for written input. It is used as an Output definition and can be used to send data to the user. + +You can find out more about it and the other Outputs [here](../components/outputs). diff --git a/src/backend/langflow/components/vectorstores/__init__.py b/docs/docs/migration/multiple-flows.mdx similarity index 100% rename from src/backend/langflow/components/vectorstores/__init__.py rename to docs/docs/migration/multiple-flows.mdx diff --git a/src/backend/langflow/core/__init__.py b/docs/docs/migration/new-categories-and-components.mdx similarity index 100% rename from src/backend/langflow/core/__init__.py rename to docs/docs/migration/new-categories-and-components.mdx diff --git a/src/backend/langflow/custom/__init__.py b/docs/docs/migration/passing-tweaks-and-inputs.mdx similarity index 100% rename from src/backend/langflow/custom/__init__.py rename to docs/docs/migration/passing-tweaks-and-inputs.mdx diff --git a/src/backend/langflow/graph/edge/__init__.py b/docs/docs/migration/renaming-and-editing-components.mdx similarity index 100% rename from src/backend/langflow/graph/edge/__init__.py rename to docs/docs/migration/renaming-and-editing-components.mdx diff --git a/src/backend/langflow/graph/graph/__init__.py b/docs/docs/migration/sidebar-and-interaction-panel.mdx similarity index 100% rename from src/backend/langflow/graph/graph/__init__.py rename to docs/docs/migration/sidebar-and-interaction-panel.mdx diff --git a/src/backend/langflow/graph/vertex/__init__.py b/docs/docs/migration/state-management.mdx similarity index 100% rename from src/backend/langflow/graph/vertex/__init__.py rename to docs/docs/migration/state-management.mdx diff --git a/src/backend/langflow/interface/__init__.py b/docs/docs/migration/supported-frameworks.mdx similarity index 100% rename from src/backend/langflow/interface/__init__.py rename to docs/docs/migration/supported-frameworks.mdx diff --git a/docs/docs/migration/text-and-record.mdx b/docs/docs/migration/text-and-record.mdx new file mode 100644 index 000000000..cdfb26b6c --- /dev/null +++ b/docs/docs/migration/text-and-record.mdx @@ -0,0 +1,45 @@ +# Text and Record + +In Langflow 1.0 we added two main input and output types: Text and Record. Text is a simple string input and output type, while Record is a structure very similar to a dictionary in Python. It is a key-value pair data structure. + +We've created a few components to help you work with these types. Let's see how a few of them work. + +### Records To Text + +This is a Component that takes in Records and outputs a Text. It does this using a template string and concatenating the values of the Record, one per line. + +If we have the following Records: + +```json +{ + "sender_name": "Alice", + "message": "Hello!" +} +{ + "sender_name": "John", + "message": "Hi!" +} +``` + +And the template string is: _`{sender_name}: {message}`_ + +``` +Alice: Hello! +John: Hi! +``` + +### Create Record + +This Component allows you to create a Record from a number of inputs. You can add as many key-value pairs as you want (as long as it is less than 15 😅). Once you've picked that number you'll need to write the name of the Key and can pass Text values from other components to it. + +### Documents To Records + +This Component takes in a [LangChain](https://langchain.com) Document and outputs a Record. It does this by extracting the _`page_content`_ and the _`metadata`_ from the Document and adding them to the Record as _`text`_ and _`data`_ respectively. + +## Why is this useful? + +The idea was to create a unified way to work with complex data in Langflow, and to make it easier to work with data that is not just a simple string. This way you can create more complex workflows and use the data in more ways. + +## What's next? + +We are planning to integrate an array of modalities to Langflow, such as images, audio, and video. This will allow you to create even more complex workflows and use cases. Stay tuned for more updates! 🚀 diff --git a/docs/docs/whats-new/a-new-chapter-langflow.mdx b/docs/docs/whats-new/a-new-chapter-langflow.mdx new file mode 100644 index 000000000..b312dc198 --- /dev/null +++ b/docs/docs/whats-new/a-new-chapter-langflow.mdx @@ -0,0 +1,96 @@ +# A new chapter for Langflow + +# First things first + +Thank you all for being part of the Langflow community. The journey so far has been amazing and we are happy to have you with us. + +We have some exciting news to share with you. Langflow is changing, and we want to tell you all about it. + +## Where have we been? + +We spent the last few months working on a new version of Langflow. We wanted to make it more powerful, more flexible, and easier to use. +We're moving from version 0.6 straight to 1.0 (preview). This is a big change, and we want to explain why we're doing it and what it means for you. + +## Why? + +In the past year, we learned a lot from the community and our users. We saw the potential of Langflow and the need for a more powerful and flexible tool for building conversational AI applications (and beyond). +We realized that Langflow was hiding things from you that would really help you build better and more complex conversational AI applications. So we decided to make a big change. + +## The only way to go is forward + +From all the people we talked to, we learned that the most important thing for (most of) them is to have a tool that is easy to use, but also powerful and controllable. They also told us that Langflow's transparency could be improved. + +In those points, we saw an opportunity to make Langflow much more powerful and flexible, while also making it easier to use and understand. + +One key change you'll notice is that projects now require you to define Inputs and Outputs. +This is a big change, but it's also a big improvement. +It allows you to define the structure of your conversation and the data that flows through it. +This makes it easier to understand and control your conversation. + +This change comes with a new way of visualizing your projects. Before 1.0 you would connect Components to ultimately build one final Component that was processed behind the scenes. +Now, each step of the process is defined by you, is visible on the canvas, and can be monitored and controlled by you. This makes it so that Composition is now just another way of building in Langflow. **Now data flows through your project more transparently**. + +The caveat is existing projects may need some new Components to get them back to their full functionality. +[We've made this as easy as possible](../migration/compatibility), and there will be improvements to it as we get feedback in our Discord server and on GitHub. + +## Custom Interactions + +The moment we decided to make this change, we saw the potential to make Langflow even more yours. +By having a clear definition of Inputs and Outputs, we could build the experience around that which led us to create the **Interaction Panel**. + +When building a project testing and debugging is crucial. The Interaction Panel is a tool that changes dynamically based on the Inputs and Outputs you defined in your project. + +For example, let's say you are building a simple RAG application. Generally, you have an Input, some references that come from a Vector Store Search, a Prompt and the answer. +Now, you could plug the output of your Prompt into a [Text Output](../components/outputs#Text-Output), rename that to "Prompt Result" and see the output of your Prompt in the Interaction Panel. + +{/* Add image here of the described above */} + +This is just one example of how the Interaction Panel can help you build and debug your projects. + +We have many planned features for the Interaction Panel, and we're excited to see how you use it and what you think of it. + +## An easier start + +The experience for the first-time user is also something we wanted to improve. + +Meet the new and improved **New Project** screen. It's now easier to start a new project, and you can choose from a list of starter projects to get you started. + +{/* Add new project image */} + +We wanted to create start projects that would help you learn about new features and also give you a head start on your projects. + +For now, we have: + +- **[Basic Prompting (Hello, world!)](/getting-started/basic-prompting)**: A simple flow that shows you how to use the Prompt Component and how to talk like a pirate. +- **[Vector Store RAG](/getting-started/rag-with-astradb)**: A flow that shows you how to ingest data into a Vector Store and then use it to run a RAG application. +- **[Memory Chatbot](/getting-started/memory-chatbot)**: This one shows you how to create a simple chatbot that can remember things about the user. +- **[Document QA](/getting-started/document-qa)**: This flow shows you how to build a simple flow that helps you get answers about a document. +- **[Blog Writer](/getting-started/blog-writer)**: Shows you how you can expand on the Prompt variables and be creative about what inputs you add to it. + +As always, your feedback is invaluable, so please let us know what you think of the new starter projects and what you would like to see in the future. + +## Less is more + +We added many new Components to Langflow and updated some of the existing ones, and we will deprecate some of them. + +The idea is that Langflow has evolved, and we want to make sure that the Components you use are the best they can be. +Some of them don't work well with the others, and some of them are just not needed anymore. + +We are working on a list of Components that will be deprecated. +In the preview stages of 1.0, we will have a smaller list of Components so that we make sure that the ones we have are the best they can be. +Regardless, community feedback is very important in this matter, so please let us know what you think of the new Components and which ones you miss. + +We are aiming at having a more stable and reliable set of Components that helps you get quickly to useful results. +This also means that your contributions in the [Langflow Store](https://langflow.store) and throughout the community are more important than ever. + +## What's next? + +Langflow went through a big change, and we are excited to see how you use it and what you think of it. + +We plan to add more types of Input and Output like Image and Audio, and we also plan to add more Components to help you build more complex projects. + +We also have some experimental features like a State Management System (so cool!) and a new way of building Grouped Components that we are excited to show you. + +## Reach out + +One last time, we want to thank you for being part of the Langflow community. Your feedback is invaluable, and we want to hear from you. diff --git a/docs/docs/whats-new/customization-control.mdx b/docs/docs/whats-new/customization-control.mdx new file mode 100644 index 000000000..11f23f53c --- /dev/null +++ b/docs/docs/whats-new/customization-control.mdx @@ -0,0 +1 @@ +# A New Customization and Control \ No newline at end of file diff --git a/docs/docs/whats-new/debugging-reimagined.mdx b/docs/docs/whats-new/debugging-reimagined.mdx new file mode 100644 index 000000000..d30234088 --- /dev/null +++ b/docs/docs/whats-new/debugging-reimagined.mdx @@ -0,0 +1 @@ +# Debugging Reimagined \ No newline at end of file diff --git a/docs/docs/whats-new/migrating-to-one-point-zero.mdx b/docs/docs/whats-new/migrating-to-one-point-zero.mdx new file mode 100644 index 000000000..45bae6084 --- /dev/null +++ b/docs/docs/whats-new/migrating-to-one-point-zero.mdx @@ -0,0 +1,125 @@ +# Migrating to Langflow 1.0: A Guide + +Langflow 1.0 is a significant update that brings many exciting changes and improvements to the platform. +This guide will walk you through the key improvements and help you migrate your existing projects to the new version. + +If you have any questions or need assistance during the migration process, please don't hesitate to reach out to in our [Discord](https://discord.gg/wZSWQaukgJ) or [GitHub](https://github.com/logspace-ai/langflow/issues) community. + +We have a special channel in our Discord server dedicated to Langflow 1.0 migration, where you can ask questions, share your experiences, and get help from the community. + +## TLDR; + +- Inputs and Outputs of Components have changed +- We've surfaced steps that were previously run in the background +- Continued support for LangChain and new support for multiple frameworks +- Redesigned sidebar and customizable interaction panel +- New Native Categories and Components +- Improved user experience with Text and Record modes +- CustomComponent for all components +- Compatibility with previous versions using Runnable Executor +- Multiple flows in the canvas +- Improved component status +- Ability to connect Output components to any other Component +- Rename and edit component descriptions +- Pass tweaks and inputs in the API using Display Name +- Global Variables for Text Fields +- Experimental components like SubFlow and Flow as Tool +- Experimental State Management system with Notify and Listen components + +## Inputs and Outputs of Components + +Langflow 1.0 introduces adds the concept of Inputs and Outputs to flows, allowing a clear definition of the data flow between components. Discover how to use Inputs and Outputs to pass data between components and create more dynamic flows. + +[Learn more about Inputs and Outputs of Components](../migration/inputs-and-outputs) + +## To Compose or Not to Compose: the choice is yours + +Even though composition is still possible in Langflow 1.0, the new standard is getting data moving through the flow. This allows for more flexibility and control over the data flow in your projects. + +We will create guides on how to interweave LangChain components with our Core components soon. + +## Continued Support for LangChain and Multiple Frameworks + +Langflow 1.0 continues to support LangChain while also introducing support for multiple frameworks. This is another important boon that adding the paradigm of data flow brings to the table. Find out how to leverage the power of different frameworks in your projects. + +[Learn more about Supported Frameworks](../migration/supported-frameworks) + +## Sidebar Redesign and Customizable Interaction Panel + +We've expanded on the chat experience by creating a customizable interaction panel that allows you to design a panel that fits your needs and interact with it. The sidebar has also been redesigned to provide a more intuitive and user-friendly experience. Explore the new sidebar and interaction panel features to enhance your workflow. + +[Learn more about some of the UI updates](../migration/sidebar-and-interaction-panel) + +## New Native Categories and Components + +Langflow 1.0 introduces many new native categories, including Inputs, Outputs, Helpers, Experimental, Models, and more. Discover the new components available, such as Chat Input, Prompt, Files, API Request, and others. + +[Learn more about New Categories and Components](../migration/new-categories-and-components) + +## New Way of Using Langflow: Text and Record (and more to come) + +With the introduction of Text and Record types connections between Components are more intuitive and easier to understand. This is the first step in a series of improvements to the way you interact with Langflow. Learn how to use Text, and Record and how they help you build better flows. + +[Learn more about Text and Record](../migration/text-and-record) + +## CustomComponent for All Components + +Almost all components in Langflow 1.0 are now CustomComponents, allowing you to check and modify the code of each component. Discover how to leverage this feature to customize your components to your specific needs. + +[Learn more about CustomComponent](../migration/custom-component) + +## Compatibility with Previous Versions + +To use flows built in previous versions of Langflow, you can utilize the experimental component Runnable Executor along with an Input and Output. **We'd love your feedback on this**. Learn how to adapt your existing flows to work seamlessly in the new version of Langflow. + +[Learn more about Compatibility with Previous Versions](../migration/compatibility) + +## Multiple Flows in the Canvas + +Langflow 1.0 allows you to have more than one flow in the canvas and run them separately. Discover how to create and manage multiple flows within a single project. + +[Learn more about Multiple Flows](../migration/multiple-flows) + +## Improved Component Status + +Each component now displays its status more clearly, allowing you to quickly identify any issues or errors. Explore how to use the new component status feature to troubleshoot and optimize your flows. + +[Learn more about Component Status](../migration/component-status-and-data-passing) + +## Connecting Output Components + +You can now connect Output components to any other component (that has a Text output), providing a better understanding of the data flow. Explore the possibilities of connecting Output components and how it enhances your flow's functionality. + +[Learn more about Connecting Output Components](../migration/connecting-output-components) + +## Renaming and Editing Component Descriptions + +Langflow 1.0 allows you to rename and edit the description of each component, making it easier to understand and interact with the flow. Learn how to customize your component names and descriptions for improved clarity. + +[Learn more about Renaming and Editing Components](../migration/renaming-and-editing-components) + +## Passing Tweaks and Inputs in the API + +Things got a whole lot easier. You can now pass tweaks and inputs in the API by referencing the Display Name of the component. Discover how to leverage this feature to dynamically control your flow's behavior. + +[Learn more about Passing Tweaks and Inputs](../migration/passing-tweaks-and-inputs) + +## Global Variables for Text Fields + +Global Variables can be used in any Text Field across your projects. Learn how to define and utilize Global Variables to streamline your workflow. + +[Learn more about Global Variables](../migration/global-variables) + +## Experimental Components + +Explore the experimental components available in Langflow 1.0, such as SubFlow, which allows you to load a flow as a component dynamically, and Flow as Tool, which enables you to use a flow as a tool for an Agent. + +[Learn more about Experimental Components](../migration/experimental-components) + +## Experimental State Management System + +We are experimenting with a State Management system for flows that allows components to trigger other components and pass messages between them using the Notify and Listen components. Discover how to leverage this system to create more dynamic and interactive flows. + +[Learn more about State Management](../migration/state-management) + +We hope this guide helps you navigate the changes and improvements in Langflow 1.0. If you have any questions or need further assistance, please don't hesitate to reach out to us in our [Discord](https://discord.gg/wZSWQaukgJ). \ No newline at end of file diff --git a/docs/docs/whats-new/simplification-standardization.mdx b/docs/docs/whats-new/simplification-standardization.mdx new file mode 100644 index 000000000..f7e3115bc --- /dev/null +++ b/docs/docs/whats-new/simplification-standardization.mdx @@ -0,0 +1 @@ +# Simplification Through Standardization \ No newline at end of file diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index 430aebcb0..979953918 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -14,6 +14,7 @@ module.exports = { organizationName: "logspace-ai", projectName: "langflow", trailingSlash: false, + staticDirectories: ["static"], customFields: { mendableAnonKey: process.env.MENDABLE_ANON_KEY, }, @@ -42,6 +43,10 @@ module.exports = { path: "docs", // sidebarPath: 'sidebars.js', }, + gtag: { + trackingID: 'G-XHC7G628ZP', + anonymizeIP: true, + }, theme: { customCss: [ require.resolve("@code-hike/mdx/styles.css"), diff --git a/docs/package-lock.json b/docs/package-lock.json index 6742b89e7..c91a4ec06 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -10,11 +10,12 @@ "dependencies": { "@babel/preset-react": "^7.22.3", "@code-hike/mdx": "^0.9.0", - "@docusaurus/core": "3.0.1", - "@docusaurus/plugin-ideal-image": "^3.0.1", - "@docusaurus/preset-classic": "3.0.1", - "@docusaurus/theme-classic": "^3.0.1", - "@docusaurus/theme-search-algolia": "^3.0.1", + "@docusaurus/core": "^3.2.0", + "@docusaurus/plugin-google-gtag": "^3.2.0", + "@docusaurus/plugin-ideal-image": "^3.2.0", + "@docusaurus/preset-classic": "^3.2.0", + "@docusaurus/theme-classic": "^3.2.0", + "@docusaurus/theme-search-algolia": "^3.2.0", "@mdx-js/react": "^2.3.0", "@mendable/search": "^0.0.154", "@pbe/react-yandex-maps": "^1.2.4", @@ -41,7 +42,7 @@ "tailwindcss": "^3.3.2" }, "devDependencies": { - "@docusaurus/module-type-aliases": "2.4.1", + "@docusaurus/module-type-aliases": "^3.2.0", "css-loader": "^6.8.1", "docusaurus-node-polyfills": "^1.0.0", "node-sass": "^9.0.0", @@ -94,74 +95,74 @@ } }, "node_modules/@algolia/cache-browser-local-storage": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.22.0.tgz", - "integrity": "sha512-uZ1uZMLDZb4qODLfTSNHxSi4fH9RdrQf7DXEzW01dS8XK7QFtFh29N5NGKa9S+Yudf1vUMIF+/RiL4i/J0pWlQ==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.23.2.tgz", + "integrity": "sha512-PvRQdCmtiU22dw9ZcTJkrVKgNBVAxKgD0/cfiqyxhA5+PHzA2WDt6jOmZ9QASkeM2BpyzClJb/Wr1yt2/t78Kw==", "dependencies": { - "@algolia/cache-common": "4.22.0" + "@algolia/cache-common": "4.23.2" } }, "node_modules/@algolia/cache-common": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.22.0.tgz", - "integrity": "sha512-TPwUMlIGPN16eW67qamNQUmxNiGHg/WBqWcrOoCddhqNTqGDPVqmgfaM85LPbt24t3r1z0zEz/tdsmuq3Q6oaA==" + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.23.2.tgz", + "integrity": "sha512-OUK/6mqr6CQWxzl/QY0/mwhlGvS6fMtvEPyn/7AHUx96NjqDA4X4+Ju7aXFQKh+m3jW9VPB0B9xvEQgyAnRPNw==" }, "node_modules/@algolia/cache-in-memory": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.22.0.tgz", - "integrity": "sha512-kf4Cio9NpPjzp1+uXQgL4jsMDeck7MP89BYThSvXSjf2A6qV/0KeqQf90TL2ECS02ovLOBXkk98P7qVarM+zGA==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.23.2.tgz", + "integrity": "sha512-rfbi/SnhEa3MmlqQvgYz/9NNJ156NkU6xFxjbxBtLWnHbpj+qnlMoKd+amoiacHRITpajg6zYbLM9dnaD3Bczw==", "dependencies": { - "@algolia/cache-common": "4.22.0" + "@algolia/cache-common": "4.23.2" } }, "node_modules/@algolia/client-account": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.22.0.tgz", - "integrity": "sha512-Bjb5UXpWmJT+yGWiqAJL0prkENyEZTBzdC+N1vBuHjwIJcjLMjPB6j1hNBRbT12Lmwi55uzqeMIKS69w+0aPzA==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.23.2.tgz", + "integrity": "sha512-VbrOCLIN/5I7iIdskSoSw3uOUPF516k4SjDD4Qz3BFwa3of7D9A0lzBMAvQEJJEPHWdVraBJlGgdJq/ttmquJQ==", "dependencies": { - "@algolia/client-common": "4.22.0", - "@algolia/client-search": "4.22.0", - "@algolia/transporter": "4.22.0" + "@algolia/client-common": "4.23.2", + "@algolia/client-search": "4.23.2", + "@algolia/transporter": "4.23.2" } }, "node_modules/@algolia/client-analytics": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.22.0.tgz", - "integrity": "sha512-os2K+kHUcwwRa4ArFl5p/3YbF9lN3TLOPkbXXXxOvDpqFh62n9IRZuzfxpHxMPKAQS3Et1s0BkKavnNP02E9Hg==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.23.2.tgz", + "integrity": "sha512-lLj7irsAztGhMoEx/SwKd1cwLY6Daf1Q5f2AOsZacpppSvuFvuBrmkzT7pap1OD/OePjLKxicJS8wNA0+zKtuw==", "dependencies": { - "@algolia/client-common": "4.22.0", - "@algolia/client-search": "4.22.0", - "@algolia/requester-common": "4.22.0", - "@algolia/transporter": "4.22.0" + "@algolia/client-common": "4.23.2", + "@algolia/client-search": "4.23.2", + "@algolia/requester-common": "4.23.2", + "@algolia/transporter": "4.23.2" } }, "node_modules/@algolia/client-common": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.22.0.tgz", - "integrity": "sha512-BlbkF4qXVWuwTmYxVWvqtatCR3lzXwxx628p1wj1Q7QP2+LsTmGt1DiUYRuy9jG7iMsnlExby6kRMOOlbhv2Ag==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.23.2.tgz", + "integrity": "sha512-Q2K1FRJBern8kIfZ0EqPvUr3V29ICxCm/q42zInV+VJRjldAD9oTsMGwqUQ26GFMdFYmqkEfCbY4VGAiQhh22g==", "dependencies": { - "@algolia/requester-common": "4.22.0", - "@algolia/transporter": "4.22.0" + "@algolia/requester-common": "4.23.2", + "@algolia/transporter": "4.23.2" } }, "node_modules/@algolia/client-personalization": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.22.0.tgz", - "integrity": "sha512-pEOftCxeBdG5pL97WngOBi9w5Vxr5KCV2j2D+xMVZH8MuU/JX7CglDSDDb0ffQWYqcUN+40Ry+xtXEYaGXTGow==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.23.2.tgz", + "integrity": "sha512-vwPsgnCGhUcHhhQG5IM27z8q7dWrN9itjdvgA6uKf2e9r7vB+WXt4OocK0CeoYQt3OGEAExryzsB8DWqdMK5wg==", "dependencies": { - "@algolia/client-common": "4.22.0", - "@algolia/requester-common": "4.22.0", - "@algolia/transporter": "4.22.0" + "@algolia/client-common": "4.23.2", + "@algolia/requester-common": "4.23.2", + "@algolia/transporter": "4.23.2" } }, "node_modules/@algolia/client-search": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.22.0.tgz", - "integrity": "sha512-bn4qQiIdRPBGCwsNuuqB8rdHhGKKWIij9OqidM1UkQxnSG8yzxHdb7CujM30pvp5EnV7jTqDZRbxacbjYVW20Q==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.23.2.tgz", + "integrity": "sha512-CxSB29OVGSE7l/iyoHvamMonzq7Ev8lnk/OkzleODZ1iBcCs3JC/XgTIKzN/4RSTrJ9QybsnlrN/bYCGufo7qw==", "dependencies": { - "@algolia/client-common": "4.22.0", - "@algolia/requester-common": "4.22.0", - "@algolia/transporter": "4.22.0" + "@algolia/client-common": "4.23.2", + "@algolia/requester-common": "4.23.2", + "@algolia/transporter": "4.23.2" } }, "node_modules/@algolia/events": { @@ -170,47 +171,65 @@ "integrity": "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==" }, "node_modules/@algolia/logger-common": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.22.0.tgz", - "integrity": "sha512-HMUQTID0ucxNCXs5d1eBJ5q/HuKg8rFVE/vOiLaM4Abfeq1YnTtGV3+rFEhOPWhRQxNDd+YHa4q864IMc0zHpQ==" + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.23.2.tgz", + "integrity": "sha512-jGM49Q7626cXZ7qRAWXn0jDlzvoA1FvN4rKTi1g0hxKsTTSReyYk0i1ADWjChDPl3Q+nSDhJuosM2bBUAay7xw==" }, "node_modules/@algolia/logger-console": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.22.0.tgz", - "integrity": "sha512-7JKb6hgcY64H7CRm3u6DRAiiEVXMvCJV5gRE672QFOUgDxo4aiDpfU61g6Uzy8NKjlEzHMmgG4e2fklELmPXhQ==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.23.2.tgz", + "integrity": "sha512-oo+lnxxEmlhTBTFZ3fGz1O8PJ+G+8FiAoMY2Qo3Q4w23xocQev6KqDTA1JQAGPDxAewNA2VBwWOsVXeXFjrI/Q==", "dependencies": { - "@algolia/logger-common": "4.22.0" + "@algolia/logger-common": "4.23.2" + } + }, + "node_modules/@algolia/recommend": { + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-4.23.2.tgz", + "integrity": "sha512-Q75CjnzRCDzgIlgWfPnkLtrfF4t82JCirhalXkSSwe/c1GH5pWh4xUyDOR3KTMo+YxxX3zTlrL/FjHmUJEWEcg==", + "dependencies": { + "@algolia/cache-browser-local-storage": "4.23.2", + "@algolia/cache-common": "4.23.2", + "@algolia/cache-in-memory": "4.23.2", + "@algolia/client-common": "4.23.2", + "@algolia/client-search": "4.23.2", + "@algolia/logger-common": "4.23.2", + "@algolia/logger-console": "4.23.2", + "@algolia/requester-browser-xhr": "4.23.2", + "@algolia/requester-common": "4.23.2", + "@algolia/requester-node-http": "4.23.2", + "@algolia/transporter": "4.23.2" } }, "node_modules/@algolia/requester-browser-xhr": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.22.0.tgz", - "integrity": "sha512-BHfv1h7P9/SyvcDJDaRuIwDu2yrDLlXlYmjvaLZTtPw6Ok/ZVhBR55JqW832XN/Fsl6k3LjdkYHHR7xnsa5Wvg==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.23.2.tgz", + "integrity": "sha512-TO9wLlp8+rvW9LnIfyHsu8mNAMYrqNdQ0oLF6eTWFxXfxG3k8F/Bh7nFYGk2rFAYty4Fw4XUtrv/YjeNDtM5og==", "dependencies": { - "@algolia/requester-common": "4.22.0" + "@algolia/requester-common": "4.23.2" } }, "node_modules/@algolia/requester-common": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.22.0.tgz", - "integrity": "sha512-Y9cEH/cKjIIZgzvI1aI0ARdtR/xRrOR13g5psCxkdhpgRN0Vcorx+zePhmAa4jdQNqexpxtkUdcKYugBzMZJgQ==" + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.23.2.tgz", + "integrity": "sha512-3EfpBS0Hri0lGDB5H/BocLt7Vkop0bTTLVUBB844HH6tVycwShmsV6bDR7yXbQvFP1uNpgePRD3cdBCjeHmk6Q==" }, "node_modules/@algolia/requester-node-http": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.22.0.tgz", - "integrity": "sha512-8xHoGpxVhz3u2MYIieHIB6MsnX+vfd5PS4REgglejJ6lPigftRhTdBCToe6zbwq4p0anZXjjPDvNWMlgK2+xYA==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.23.2.tgz", + "integrity": "sha512-SVzgkZM/malo+2SB0NWDXpnT7nO5IZwuDTaaH6SjLeOHcya1o56LSWXk+3F3rNLz2GVH+I/rpYKiqmHhSOjerw==", "dependencies": { - "@algolia/requester-common": "4.22.0" + "@algolia/requester-common": "4.23.2" } }, "node_modules/@algolia/transporter": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.22.0.tgz", - "integrity": "sha512-ieO1k8x2o77GNvOoC+vAkFKppydQSVfbjM3YrSjLmgywiBejPTvU1R1nEvG59JIIUvtSLrZsLGPkd6vL14zopA==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.23.2.tgz", + "integrity": "sha512-GY3aGKBy+8AK4vZh8sfkatDciDVKad5rTY2S10Aefyjh7e7UGBP4zigf42qVXwU8VOPwi7l/L7OACGMOFcjB0Q==", "dependencies": { - "@algolia/cache-common": "4.22.0", - "@algolia/logger-common": "4.22.0", - "@algolia/requester-common": "4.22.0" + "@algolia/cache-common": "4.23.2", + "@algolia/logger-common": "4.23.2", + "@algolia/requester-common": "4.23.2" } }, "node_modules/@alloc/quick-lru": { @@ -2033,18 +2052,18 @@ } }, "node_modules/@docsearch/css": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.5.2.tgz", - "integrity": "sha512-SPiDHaWKQZpwR2siD0KQUwlStvIAnEyK6tAE2h2Wuoq8ue9skzhlyVQ1ddzOxX6khULnAALDiR/isSF3bnuciA==" + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.6.0.tgz", + "integrity": "sha512-+sbxb71sWre+PwDK7X2T8+bhS6clcVMLwBPznX45Qu6opJcgRjAp7gYSDzVFp187J+feSj5dNBN1mJoi6ckkUQ==" }, "node_modules/@docsearch/react": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.5.2.tgz", - "integrity": "sha512-9Ahcrs5z2jq/DcAvYtvlqEBHImbm4YJI8M9y0x6Tqg598P40HTEkX7hsMcIuThI+hTFxRGZ9hll0Wygm2yEjng==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.6.0.tgz", + "integrity": "sha512-HUFut4ztcVNmqy9gp/wxNbC7pTOHhgVVkHVGCACTuLhUKUhKAF9KYHJtMiLUJxEqiFLQiuri1fWF8zqwM/cu1w==", "dependencies": { "@algolia/autocomplete-core": "1.9.3", "@algolia/autocomplete-preset-algolia": "1.9.3", - "@docsearch/css": "3.5.2", + "@docsearch/css": "3.6.0", "algoliasearch": "^4.19.1" }, "peerDependencies": { @@ -2069,9 +2088,9 @@ } }, "node_modules/@docusaurus/core": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.0.1.tgz", - "integrity": "sha512-CXrLpOnW+dJdSv8M5FAJ3JBwXtL6mhUWxFA8aS0ozK6jBG/wgxERk5uvH28fCeFxOGbAT9v1e9dOMo1X2IEVhQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.2.0.tgz", + "integrity": "sha512-WTO6vW4404nhTmK9NL+95nd13I1JveFwZ8iOBYxb4xt+N2S3KzY+mm+1YtWw2vV37FbYfH+w+KrlrRaWuy5Hzw==", "dependencies": { "@babel/core": "^7.23.3", "@babel/generator": "^7.23.3", @@ -2083,14 +2102,13 @@ "@babel/runtime": "^7.22.6", "@babel/runtime-corejs3": "^7.22.6", "@babel/traverse": "^7.22.8", - "@docusaurus/cssnano-preset": "3.0.1", - "@docusaurus/logger": "3.0.1", - "@docusaurus/mdx-loader": "3.0.1", + "@docusaurus/cssnano-preset": "3.2.0", + "@docusaurus/logger": "3.2.0", + "@docusaurus/mdx-loader": "3.2.0", "@docusaurus/react-loadable": "5.5.2", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-common": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", - "@slorber/static-site-generator-webpack-plugin": "^4.0.7", + "@docusaurus/utils": "3.2.0", + "@docusaurus/utils-common": "3.2.0", + "@docusaurus/utils-validation": "3.2.0", "@svgr/webpack": "^6.5.1", "autoprefixer": "^10.4.14", "babel-loader": "^9.1.3", @@ -2111,6 +2129,7 @@ "detect-port": "^1.5.1", "escape-html": "^1.0.3", "eta": "^2.2.0", + "eval": "^0.1.8", "file-loader": "^6.2.0", "fs-extra": "^11.1.1", "html-minifier-terser": "^7.2.0", @@ -2119,6 +2138,7 @@ "leven": "^3.1.0", "lodash": "^4.17.21", "mini-css-extract-plugin": "^2.7.6", + "p-map": "^4.0.0", "postcss": "^8.4.26", "postcss-loader": "^7.3.3", "prompts": "^2.4.2", @@ -2249,9 +2269,9 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/@docusaurus/cssnano-preset": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.0.1.tgz", - "integrity": "sha512-wjuXzkHMW+ig4BD6Ya1Yevx9UJadO4smNZCEljqBoQfIQrQskTswBs7lZ8InHP7mCt273a/y/rm36EZhqJhknQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.2.0.tgz", + "integrity": "sha512-H88RXGUia7r/VF3XfyoA4kbwgpUZcKsObF6VvwBOP91EdArTf6lnHbJ/x8Ca79KS/zf98qaWyBGzW+5ez58Iyw==", "dependencies": { "cssnano-preset-advanced": "^5.3.10", "postcss": "^8.4.26", @@ -2263,9 +2283,9 @@ } }, "node_modules/@docusaurus/logger": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.0.1.tgz", - "integrity": "sha512-I5L6Nk8OJzkVA91O2uftmo71LBSxe1vmOn9AMR6JRCzYeEBrqneWMH02AqMvjJ2NpMiviO+t0CyPjyYV7nxCWQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.2.0.tgz", + "integrity": "sha512-Z1R1NcOGXZ8CkIJSvjvyxnuDDSlx/+1xlh20iVTw1DZRjonFmI3T3tTgk40YpXyWUYQpIgAoqqPMpuseMMdgRQ==", "dependencies": { "chalk": "^4.1.2", "tslib": "^2.6.0" @@ -2339,11 +2359,11 @@ } }, "node_modules/@docusaurus/lqip-loader": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/lqip-loader/-/lqip-loader-3.0.1.tgz", - "integrity": "sha512-hFSu8ltYo0ZnWBWmjMhSprOr6nNKG01YdMDxH/hahBfyaNDCkZU4o7mQNgUW845lvYdp6bhjyW31WJwBjOnLqw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/lqip-loader/-/lqip-loader-3.2.0.tgz", + "integrity": "sha512-lmYT3fslGH3ibdXySSUgtd4E3B8sQ7xizlNhmTj5eiqSQdiRiD15rVH73RohK8h+yrbu2QUDHTDAH6j7O5e2Gg==", "dependencies": { - "@docusaurus/logger": "3.0.1", + "@docusaurus/logger": "3.2.0", "file-loader": "^6.2.0", "lodash": "^4.17.21", "sharp": "^0.32.3", @@ -2354,15 +2374,13 @@ } }, "node_modules/@docusaurus/mdx-loader": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.0.1.tgz", - "integrity": "sha512-ldnTmvnvlrONUq45oKESrpy+lXtbnTcTsFkOTIDswe5xx5iWJjt6eSa0f99ZaWlnm24mlojcIGoUWNCS53qVlQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.2.0.tgz", + "integrity": "sha512-JtkI5o6R/rJSr1Y23cHKz085aBJCvJw3AYHihJ7r+mBX+O8EuQIynG0e6/XpbSCpr7Ino0U50UtxaXcEbFwg9Q==", "dependencies": { - "@babel/parser": "^7.22.7", - "@babel/traverse": "^7.22.8", - "@docusaurus/logger": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/logger": "3.2.0", + "@docusaurus/utils": "3.2.0", + "@docusaurus/utils-validation": "3.2.0", "@mdx-js/mdx": "^3.0.0", "@slorber/remark-comment": "^1.0.0", "escape-html": "^1.0.3", @@ -2394,13 +2412,12 @@ } }, "node_modules/@docusaurus/module-type-aliases": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-2.4.1.tgz", - "integrity": "sha512-gLBuIFM8Dp2XOCWffUDSjtxY7jQgKvYujt7Mx5s4FCTfoL5dN1EVbnrn+O2Wvh8b0a77D57qoIDY7ghgmatR1A==", - "dev": true, + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.2.0.tgz", + "integrity": "sha512-jRSp9YkvBwwNz6Xgy0RJPsnie+Ebb//gy7GdbkJ2pW2gvvlYKGib2+jSF0pfIzvyZLulfCynS1KQdvDKdSl8zQ==", "dependencies": { "@docusaurus/react-loadable": "5.5.2", - "@docusaurus/types": "2.4.1", + "@docusaurus/types": "3.2.0", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -2413,38 +2430,18 @@ "react-dom": "*" } }, - "node_modules/@docusaurus/module-type-aliases/node_modules/@docusaurus/types": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-2.4.1.tgz", - "integrity": "sha512-0R+cbhpMkhbRXX138UOc/2XZFF8hiZa6ooZAEEJFp5scytzCw4tC1gChMFXrpa3d2tYE6AX8IrOEpSonLmfQuQ==", - "dev": true, - "dependencies": { - "@types/history": "^4.7.11", - "@types/react": "*", - "commander": "^5.1.0", - "joi": "^17.6.0", - "react-helmet-async": "^1.3.0", - "utility-types": "^3.10.0", - "webpack": "^5.73.0", - "webpack-merge": "^5.8.0" - }, - "peerDependencies": { - "react": "^16.8.4 || ^17.0.0", - "react-dom": "^16.8.4 || ^17.0.0" - } - }, "node_modules/@docusaurus/plugin-content-blog": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.0.1.tgz", - "integrity": "sha512-cLOvtvAyaMQFLI8vm4j26svg3ktxMPSXpuUJ7EERKoGbfpJSsgtowNHcRsaBVmfuCsRSk1HZ/yHBsUkTmHFEsg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.2.0.tgz", + "integrity": "sha512-MABqwjSicyHmYEfQueMthPCz18JkVxhK3EGhXTSRWwReAZ0UTuw9pG6+Wo+uXAugDaIcJH28rVZSwTDINPm2bw==", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/logger": "3.0.1", - "@docusaurus/mdx-loader": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-common": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/core": "3.2.0", + "@docusaurus/logger": "3.2.0", + "@docusaurus/mdx-loader": "3.2.0", + "@docusaurus/types": "3.2.0", + "@docusaurus/utils": "3.2.0", + "@docusaurus/utils-common": "3.2.0", + "@docusaurus/utils-validation": "3.2.0", "cheerio": "^1.0.0-rc.12", "feed": "^4.2.2", "fs-extra": "^11.1.1", @@ -2465,17 +2462,18 @@ } }, "node_modules/@docusaurus/plugin-content-docs": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.0.1.tgz", - "integrity": "sha512-dRfAOA5Ivo+sdzzJGXEu33yAtvGg8dlZkvt/NEJ7nwi1F2j4LEdsxtfX2GKeETB2fP6XoGNSQnFXqa2NYGrHFg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.2.0.tgz", + "integrity": "sha512-uuqhahmsBnirxOz+SXksnWt7+wc+iN4ntxNRH48BUgo7QRNLATWjHCgI8t6zrMJxK4o+QL9DhLaPDlFHs91B3Q==", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/logger": "3.0.1", - "@docusaurus/mdx-loader": "3.0.1", - "@docusaurus/module-type-aliases": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/core": "3.2.0", + "@docusaurus/logger": "3.2.0", + "@docusaurus/mdx-loader": "3.2.0", + "@docusaurus/module-type-aliases": "3.2.0", + "@docusaurus/types": "3.2.0", + "@docusaurus/utils": "3.2.0", + "@docusaurus/utils-common": "3.2.0", + "@docusaurus/utils-validation": "3.2.0", "@types/react-router-config": "^5.0.7", "combine-promises": "^1.1.0", "fs-extra": "^11.1.1", @@ -2493,35 +2491,16 @@ "react-dom": "^18.0.0" } }, - "node_modules/@docusaurus/plugin-content-docs/node_modules/@docusaurus/module-type-aliases": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.0.1.tgz", - "integrity": "sha512-DEHpeqUDsLynl3AhQQiO7AbC7/z/lBra34jTcdYuvp9eGm01pfH1wTVq8YqWZq6Jyx0BgcVl/VJqtE9StRd9Ag==", - "dependencies": { - "@docusaurus/react-loadable": "5.5.2", - "@docusaurus/types": "3.0.1", - "@types/history": "^4.7.11", - "@types/react": "*", - "@types/react-router-config": "*", - "@types/react-router-dom": "*", - "react-helmet-async": "*", - "react-loadable": "npm:@docusaurus/react-loadable@5.5.2" - }, - "peerDependencies": { - "react": "*", - "react-dom": "*" - } - }, "node_modules/@docusaurus/plugin-content-pages": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.0.1.tgz", - "integrity": "sha512-oP7PoYizKAXyEttcvVzfX3OoBIXEmXTMzCdfmC4oSwjG4SPcJsRge3mmI6O8jcZBgUPjIzXD21bVGWEE1iu8gg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.2.0.tgz", + "integrity": "sha512-4ofAN7JDsdb4tODO9OIrizWY5DmEJXr0eu+UDIkLqGP+gXXTahJZv8h2mlxO+lPXGXRCVBOfA14OG1hOYJVPwA==", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/mdx-loader": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/core": "3.2.0", + "@docusaurus/mdx-loader": "3.2.0", + "@docusaurus/types": "3.2.0", + "@docusaurus/utils": "3.2.0", + "@docusaurus/utils-validation": "3.2.0", "fs-extra": "^11.1.1", "tslib": "^2.6.0", "webpack": "^5.88.1" @@ -2535,13 +2514,13 @@ } }, "node_modules/@docusaurus/plugin-debug": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.0.1.tgz", - "integrity": "sha512-09dxZMdATky4qdsZGzhzlUvvC+ilQ2hKbYF+wez+cM2mGo4qHbv8+qKXqxq0CQZyimwlAOWQLoSozIXU0g0i7g==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.2.0.tgz", + "integrity": "sha512-p6WxtO5XZGz66y6QNQtCJwBefq4S6/w75XaXVvH1/2P9uaijvF7R+Cm2EWQZ5WsvA5wl//DFWblyDHRyVC207Q==", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils": "3.0.1", + "@docusaurus/core": "3.2.0", + "@docusaurus/types": "3.2.0", + "@docusaurus/utils": "3.2.0", "fs-extra": "^11.1.1", "react-json-view-lite": "^1.2.0", "tslib": "^2.6.0" @@ -2555,13 +2534,13 @@ } }, "node_modules/@docusaurus/plugin-google-analytics": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.0.1.tgz", - "integrity": "sha512-jwseSz1E+g9rXQwDdr0ZdYNjn8leZBnKPjjQhMBEiwDoenL3JYFcNW0+p0sWoVF/f2z5t7HkKA+cYObrUh18gg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.2.0.tgz", + "integrity": "sha512-//TepJTEyAZSvBwHKEbXHu9xT/VkK3wUil2ZakKvQZYfUC01uWn6A1E3toa8R7WhCy1xPUeIukqmJy1Clg8njQ==", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/core": "3.2.0", + "@docusaurus/types": "3.2.0", + "@docusaurus/utils-validation": "3.2.0", "tslib": "^2.6.0" }, "engines": { @@ -2573,13 +2552,13 @@ } }, "node_modules/@docusaurus/plugin-google-gtag": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.0.1.tgz", - "integrity": "sha512-UFTDvXniAWrajsulKUJ1DB6qplui1BlKLQZjX4F7qS/qfJ+qkKqSkhJ/F4VuGQ2JYeZstYb+KaUzUzvaPK1aRQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.2.0.tgz", + "integrity": "sha512-3s6zxlaMMb87MW2Rxy6EnSRDs0WDEQPuHilZZH402C8kOrUnIwlhlfjWZ4ZyLDziGl/Eec/DvD0PVqj0qHRomA==", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/core": "3.2.0", + "@docusaurus/types": "3.2.0", + "@docusaurus/utils-validation": "3.2.0", "@types/gtag.js": "^0.0.12", "tslib": "^2.6.0" }, @@ -2592,13 +2571,13 @@ } }, "node_modules/@docusaurus/plugin-google-tag-manager": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.0.1.tgz", - "integrity": "sha512-IPFvuz83aFuheZcWpTlAdiiX1RqWIHM+OH8wS66JgwAKOiQMR3+nLywGjkLV4bp52x7nCnwhNk1rE85Cpy/CIw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.2.0.tgz", + "integrity": "sha512-rAKtsJ11vPHA7dTAqWCgyIy7AyFRF/lpI77Zd/4HKgqcIvIayVBvL3QtelhUazfYTLTH6ls6kQ9wjMcIFxRiGg==", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/core": "3.2.0", + "@docusaurus/types": "3.2.0", + "@docusaurus/utils-validation": "3.2.0", "tslib": "^2.6.0" }, "engines": { @@ -2610,16 +2589,16 @@ } }, "node_modules/@docusaurus/plugin-ideal-image": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-ideal-image/-/plugin-ideal-image-3.0.1.tgz", - "integrity": "sha512-IvAUpEIz6v1/fVz6UTdQY12pYIE5geNFtsuKpsULpMaotwYf3Gs7acXjQog4qquKkc65yV5zuvMj8BZMHEwLyQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-ideal-image/-/plugin-ideal-image-3.2.0.tgz", + "integrity": "sha512-FPvNyOmSRBnSUQkiti7098N9W950EC4z7hXRn5ZwaG7Q+JGLdXC7sYWyTsjR5KZbEGolJWG1uyi+bG2vd1zDsw==", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/lqip-loader": "3.0.1", + "@docusaurus/core": "3.2.0", + "@docusaurus/lqip-loader": "3.2.0", "@docusaurus/responsive-loader": "^1.7.0", - "@docusaurus/theme-translations": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/theme-translations": "3.2.0", + "@docusaurus/types": "3.2.0", + "@docusaurus/utils-validation": "3.2.0", "@slorber/react-ideal-image": "^0.0.12", "react-waypoint": "^10.3.0", "sharp": "^0.32.3", @@ -2641,16 +2620,16 @@ } }, "node_modules/@docusaurus/plugin-sitemap": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.0.1.tgz", - "integrity": "sha512-xARiWnjtVvoEniZudlCq5T9ifnhCu/GAZ5nA7XgyLfPcNpHQa241HZdsTlLtVcecEVVdllevBKOp7qknBBaMGw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.2.0.tgz", + "integrity": "sha512-gnWDFt6MStjLkdtt63Lzc+14EPSd8B6mzJGJp9GQMvWDUoMAUijUqpVIHYQq+DPMcI4PJZ5I2nsl5XFf1vOldA==", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/logger": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-common": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/core": "3.2.0", + "@docusaurus/logger": "3.2.0", + "@docusaurus/types": "3.2.0", + "@docusaurus/utils": "3.2.0", + "@docusaurus/utils-common": "3.2.0", + "@docusaurus/utils-validation": "3.2.0", "fs-extra": "^11.1.1", "sitemap": "^7.1.1", "tslib": "^2.6.0" @@ -2664,23 +2643,23 @@ } }, "node_modules/@docusaurus/preset-classic": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.0.1.tgz", - "integrity": "sha512-il9m9xZKKjoXn6h0cRcdnt6wce0Pv1y5t4xk2Wx7zBGhKG1idu4IFHtikHlD0QPuZ9fizpXspXcTzjL5FXc1Gw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.2.0.tgz", + "integrity": "sha512-t7tXyk8kUgT7hUqEOgSJnPs+Foem9ucuan/a9QVYaVFCDjp92Sb2FpCY8bVasAokYCjodYe2LfpAoSCj5YDYWg==", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/plugin-content-blog": "3.0.1", - "@docusaurus/plugin-content-docs": "3.0.1", - "@docusaurus/plugin-content-pages": "3.0.1", - "@docusaurus/plugin-debug": "3.0.1", - "@docusaurus/plugin-google-analytics": "3.0.1", - "@docusaurus/plugin-google-gtag": "3.0.1", - "@docusaurus/plugin-google-tag-manager": "3.0.1", - "@docusaurus/plugin-sitemap": "3.0.1", - "@docusaurus/theme-classic": "3.0.1", - "@docusaurus/theme-common": "3.0.1", - "@docusaurus/theme-search-algolia": "3.0.1", - "@docusaurus/types": "3.0.1" + "@docusaurus/core": "3.2.0", + "@docusaurus/plugin-content-blog": "3.2.0", + "@docusaurus/plugin-content-docs": "3.2.0", + "@docusaurus/plugin-content-pages": "3.2.0", + "@docusaurus/plugin-debug": "3.2.0", + "@docusaurus/plugin-google-analytics": "3.2.0", + "@docusaurus/plugin-google-gtag": "3.2.0", + "@docusaurus/plugin-google-tag-manager": "3.2.0", + "@docusaurus/plugin-sitemap": "3.2.0", + "@docusaurus/theme-classic": "3.2.0", + "@docusaurus/theme-common": "3.2.0", + "@docusaurus/theme-search-algolia": "3.2.0", + "@docusaurus/types": "3.2.0" }, "engines": { "node": ">=18.0" @@ -2726,22 +2705,22 @@ } }, "node_modules/@docusaurus/theme-classic": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.0.1.tgz", - "integrity": "sha512-XD1FRXaJiDlmYaiHHdm27PNhhPboUah9rqIH0lMpBt5kYtsGjJzhqa27KuZvHLzOP2OEpqd2+GZ5b6YPq7Q05Q==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.2.0.tgz", + "integrity": "sha512-4oSO5BQOJ5ja7WYdL6jK1n4J96tp+VJHamdwao6Ea252sA3W3vvR0otTflG4p4XVjNZH6hlPQoi5lKW0HeRgfQ==", "dependencies": { - "@docusaurus/core": "3.0.1", - "@docusaurus/mdx-loader": "3.0.1", - "@docusaurus/module-type-aliases": "3.0.1", - "@docusaurus/plugin-content-blog": "3.0.1", - "@docusaurus/plugin-content-docs": "3.0.1", - "@docusaurus/plugin-content-pages": "3.0.1", - "@docusaurus/theme-common": "3.0.1", - "@docusaurus/theme-translations": "3.0.1", - "@docusaurus/types": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-common": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/core": "3.2.0", + "@docusaurus/mdx-loader": "3.2.0", + "@docusaurus/module-type-aliases": "3.2.0", + "@docusaurus/plugin-content-blog": "3.2.0", + "@docusaurus/plugin-content-docs": "3.2.0", + "@docusaurus/plugin-content-pages": "3.2.0", + "@docusaurus/theme-common": "3.2.0", + "@docusaurus/theme-translations": "3.2.0", + "@docusaurus/types": "3.2.0", + "@docusaurus/utils": "3.2.0", + "@docusaurus/utils-common": "3.2.0", + "@docusaurus/utils-validation": "3.2.0", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "copy-text-to-clipboard": "^3.2.0", @@ -2764,29 +2743,10 @@ "react-dom": "^18.0.0" } }, - "node_modules/@docusaurus/theme-classic/node_modules/@docusaurus/module-type-aliases": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.0.1.tgz", - "integrity": "sha512-DEHpeqUDsLynl3AhQQiO7AbC7/z/lBra34jTcdYuvp9eGm01pfH1wTVq8YqWZq6Jyx0BgcVl/VJqtE9StRd9Ag==", - "dependencies": { - "@docusaurus/react-loadable": "5.5.2", - "@docusaurus/types": "3.0.1", - "@types/history": "^4.7.11", - "@types/react": "*", - "@types/react-router-config": "*", - "@types/react-router-dom": "*", - "react-helmet-async": "*", - "react-loadable": "npm:@docusaurus/react-loadable@5.5.2" - }, - "peerDependencies": { - "react": "*", - "react-dom": "*" - } - }, "node_modules/@docusaurus/theme-classic/node_modules/@mdx-js/react": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.0.tgz", - "integrity": "sha512-nDctevR9KyYFyV+m+/+S4cpzCWHqj+iHDHq3QrsWezcC+B17uZdIWgCguESUkwFhM3n/56KxWVE3V6EokrmONQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", + "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", "dependencies": { "@types/mdx": "^2.0.0" }, @@ -2800,9 +2760,9 @@ } }, "node_modules/@docusaurus/theme-classic/node_modules/clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", + "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==", "engines": { "node": ">=6" } @@ -2820,17 +2780,17 @@ } }, "node_modules/@docusaurus/theme-common": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.0.1.tgz", - "integrity": "sha512-cr9TOWXuIOL0PUfuXv6L5lPlTgaphKP+22NdVBOYah5jSq5XAAulJTjfe+IfLsEG4L7lJttLbhW7LXDFSAI7Ag==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.2.0.tgz", + "integrity": "sha512-sFbw9XviNJJ+760kAcZCQMQ3jkNIznGqa6MQ70E5BnbP+ja36kGgPOfjcsvAcNey1H1Rkhh3p2Mhf4HVLdKVVw==", "dependencies": { - "@docusaurus/mdx-loader": "3.0.1", - "@docusaurus/module-type-aliases": "3.0.1", - "@docusaurus/plugin-content-blog": "3.0.1", - "@docusaurus/plugin-content-docs": "3.0.1", - "@docusaurus/plugin-content-pages": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-common": "3.0.1", + "@docusaurus/mdx-loader": "3.2.0", + "@docusaurus/module-type-aliases": "3.2.0", + "@docusaurus/plugin-content-blog": "3.2.0", + "@docusaurus/plugin-content-docs": "3.2.0", + "@docusaurus/plugin-content-pages": "3.2.0", + "@docusaurus/utils": "3.2.0", + "@docusaurus/utils-common": "3.2.0", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -2848,29 +2808,10 @@ "react-dom": "^18.0.0" } }, - "node_modules/@docusaurus/theme-common/node_modules/@docusaurus/module-type-aliases": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.0.1.tgz", - "integrity": "sha512-DEHpeqUDsLynl3AhQQiO7AbC7/z/lBra34jTcdYuvp9eGm01pfH1wTVq8YqWZq6Jyx0BgcVl/VJqtE9StRd9Ag==", - "dependencies": { - "@docusaurus/react-loadable": "5.5.2", - "@docusaurus/types": "3.0.1", - "@types/history": "^4.7.11", - "@types/react": "*", - "@types/react-router-config": "*", - "@types/react-router-dom": "*", - "react-helmet-async": "*", - "react-loadable": "npm:@docusaurus/react-loadable@5.5.2" - }, - "peerDependencies": { - "react": "*", - "react-dom": "*" - } - }, "node_modules/@docusaurus/theme-common/node_modules/clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", + "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==", "engines": { "node": ">=6" } @@ -2888,18 +2829,18 @@ } }, "node_modules/@docusaurus/theme-search-algolia": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.0.1.tgz", - "integrity": "sha512-DDiPc0/xmKSEdwFkXNf1/vH1SzJPzuJBar8kMcBbDAZk/SAmo/4lf6GU2drou4Ae60lN2waix+jYWTWcJRahSA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.2.0.tgz", + "integrity": "sha512-PgvF4qHoqJp8+GfqClUbTF/zYNOsz4De251IuzXon7+7FAXwvb2qmYtA2nEwyMbB7faKOz33Pxzv+y+153KS/g==", "dependencies": { "@docsearch/react": "^3.5.2", - "@docusaurus/core": "3.0.1", - "@docusaurus/logger": "3.0.1", - "@docusaurus/plugin-content-docs": "3.0.1", - "@docusaurus/theme-common": "3.0.1", - "@docusaurus/theme-translations": "3.0.1", - "@docusaurus/utils": "3.0.1", - "@docusaurus/utils-validation": "3.0.1", + "@docusaurus/core": "3.2.0", + "@docusaurus/logger": "3.2.0", + "@docusaurus/plugin-content-docs": "3.2.0", + "@docusaurus/theme-common": "3.2.0", + "@docusaurus/theme-translations": "3.2.0", + "@docusaurus/utils": "3.2.0", + "@docusaurus/utils-validation": "3.2.0", "algoliasearch": "^4.18.0", "algoliasearch-helper": "^3.13.3", "clsx": "^2.0.0", @@ -2918,17 +2859,17 @@ } }, "node_modules/@docusaurus/theme-search-algolia/node_modules/clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", + "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==", "engines": { "node": ">=6" } }, "node_modules/@docusaurus/theme-translations": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.0.1.tgz", - "integrity": "sha512-6UrbpzCTN6NIJnAtZ6Ne9492vmPVX+7Fsz4kmp+yor3KQwA1+MCzQP7ItDNkP38UmVLnvB/cYk/IvehCUqS3dg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.2.0.tgz", + "integrity": "sha512-VXzZJBuyVEmwUYyud+7IgJQEBRM6R2u/s10Rp3DOP19CBQxeKgHYTKkKhFtDeKMHDassb665kjgOi0YlJfUT6w==", "dependencies": { "fs-extra": "^11.1.1", "tslib": "^2.6.0" @@ -2938,10 +2879,11 @@ } }, "node_modules/@docusaurus/types": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.0.1.tgz", - "integrity": "sha512-plyX2iU1tcUsF46uQ01pAd4JhexR7n0iiQ5MSnBFX6M6NSJgDYdru/i1/YNPKOnQHBoXGLHv0dNT6OAlDWNjrg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.2.0.tgz", + "integrity": "sha512-uG3FfTkkkbZIPPNYx6xRfZHKeGyRd/inIT1cqvYt1FobFLd+7WhRXrSBqwJ9JajJjEAjNioRMVFgGofGf/Wdww==", "dependencies": { + "@mdx-js/mdx": "^3.0.0", "@types/history": "^4.7.11", "@types/react": "*", "commander": "^5.1.0", @@ -2957,11 +2899,12 @@ } }, "node_modules/@docusaurus/utils": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.0.1.tgz", - "integrity": "sha512-TwZ33Am0q4IIbvjhUOs+zpjtD/mXNmLmEgeTGuRq01QzulLHuPhaBTTAC/DHu6kFx3wDgmgpAlaRuCHfTcXv8g==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.2.0.tgz", + "integrity": "sha512-3rgrE7iL60yV2JQivlcoxUNNTK2APmn+OHLUmTvX2pueIM8DEOCEFHpJO4MiWjFO7V/Wq3iA/W1M03JnjdugVw==", "dependencies": { - "@docusaurus/logger": "3.0.1", + "@docusaurus/logger": "3.2.0", + "@docusaurus/utils-common": "3.2.0", "@svgr/webpack": "^6.5.1", "escape-string-regexp": "^4.0.0", "file-loader": "^6.2.0", @@ -2973,6 +2916,7 @@ "js-yaml": "^4.1.0", "lodash": "^4.17.21", "micromatch": "^4.0.5", + "prompts": "^2.4.2", "resolve-pathname": "^3.0.0", "shelljs": "^0.8.5", "tslib": "^2.6.0", @@ -2992,9 +2936,9 @@ } }, "node_modules/@docusaurus/utils-common": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.0.1.tgz", - "integrity": "sha512-W0AxD6w6T8g6bNro8nBRWf7PeZ/nn7geEWM335qHU2DDDjHuV4UZjgUGP1AQsdcSikPrlIqTJJbKzer1lRSlIg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.2.0.tgz", + "integrity": "sha512-WEQT5L2lT/tBQgDRgeZQAIi9YJBrwEILb1BuObQn1St3T/4K1gx5fWwOT8qdLOov296XLd1FQg9Ywu27aE9svw==", "dependencies": { "tslib": "^2.6.0" }, @@ -3011,12 +2955,13 @@ } }, "node_modules/@docusaurus/utils-validation": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.0.1.tgz", - "integrity": "sha512-ujTnqSfyGQ7/4iZdB4RRuHKY/Nwm58IIb+41s5tCXOv/MBU2wGAjOHq3U+AEyJ8aKQcHbxvTKJaRchNHYUVUQg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.2.0.tgz", + "integrity": "sha512-rCzMTqwNrBrEOyU8EaD1fYWdig4TDhfj+YLqB8DY68VUAqSIgbY+yshpqFKB0bznFYNBJbn0bGpvVuImQOa/vA==", "dependencies": { - "@docusaurus/logger": "3.0.1", - "@docusaurus/utils": "3.0.1", + "@docusaurus/logger": "3.2.0", + "@docusaurus/utils": "3.2.0", + "@docusaurus/utils-common": "3.2.0", "joi": "^17.9.2", "js-yaml": "^4.1.0", "tslib": "^2.6.0" @@ -3234,9 +3179,9 @@ "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" }, "node_modules/@mdx-js/mdx": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.0.0.tgz", - "integrity": "sha512-Icm0TBKBLYqroYbNW3BPnzMGn+7mwpQOK310aZ7+fkCtiU3aqv2cdcX+nd0Ydo3wI5Rx8bX2Z2QmGb/XcAClCw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.0.1.tgz", + "integrity": "sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA==", "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", @@ -3480,9 +3425,9 @@ } }, "node_modules/@sideway/address": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", - "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", "dependencies": { "@hapi/hoek": "^9.0.0" } @@ -3537,19 +3482,6 @@ "micromark-util-symbol": "^1.0.1" } }, - "node_modules/@slorber/static-site-generator-webpack-plugin": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.7.tgz", - "integrity": "sha512-Ug7x6z5lwrz0WqdnNFOMYrDQNTPAprvHLSh6+/fmml3qUiz6l5eq+2MzLKWtn/q5K5NpSiFsZTP/fck/3vjSxA==", - "dependencies": { - "eval": "^0.1.8", - "p-map": "^4.0.0", - "webpack-sources": "^3.2.2" - }, - "engines": { - "node": ">=14" - } - }, "node_modules/@svgr/babel-plugin-add-jsx-attribute": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz", @@ -3930,9 +3862,9 @@ "integrity": "sha512-YQV9bUsemkzG81Ea295/nF/5GijnD2Af7QhEofh7xu+kvCN6RdodgNwwGWXB5GMI3NoyvQo0odNctoH/qLMIpg==" }, "node_modules/@types/hast": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.3.tgz", - "integrity": "sha512-2fYGlaDy/qyLlhidX42wAH0KBi2TCjKMH8CHmBXgRlJ3Y+OXTiqsPQ6IWarZKwF1JoUcAJdPogv1d4b0COTpmQ==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", "dependencies": { "@types/unist": "*" } @@ -4505,30 +4437,31 @@ } }, "node_modules/algoliasearch": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.22.0.tgz", - "integrity": "sha512-gfceltjkwh7PxXwtkS8KVvdfK+TSNQAWUeNSxf4dA29qW5tf2EGwa8jkJujlT9jLm17cixMVoGNc+GJFO1Mxhg==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.23.2.tgz", + "integrity": "sha512-8aCl055IsokLuPU8BzLjwzXjb7ty9TPcUFFOk0pYOwsE5DMVhE3kwCMFtsCFKcnoPZK7oObm+H5mbnSO/9ioxQ==", "dependencies": { - "@algolia/cache-browser-local-storage": "4.22.0", - "@algolia/cache-common": "4.22.0", - "@algolia/cache-in-memory": "4.22.0", - "@algolia/client-account": "4.22.0", - "@algolia/client-analytics": "4.22.0", - "@algolia/client-common": "4.22.0", - "@algolia/client-personalization": "4.22.0", - "@algolia/client-search": "4.22.0", - "@algolia/logger-common": "4.22.0", - "@algolia/logger-console": "4.22.0", - "@algolia/requester-browser-xhr": "4.22.0", - "@algolia/requester-common": "4.22.0", - "@algolia/requester-node-http": "4.22.0", - "@algolia/transporter": "4.22.0" + "@algolia/cache-browser-local-storage": "4.23.2", + "@algolia/cache-common": "4.23.2", + "@algolia/cache-in-memory": "4.23.2", + "@algolia/client-account": "4.23.2", + "@algolia/client-analytics": "4.23.2", + "@algolia/client-common": "4.23.2", + "@algolia/client-personalization": "4.23.2", + "@algolia/client-search": "4.23.2", + "@algolia/logger-common": "4.23.2", + "@algolia/logger-console": "4.23.2", + "@algolia/recommend": "4.23.2", + "@algolia/requester-browser-xhr": "4.23.2", + "@algolia/requester-common": "4.23.2", + "@algolia/requester-node-http": "4.23.2", + "@algolia/transporter": "4.23.2" } }, "node_modules/algoliasearch-helper": { - "version": "3.16.1", - "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.16.1.tgz", - "integrity": "sha512-qxAHVjjmT7USVvrM8q6gZGaJlCK1fl4APfdAA7o8O6iXEc68G0xMNrzRkxoB/HmhhvyHnoteS/iMTiHiTcQQcg==", + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.17.0.tgz", + "integrity": "sha512-R5422OiQjvjlK3VdpNQ/Qk7KsTIGeM5ACm8civGifOVWdRRV/3SgXuKmeNxe94Dz6fwj/IgpVmXbHutU4mHubg==", "dependencies": { "@algolia/events": "^4.0.1" }, @@ -4928,12 +4861,12 @@ "dev": true }, "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -4941,7 +4874,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.1", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -6124,9 +6057,9 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "engines": { "node": ">= 0.6" } @@ -9620,16 +9553,16 @@ } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -10005,9 +9938,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", - "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -10923,9 +10856,9 @@ } }, "node_modules/hast-util-raw": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.0.1.tgz", - "integrity": "sha512-5m1gmba658Q+lO5uqL5YNGQWeh1MYWZbZmWrM5lncdcuiXuo5E2HT/CIOp0rLF8ksfSwiCVJ3twlgVRyTGThGA==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.0.2.tgz", + "integrity": "sha512-PldBy71wO9Uq1kyaMch9AHIghtQvIwxBUkv823pKmkTM3oV1JxtsTNYdevMxvUHqcnOAuO65JKU2+0NOxc2ksA==", "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", @@ -11000,16 +10933,16 @@ } }, "node_modules/hast-util-to-jsx-runtime/node_modules/inline-style-parser": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.2.tgz", - "integrity": "sha512-EcKzdTHVe8wFVOGEYXiW9WmJXPjqi1T+234YpJr98RiFYKHV3cdy1+3mkTE+KHTHxFFLH51SfaGOoUdW+v7ViQ==" + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.3.tgz", + "integrity": "sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g==" }, "node_modules/hast-util-to-jsx-runtime/node_modules/style-to-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.5.tgz", - "integrity": "sha512-rDRwHtoDD3UMMrmZ6BzOW0naTjMsVZLIjsGleSKS/0Oz+cgCfAPRspaqJuE8rDzpKha/nEvnM0IF4seEAZUTKQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.6.tgz", + "integrity": "sha512-khxq+Qm3xEyZfKd/y9L3oIWQimxuc4STrQKtQn8aSDRHb8mFgpukgX1hdzfrMEW6JCjyJ8p89x+IUMVnCBI1PA==", "dependencies": { - "inline-style-parser": "0.2.2" + "inline-style-parser": "0.2.3" } }, "node_modules/hast-util-to-parse5": { @@ -11688,9 +11621,9 @@ } }, "node_modules/ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", + "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==", "dev": true }, "node_modules/ipaddr.js": { @@ -12226,13 +12159,13 @@ } }, "node_modules/joi": { - "version": "17.11.0", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.11.0.tgz", - "integrity": "sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ==", + "version": "17.12.2", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.12.2.tgz", + "integrity": "sha512-RonXAIzCiHLc8ss3Ibuz45u28GOsWE1UpfDXLbN/9NKbL4tCJf8TWYVKsoYuuh+sAUt7fsSNpA+r2+TBA6Wjmw==", "dependencies": { - "@hapi/hoek": "^9.0.0", - "@hapi/topo": "^5.0.0", - "@sideway/address": "^4.1.3", + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", "@sideway/formula": "^3.0.1", "@sideway/pinpoint": "^2.0.0" } @@ -12820,9 +12753,9 @@ } }, "node_modules/mdast-util-gfm-autolink-literal/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -12948,9 +12881,9 @@ } }, "node_modules/mdast-util-mdx-jsx": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.0.0.tgz", - "integrity": "sha512-XZuPPzQNBPAlaqsTTgRrcJnyFbSOBovSadFgbFu8SnuNgm+6Bdx1K+IWoitsmj6Lq6MNtI+ytOqwN70n//NaBA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.2.tgz", + "integrity": "sha512-eKMQDeywY2wlHc97k5eD8VC+9ASMjN8ItEZQNGwJ6E0XWKiW/Z0V5/H8pvoXUf+y+Mj0VIgeRRbujBmFn4FTyA==", "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", @@ -12989,9 +12922,9 @@ } }, "node_modules/mdast-util-phrasing": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.0.0.tgz", - "integrity": "sha512-xadSsJayQIucJ9n053dfQwVu1kuXg7jCTdYsMK8rqzKZh52nLfSH/k0sAxE0u+pj/zKZX+o5wB+ML5mRayOxFA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", "dependencies": { "@types/mdast": "^4.0.0", "unist-util-is": "^6.0.0" @@ -13002,9 +12935,9 @@ } }, "node_modules/mdast-util-to-hast": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.0.2.tgz", - "integrity": "sha512-U5I+500EOOw9e3ZrclN3Is3fRpw8c19SMyNZlZ2IS+7vLsNzb2Om11VpIVOR+/0137GhZsFEF6YiKD5+0Hr2Og==", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.1.0.tgz", + "integrity": "sha512-/e2l/6+OdGp/FB+ctrJ9Avz71AN/GRH3oi/3KAx/kMnoUsD6q0woXlDT8lLEeViVKE7oZxE7RXzvO3T8kF2/sA==", "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", @@ -13013,7 +12946,8 @@ "micromark-util-sanitize-uri": "^2.0.0", "trim-lines": "^3.0.0", "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0" + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" }, "funding": { "type": "opencollective", @@ -13236,9 +13170,9 @@ } }, "node_modules/micromark-core-commonmark/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -13307,9 +13241,9 @@ } }, "node_modules/micromark-extension-directive/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -13356,9 +13290,9 @@ } }, "node_modules/micromark-extension-frontmatter/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -13424,9 +13358,9 @@ } }, "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -13496,9 +13430,9 @@ } }, "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -13597,9 +13531,9 @@ } }, "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -13678,9 +13612,9 @@ } }, "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -13756,9 +13690,9 @@ } }, "node_modules/micromark-extension-mdx-expression/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -13830,9 +13764,9 @@ } }, "node_modules/micromark-extension-mdx-jsx/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -13915,9 +13849,9 @@ } }, "node_modules/micromark-extension-mdxjs-esm/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -13969,9 +13903,9 @@ } }, "node_modules/micromark-factory-destination/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -14024,9 +13958,9 @@ } }, "node_modules/micromark-factory-label/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -14083,9 +14017,9 @@ } }, "node_modules/micromark-factory-mdx-expression/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -14191,9 +14125,9 @@ } }, "node_modules/micromark-factory-title/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -14265,9 +14199,9 @@ } }, "node_modules/micromark-factory-whitespace/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -14386,9 +14320,9 @@ } }, "node_modules/micromark-util-classify-character/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -14493,9 +14427,9 @@ } }, "node_modules/micromark-util-decode-string/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -14668,9 +14602,9 @@ } }, "node_modules/micromark-util-sanitize-uri/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -14787,9 +14721,9 @@ } }, "node_modules/micromark/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -17476,9 +17410,9 @@ } }, "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -17780,9 +17714,9 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/react-json-view-lite": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-1.2.1.tgz", - "integrity": "sha512-Itc0g86fytOmKZoIoJyGgvNqohWSbh3NXIKNgH6W6FT9PC1ck4xas1tT3Rr/b3UlFXyA9Jjaw9QSXdZy2JwGMQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-1.3.0.tgz", + "integrity": "sha512-aN1biKC5v4DQkmQBlZjuMFR09MKZGMPtIg+cut8zEeg2HXd6gl2gRy0n4HMacHf0dznQgo0SVXN7eT8zV3hEuQ==", "engines": { "node": ">=14" }, @@ -18587,9 +18521,9 @@ } }, "node_modules/remark-mdx": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.0.0.tgz", - "integrity": "sha512-O7yfjuC6ra3NHPbRVxfflafAj3LTwx3b73aBvkEFU5z4PsD6FD4vrqJAkE5iNGLz71GdjXfgRqm3SQ0h0VuE7g==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.0.1.tgz", + "integrity": "sha512-3Pz3yPQ5Rht2pM5R+0J2MrGoBSrzf+tJG94N+t/ilfdh8YLyyKYtidAYwTveB20BoHAcwIopOUqhcmh2F7hGYA==", "dependencies": { "mdast-util-mdx": "^3.0.0", "micromark-extension-mdxjs": "^3.0.0" @@ -19088,9 +19022,9 @@ } }, "node_modules/remark-rehype": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.0.0.tgz", - "integrity": "sha512-vx8x2MDMcxuE4lBmQ46zYUDfcFMmvg80WYX+UNLeG6ixjdCCLcw1lrgAukwBTuOFsS78eoAedHGn9sNM0w7TPw==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.0.tgz", + "integrity": "sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g==", "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", @@ -21778,9 +21712,9 @@ "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==" }, "node_modules/utility-types": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz", - "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.11.0.tgz", + "integrity": "sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==", "engines": { "node": ">= 4" } @@ -22018,9 +21952,9 @@ } }, "node_modules/webpack-dev-middleware": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", - "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", + "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", "dependencies": { "colorette": "^2.0.10", "memfs": "^3.4.3", diff --git a/docs/package.json b/docs/package.json index 35f38de59..87f3d3d71 100644 --- a/docs/package.json +++ b/docs/package.json @@ -16,11 +16,12 @@ "dependencies": { "@babel/preset-react": "^7.22.3", "@code-hike/mdx": "^0.9.0", - "@docusaurus/core": "3.0.1", - "@docusaurus/plugin-ideal-image": "^3.0.1", - "@docusaurus/preset-classic": "3.0.1", - "@docusaurus/theme-classic": "^3.0.1", - "@docusaurus/theme-search-algolia": "^3.0.1", + "@docusaurus/core": "^3.2.0", + "@docusaurus/plugin-google-gtag": "^3.2.0", + "@docusaurus/plugin-ideal-image": "^3.2.0", + "@docusaurus/preset-classic": "^3.2.0", + "@docusaurus/theme-classic": "^3.2.0", + "@docusaurus/theme-search-algolia": "^3.2.0", "@mdx-js/react": "^2.3.0", "@mendable/search": "^0.0.154", "@pbe/react-yandex-maps": "^1.2.4", @@ -47,7 +48,7 @@ "tailwindcss": "^3.3.2" }, "devDependencies": { - "@docusaurus/module-type-aliases": "2.4.1", + "@docusaurus/module-type-aliases": "^3.2.0", "css-loader": "^6.8.1", "docusaurus-node-polyfills": "^1.0.0", "node-sass": "^9.0.0", @@ -69,4 +70,4 @@ "engines": { "node": ">=16.14" } -} \ No newline at end of file +} diff --git a/docs/sidebars.js b/docs/sidebars.js index e238e1860..ddc9af202 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -2,13 +2,49 @@ module.exports = { docs: [ { type: "category", - label: "Getting Started", + label: " Getting Started", collapsed: false, items: [ "index", - "getting-started/installation", - "getting-started/hugging-face-spaces", - "getting-started/creating-flows", + "getting-started/cli", + "getting-started/basic-prompting", + "getting-started/document-qa", + "getting-started/blog-writer", + "getting-started/memory-chatbot", + "getting-started/rag-with-astradb", + ], + }, + { + type: "category", + label: " What's New", + collapsed: false, + items: [ + "whats-new/a-new-chapter-langflow", + "whats-new/migrating-to-one-point-zero", + ], + }, + + { + type: "category", + label: " Migration Guides", + collapsed: false, + items: [ + // "migration/flow-of-data", + "migration/inputs-and-outputs", + // "migration/supported-frameworks", + // "migration/sidebar-and-interaction-panel", + // "migration/new-categories-and-components", + "migration/text-and-record", + // "migration/custom-component", + "migration/compatibility", + // "migration/multiple-flows", + // "migration/component-status-and-data-passing", + // "migration/connecting-output-components", + // "migration/renaming-and-editing-components", + // "migration/passing-tweaks-and-inputs", + "migration/global-variables", + // "migration/experimental-components", + // "migration/state-management", ], }, { @@ -18,7 +54,6 @@ module.exports = { items: [ "guidelines/login", "guidelines/api", - "guidelines/async-api", "guidelines/components", "guidelines/features", "guidelines/collection", @@ -30,47 +65,42 @@ module.exports = { }, { type: "category", - label: "Component Reference", + label: "Step-by-Step Guides", + collapsed: false, + items: ["guides/langfuse_integration"], + }, + { + type: "category", + label: "Core Components", collapsed: false, items: [ - "components/agents", - "components/chains", - "components/custom", - "components/embeddings", - "components/llms", - "components/loaders", - "components/memories", - "components/prompts", - "components/retrievers", - "components/text-splitters", - "components/toolkits", - "components/tools", - "components/utilities", + "components/inputs", + "components/outputs", + "components/data", + "components/models", + "components/helpers", "components/vector-stores", - "components/wrappers", + "components/embeddings", ], }, { type: "category", - label: "Step-by-Step Guides", + label: "Extended Components", collapsed: false, items: [ - "guides/async-tasks", - "guides/loading_document", - "guides/chatprompttemplate_guide", - "guides/langfuse_integration", + "components/agents", + "components/chains", + "components/loaders", + "components/experimental", + "components/utilities", + "components/memories", + "components/model_specs", + "components/retrievers", + "components/text-splitters", + "components/toolkits", + "components/tools", ], }, - // { - // type: 'category', - // label: 'Components', - // collapsed: false, - // items: [ - // 'components/agents', 'components/chains', 'components/loaders', 'components/embeddings', 'components/llms', - // 'components/memories', 'components/prompts','components/text-splitters', 'components/toolkits', 'components/tools', - // 'components/utilities', 'components/vector-stores', 'components/wrappers', - // ], - // }, { type: "category", label: "Examples", @@ -79,13 +109,10 @@ module.exports = { "examples/flow-runner", "examples/conversation-chain", "examples/buffer-memory", - "examples/midjourney-prompt-chain", "examples/csv-loader", "examples/searchapi-tool", "examples/serp-api-tool", - "examples/multiple-vectorstores", "examples/python-function", - "examples/how-upload-examples", ], }, { diff --git a/docs/src/theme/DownloadableJsonFile.js b/docs/src/theme/DownloadableJsonFile.js new file mode 100644 index 000000000..7b5466eac --- /dev/null +++ b/docs/src/theme/DownloadableJsonFile.js @@ -0,0 +1,29 @@ +const DownloadableJsonFile = ({ source, title }) => { + const handleDownload = (event) => { + event.preventDefault(); + fetch(source) + .then((response) => response.blob()) + .then((blob) => { + const url = window.URL.createObjectURL( + new Blob([blob], { type: "application/json" }) + ); + const link = document.createElement("a"); + link.href = url; + link.setAttribute("download", title); + document.body.appendChild(link); + link.click(); + link.parentNode.removeChild(link); + }) + .catch((error) => { + console.error("Error downloading file:", error); + }); + }; + + return ( + + {title} + + ); +}; + +export default DownloadableJsonFile; diff --git a/docs/static/data/AstraDB-RAG-Flows.json b/docs/static/data/AstraDB-RAG-Flows.json new file mode 100644 index 000000000..5706a0fbf --- /dev/null +++ b/docs/static/data/AstraDB-RAG-Flows.json @@ -0,0 +1,3403 @@ +{ + "id": "51e2b78a-199b-4054-9f32-e288eef6924c", + "data": { + "nodes": [ + { + "id": "ChatInput-yxMKE", + "type": "genericNode", + "position": { + "x": 1195.5276981160775, + "y": 209.421875 + }, + "data": { + "type": "ChatInput", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional, Union\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.schema import Record\n\n\nclass ChatInput(ChatComponent):\n display_name = \"Chat Input\"\n description = \"Get chat inputs from the Interaction Panel.\"\n icon = \"ChatInput\"\n\n def build_config(self):\n build_config = super().build_config()\n build_config[\"input_value\"] = {\n \"input_types\": [],\n \"display_name\": \"Message\",\n \"multiline\": True,\n }\n\n return build_config\n\n def build(\n self,\n sender: Optional[str] = \"User\",\n sender_name: Optional[str] = \"User\",\n input_value: Optional[str] = None,\n session_id: Optional[str] = None,\n return_record: Optional[bool] = False,\n ) -> Union[Text, Record]:\n return super().build(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n session_id=session_id,\n return_record=return_record,\n )\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "input_value": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Message", + "advanced": false, + "input_types": [], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "value": "what is a line" + }, + "return_record": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "return_record", + "display_name": "Return Record", + "advanced": true, + "dynamic": false, + "info": "Return the message as a record containing the sender, sender_name, and session_id.", + "load_from_db": false, + "title_case": false + }, + "sender": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "User", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "Machine", + "User" + ], + "name": "sender", + "display_name": "Sender Type", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "sender_name": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "User", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "sender_name", + "display_name": "Sender Name", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "session_id": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "session_id", + "display_name": "Session ID", + "advanced": true, + "dynamic": false, + "info": "If provided, the message will be stored in the memory.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "_type": "CustomComponent" + }, + "description": "Get chat inputs from the Interaction Panel.", + "icon": "ChatInput", + "base_classes": [ + "Text", + "str", + "object", + "Record" + ], + "display_name": "Chat Input", + "documentation": "", + "custom_fields": { + "sender": null, + "sender_name": null, + "input_value": null, + "session_id": null, + "return_record": null + }, + "output_types": [ + "Text", + "Record" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "ChatInput-yxMKE" + }, + "selected": false, + "width": 384, + "height": 383 + }, + { + "id": "TextOutput-BDknO", + "type": "genericNode", + "position": { + "x": 2322.600672827879, + "y": 604.9467307442569 + }, + "data": { + "type": "TextOutput", + "node": { + "template": { + "input_value": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Value", + "advanced": false, + "input_types": [ + "Record", + "Text" + ], + "dynamic": false, + "info": "Text or Record to be passed as output.", + "load_from_db": false, + "title_case": false + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional\n\nfrom langflow.base.io.text import TextComponent\nfrom langflow.field_typing import Text\n\n\nclass TextOutput(TextComponent):\n display_name = \"Text Output\"\n description = \"Display a text output in the Interaction Panel.\"\n icon = \"type\"\n\n def build_config(self):\n return {\n \"input_value\": {\n \"display_name\": \"Value\",\n \"input_types\": [\"Record\", \"Text\"],\n \"info\": \"Text or Record to be passed as output.\",\n },\n \"record_template\": {\n \"display_name\": \"Record Template\",\n \"multiline\": True,\n \"info\": \"Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.\",\n \"advanced\": True,\n },\n }\n\n def build(self, input_value: Optional[Text] = \"\", record_template: str = \"\") -> Text:\n return super().build(input_value=input_value, record_template=record_template)\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "record_template": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "{text}", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "record_template", + "display_name": "Record Template", + "advanced": true, + "dynamic": false, + "info": "Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "_type": "CustomComponent" + }, + "description": "Display a text output in the Interaction Panel.", + "icon": "type", + "base_classes": [ + "object", + "Text", + "str" + ], + "display_name": "Extracted Chunks", + "documentation": "", + "custom_fields": { + "input_value": null, + "record_template": null + }, + "output_types": [ + "Text" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "TextOutput-BDknO" + }, + "selected": false, + "width": 384, + "height": 289, + "positionAbsolute": { + "x": 2322.600672827879, + "y": 604.9467307442569 + }, + "dragging": false + }, + { + "id": "OpenAIEmbeddings-ZlOk1", + "type": "genericNode", + "position": { + "x": 1183.667250865064, + "y": 687.3171828430261 + }, + "data": { + "type": "OpenAIEmbeddings", + "node": { + "template": { + "allowed_special": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": [], + "fileTypes": [], + "file_path": "", + "password": false, + "name": "allowed_special", + "display_name": "Allowed Special", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "chunk_size": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 1000, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "chunk_size", + "display_name": "Chunk Size", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "client": { + "type": "Any", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "client", + "display_name": "Client", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Any, Dict, List, Optional\n\nfrom langchain_openai.embeddings.base import OpenAIEmbeddings\n\nfrom langflow.field_typing import Embeddings, NestedDict\nfrom langflow.interface.custom.custom_component import CustomComponent\n\n\nclass OpenAIEmbeddingsComponent(CustomComponent):\n display_name = \"OpenAI Embeddings\"\n description = \"Generate embeddings using OpenAI models.\"\n\n def build_config(self):\n return {\n \"allowed_special\": {\n \"display_name\": \"Allowed Special\",\n \"advanced\": True,\n \"field_type\": \"str\",\n \"is_list\": True,\n },\n \"default_headers\": {\n \"display_name\": \"Default Headers\",\n \"advanced\": True,\n \"field_type\": \"dict\",\n },\n \"default_query\": {\n \"display_name\": \"Default Query\",\n \"advanced\": True,\n \"field_type\": \"NestedDict\",\n },\n \"disallowed_special\": {\n \"display_name\": \"Disallowed Special\",\n \"advanced\": True,\n \"field_type\": \"str\",\n \"is_list\": True,\n },\n \"chunk_size\": {\"display_name\": \"Chunk Size\", \"advanced\": True},\n \"client\": {\"display_name\": \"Client\", \"advanced\": True},\n \"deployment\": {\"display_name\": \"Deployment\", \"advanced\": True},\n \"embedding_ctx_length\": {\n \"display_name\": \"Embedding Context Length\",\n \"advanced\": True,\n },\n \"max_retries\": {\"display_name\": \"Max Retries\", \"advanced\": True},\n \"model\": {\n \"display_name\": \"Model\",\n \"advanced\": False,\n \"options\": [\n \"text-embedding-3-small\",\n \"text-embedding-3-large\",\n \"text-embedding-ada-002\",\n ],\n },\n \"model_kwargs\": {\"display_name\": \"Model Kwargs\", \"advanced\": True},\n \"openai_api_base\": {\n \"display_name\": \"OpenAI API Base\",\n \"password\": True,\n \"advanced\": True,\n },\n \"openai_api_key\": {\"display_name\": \"OpenAI API Key\", \"password\": True},\n \"openai_api_type\": {\n \"display_name\": \"OpenAI API Type\",\n \"advanced\": True,\n \"password\": True,\n },\n \"openai_api_version\": {\n \"display_name\": \"OpenAI API Version\",\n \"advanced\": True,\n },\n \"openai_organization\": {\n \"display_name\": \"OpenAI Organization\",\n \"advanced\": True,\n },\n \"openai_proxy\": {\"display_name\": \"OpenAI Proxy\", \"advanced\": True},\n \"request_timeout\": {\"display_name\": \"Request Timeout\", \"advanced\": True},\n \"show_progress_bar\": {\n \"display_name\": \"Show Progress Bar\",\n \"advanced\": True,\n },\n \"skip_empty\": {\"display_name\": \"Skip Empty\", \"advanced\": True},\n \"tiktoken_model_name\": {\n \"display_name\": \"TikToken Model Name\",\n \"advanced\": True,\n },\n \"tiktoken_enable\": {\"display_name\": \"TikToken Enable\", \"advanced\": True},\n }\n\n def build(\n self,\n openai_api_key: str,\n default_headers: Optional[Dict[str, str]] = None,\n default_query: Optional[NestedDict] = {},\n allowed_special: List[str] = [],\n disallowed_special: List[str] = [\"all\"],\n chunk_size: int = 1000,\n client: Optional[Any] = None,\n deployment: str = \"text-embedding-ada-002\",\n embedding_ctx_length: int = 8191,\n max_retries: int = 6,\n model: str = \"text-embedding-ada-002\",\n model_kwargs: NestedDict = {},\n openai_api_base: Optional[str] = None,\n openai_api_type: Optional[str] = None,\n openai_api_version: Optional[str] = None,\n openai_organization: Optional[str] = None,\n openai_proxy: Optional[str] = None,\n request_timeout: Optional[float] = None,\n show_progress_bar: bool = False,\n skip_empty: bool = False,\n tiktoken_enable: bool = True,\n tiktoken_model_name: Optional[str] = None,\n ) -> Embeddings:\n # This is to avoid errors with Vector Stores (e.g Chroma)\n if disallowed_special == [\"all\"]:\n disallowed_special = \"all\" # type: ignore\n\n return OpenAIEmbeddings(\n tiktoken_enabled=tiktoken_enable,\n default_headers=default_headers,\n default_query=default_query,\n allowed_special=set(allowed_special),\n disallowed_special=\"all\",\n chunk_size=chunk_size,\n client=client,\n deployment=deployment,\n embedding_ctx_length=embedding_ctx_length,\n max_retries=max_retries,\n model=model,\n model_kwargs=model_kwargs,\n base_url=openai_api_base,\n api_key=openai_api_key,\n openai_api_type=openai_api_type,\n api_version=openai_api_version,\n organization=openai_organization,\n openai_proxy=openai_proxy,\n timeout=request_timeout,\n show_progress_bar=show_progress_bar,\n skip_empty=skip_empty,\n tiktoken_model_name=tiktoken_model_name,\n )\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "default_headers": { + "type": "dict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "default_headers", + "display_name": "Default Headers", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "default_query": { + "type": "NestedDict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": {}, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "default_query", + "display_name": "Default Query", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "deployment": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "text-embedding-ada-002", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "deployment", + "display_name": "Deployment", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "disallowed_special": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": [ + "all" + ], + "fileTypes": [], + "file_path": "", + "password": false, + "name": "disallowed_special", + "display_name": "Disallowed Special", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "embedding_ctx_length": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 8191, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "embedding_ctx_length", + "display_name": "Embedding Context Length", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "max_retries": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 6, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "max_retries", + "display_name": "Max Retries", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "model": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "text-embedding-ada-002", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "text-embedding-3-small", + "text-embedding-3-large", + "text-embedding-ada-002" + ], + "name": "model", + "display_name": "Model", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "model_kwargs": { + "type": "NestedDict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": {}, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "model_kwargs", + "display_name": "Model Kwargs", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "openai_api_base": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": true, + "name": "openai_api_base", + "display_name": "OpenAI API Base", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_api_key": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": true, + "name": "openai_api_key", + "display_name": "OpenAI API Key", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ], + "value": "" + }, + "openai_api_type": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": true, + "name": "openai_api_type", + "display_name": "OpenAI API Type", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_api_version": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "openai_api_version", + "display_name": "OpenAI API Version", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_organization": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "openai_organization", + "display_name": "OpenAI Organization", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_proxy": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "openai_proxy", + "display_name": "OpenAI Proxy", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "request_timeout": { + "type": "float", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "request_timeout", + "display_name": "Request Timeout", + "advanced": true, + "dynamic": false, + "info": "", + "rangeSpec": { + "step_type": "float", + "min": -1, + "max": 1, + "step": 0.1 + }, + "load_from_db": false, + "title_case": false + }, + "show_progress_bar": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "show_progress_bar", + "display_name": "Show Progress Bar", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "skip_empty": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "skip_empty", + "display_name": "Skip Empty", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "tiktoken_enable": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": true, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "tiktoken_enable", + "display_name": "TikToken Enable", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "tiktoken_model_name": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "tiktoken_model_name", + "display_name": "TikToken Model Name", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "_type": "CustomComponent" + }, + "description": "Generate embeddings using OpenAI models.", + "base_classes": [ + "Embeddings" + ], + "display_name": "OpenAI Embeddings", + "documentation": "", + "custom_fields": { + "openai_api_key": null, + "default_headers": null, + "default_query": null, + "allowed_special": null, + "disallowed_special": null, + "chunk_size": null, + "client": null, + "deployment": null, + "embedding_ctx_length": null, + "max_retries": null, + "model": null, + "model_kwargs": null, + "openai_api_base": null, + "openai_api_type": null, + "openai_api_version": null, + "openai_organization": null, + "openai_proxy": null, + "request_timeout": null, + "show_progress_bar": null, + "skip_empty": null, + "tiktoken_enable": null, + "tiktoken_model_name": null + }, + "output_types": [ + "Embeddings" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "OpenAIEmbeddings-ZlOk1" + }, + "selected": false, + "width": 384, + "height": 383, + "dragging": false + }, + { + "id": "OpenAIModel-EjXlN", + "type": "genericNode", + "position": { + "x": 3410.117202077183, + "y": 431.2038048137648 + }, + "data": { + "type": "OpenAIModel", + "node": { + "template": { + "input_value": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Input", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional\n\nfrom langchain_openai import ChatOpenAI\n\nfrom langflow.base.constants import STREAM_INFO_TEXT\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.field_typing import NestedDict, Text\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n\n field_order = [\n \"max_tokens\",\n \"model_kwargs\",\n \"model_name\",\n \"openai_api_base\",\n \"openai_api_key\",\n \"temperature\",\n \"input_value\",\n \"system_message\",\n \"stream\",\n ]\n\n def build_config(self):\n return {\n \"input_value\": {\"display_name\": \"Input\"},\n \"max_tokens\": {\n \"display_name\": \"Max Tokens\",\n \"advanced\": True,\n },\n \"model_kwargs\": {\n \"display_name\": \"Model Kwargs\",\n \"advanced\": True,\n },\n \"model_name\": {\n \"display_name\": \"Model Name\",\n \"advanced\": False,\n \"options\": [\n \"gpt-4-turbo-preview\",\n \"gpt-3.5-turbo\",\n \"gpt-4-0125-preview\",\n \"gpt-4-1106-preview\",\n \"gpt-4-vision-preview\",\n \"gpt-3.5-turbo-0125\",\n \"gpt-3.5-turbo-1106\",\n ],\n \"value\": \"gpt-4-turbo-preview\",\n },\n \"openai_api_base\": {\n \"display_name\": \"OpenAI API Base\",\n \"advanced\": True,\n \"info\": (\n \"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\n\"\n \"You can change this to use other APIs like JinaChat, LocalAI and Prem.\"\n ),\n },\n \"openai_api_key\": {\n \"display_name\": \"OpenAI API Key\",\n \"info\": \"The OpenAI API Key to use for the OpenAI model.\",\n \"advanced\": False,\n \"password\": True,\n },\n \"temperature\": {\n \"display_name\": \"Temperature\",\n \"advanced\": False,\n \"value\": 0.1,\n },\n \"stream\": {\n \"display_name\": \"Stream\",\n \"info\": STREAM_INFO_TEXT,\n \"advanced\": True,\n },\n \"system_message\": {\n \"display_name\": \"System Message\",\n \"info\": \"System message to pass to the model.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n input_value: Text,\n openai_api_key: str,\n temperature: float,\n model_name: str,\n max_tokens: Optional[int] = 256,\n model_kwargs: NestedDict = {},\n openai_api_base: Optional[str] = None,\n stream: bool = False,\n system_message: Optional[str] = None,\n ) -> Text:\n if not openai_api_base:\n openai_api_base = \"https://api.openai.com/v1\"\n output = ChatOpenAI(\n max_tokens=max_tokens,\n model_kwargs=model_kwargs,\n model=model_name,\n base_url=openai_api_base,\n api_key=openai_api_key,\n temperature=temperature,\n )\n\n return self.get_chat_result(output, stream, input_value, system_message)\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "max_tokens": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 256, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "max_tokens", + "display_name": "Max Tokens", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "model_kwargs": { + "type": "NestedDict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": {}, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "model_kwargs", + "display_name": "Model Kwargs", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "model_name": { + "type": "str", + "required": true, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "gpt-3.5-turbo", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "gpt-4-turbo-preview", + "gpt-3.5-turbo", + "gpt-4-0125-preview", + "gpt-4-1106-preview", + "gpt-4-vision-preview", + "gpt-3.5-turbo-0125", + "gpt-3.5-turbo-1106" + ], + "name": "model_name", + "display_name": "Model Name", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_api_base": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "openai_api_base", + "display_name": "OpenAI API Base", + "advanced": true, + "dynamic": false, + "info": "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_api_key": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": true, + "name": "openai_api_key", + "display_name": "OpenAI API Key", + "advanced": false, + "dynamic": false, + "info": "The OpenAI API Key to use for the OpenAI model.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ], + "value": "" + }, + "stream": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "stream", + "display_name": "Stream", + "advanced": true, + "dynamic": false, + "info": "Stream the response from the model. Streaming works only in Chat.", + "load_from_db": false, + "title_case": false + }, + "system_message": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "system_message", + "display_name": "System Message", + "advanced": true, + "dynamic": false, + "info": "System message to pass to the model.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "temperature": { + "type": "float", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 0.1, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "temperature", + "display_name": "Temperature", + "advanced": false, + "dynamic": false, + "info": "", + "rangeSpec": { + "step_type": "float", + "min": -1, + "max": 1, + "step": 0.1 + }, + "load_from_db": false, + "title_case": false + }, + "_type": "CustomComponent" + }, + "description": "Generates text using OpenAI LLMs.", + "icon": "OpenAI", + "base_classes": [ + "object", + "Text", + "str" + ], + "display_name": "OpenAI", + "documentation": "", + "custom_fields": { + "input_value": null, + "openai_api_key": null, + "temperature": null, + "model_name": null, + "max_tokens": null, + "model_kwargs": null, + "openai_api_base": null, + "stream": null, + "system_message": null + }, + "output_types": [ + "Text" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [ + "max_tokens", + "model_kwargs", + "model_name", + "openai_api_base", + "openai_api_key", + "temperature", + "input_value", + "system_message", + "stream" + ], + "beta": false + }, + "id": "OpenAIModel-EjXlN" + }, + "selected": true, + "width": 384, + "height": 563, + "positionAbsolute": { + "x": 3410.117202077183, + "y": 431.2038048137648 + }, + "dragging": false + }, + { + "id": "Prompt-xeI6K", + "type": "genericNode", + "position": { + "x": 2969.0261961391298, + "y": 442.1613649809069 + }, + "data": { + "type": "Prompt", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from langchain_core.prompts import PromptTemplate\n\nfrom langflow.field_typing import Prompt, TemplateField, Text\nfrom langflow.interface.custom.custom_component import CustomComponent\n\n\nclass PromptComponent(CustomComponent):\n display_name: str = \"Prompt\"\n description: str = \"Create a prompt template with dynamic variables.\"\n icon = \"prompts\"\n\n def build_config(self):\n return {\n \"template\": TemplateField(display_name=\"Template\"),\n \"code\": TemplateField(advanced=True),\n }\n\n def build(\n self,\n template: Prompt,\n **kwargs,\n ) -> Text:\n from langflow.base.prompts.utils import dict_values_to_string\n\n prompt_template = PromptTemplate.from_template(Text(template))\n kwargs = dict_values_to_string(kwargs)\n kwargs = {k: \"\\n\".join(v) if isinstance(v, list) else v for k, v in kwargs.items()}\n try:\n formated_prompt = prompt_template.format(**kwargs)\n except Exception as exc:\n raise ValueError(f\"Error formatting prompt: {exc}\") from exc\n self.status = f'Prompt:\\n\"{formated_prompt}\"'\n return formated_prompt\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "template": { + "type": "prompt", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "{context}\n\n---\n\nGiven the context above, answer the question as best as possible.\n\nQuestion: {question}\n\nAnswer: ", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "template", + "display_name": "Template", + "advanced": false, + "input_types": [ + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "_type": "CustomComponent", + "context": { + "field_type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "context", + "display_name": "context", + "advanced": false, + "input_types": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "type": "str" + }, + "question": { + "field_type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "question", + "display_name": "question", + "advanced": false, + "input_types": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "type": "str" + } + }, + "description": "Create a prompt template with dynamic variables.", + "icon": "prompts", + "is_input": null, + "is_output": null, + "is_composition": null, + "base_classes": [ + "object", + "Text", + "str" + ], + "name": "", + "display_name": "Prompt", + "documentation": "", + "custom_fields": { + "template": [ + "context", + "question" + ] + }, + "output_types": [ + "Text" + ], + "full_path": null, + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false, + "error": null + }, + "id": "Prompt-xeI6K", + "description": "Create a prompt template with dynamic variables.", + "display_name": "Prompt" + }, + "selected": false, + "width": 384, + "height": 477, + "positionAbsolute": { + "x": 2969.0261961391298, + "y": 442.1613649809069 + }, + "dragging": false + }, + { + "id": "ChatOutput-Q39I8", + "type": "genericNode", + "position": { + "x": 3887.2073667611485, + "y": 588.4801225794856 + }, + "data": { + "type": "ChatOutput", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional, Union\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.schema import Record\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Interaction Panel.\"\n icon = \"ChatOutput\"\n\n def build(\n self,\n sender: Optional[str] = \"Machine\",\n sender_name: Optional[str] = \"AI\",\n input_value: Optional[str] = None,\n session_id: Optional[str] = None,\n return_record: Optional[bool] = False,\n record_template: Optional[str] = \"{text}\",\n ) -> Union[Text, Record]:\n return super().build(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n session_id=session_id,\n return_record=return_record,\n record_template=record_template,\n )\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "input_value": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Message", + "advanced": false, + "input_types": [ + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "record_template": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "{text}", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "record_template", + "display_name": "Record Template", + "advanced": true, + "dynamic": false, + "info": "In case of Message being a Record, this template will be used to convert it to text.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "return_record": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "return_record", + "display_name": "Return Record", + "advanced": true, + "dynamic": false, + "info": "Return the message as a record containing the sender, sender_name, and session_id.", + "load_from_db": false, + "title_case": false + }, + "sender": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "Machine", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "Machine", + "User" + ], + "name": "sender", + "display_name": "Sender Type", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "sender_name": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "AI", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "sender_name", + "display_name": "Sender Name", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "session_id": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "session_id", + "display_name": "Session ID", + "advanced": true, + "dynamic": false, + "info": "If provided, the message will be stored in the memory.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "_type": "CustomComponent" + }, + "description": "Display a chat message in the Interaction Panel.", + "icon": "ChatOutput", + "base_classes": [ + "object", + "Text", + "Record", + "str" + ], + "display_name": "Chat Output", + "documentation": "", + "custom_fields": { + "sender": null, + "sender_name": null, + "input_value": null, + "session_id": null, + "return_record": null, + "record_template": null + }, + "output_types": [ + "Text", + "Record" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "ChatOutput-Q39I8" + }, + "selected": false, + "width": 384, + "height": 383, + "positionAbsolute": { + "x": 3887.2073667611485, + "y": 588.4801225794856 + }, + "dragging": false + }, + { + "id": "File-t0a6a", + "type": "genericNode", + "position": { + "x": 2257.233450682836, + "y": 1747.5389618367233 + }, + "data": { + "type": "File", + "node": { + "template": { + "path": { + "type": "file", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [ + ".txt", + ".md", + ".mdx", + ".csv", + ".json", + ".yaml", + ".yml", + ".xml", + ".html", + ".htm", + ".pdf", + ".docx" + ], + "file_path": "51e2b78a-199b-4054-9f32-e288eef6924c/Langflow conversation.pdf", + "password": false, + "name": "path", + "display_name": "Path", + "advanced": false, + "dynamic": false, + "info": "Supported file types: txt, md, mdx, csv, json, yaml, yml, xml, html, htm, pdf, docx", + "load_from_db": false, + "title_case": false, + "value": "" + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from pathlib import Path\nfrom typing import Any, Dict\n\nfrom langflow.base.data.utils import TEXT_FILE_TYPES, parse_text_file_to_record\nfrom langflow.interface.custom.custom_component import CustomComponent\nfrom langflow.schema import Record\n\n\nclass FileComponent(CustomComponent):\n display_name = \"File\"\n description = \"A generic file loader.\"\n icon = \"file-text\"\n\n def build_config(self) -> Dict[str, Any]:\n return {\n \"path\": {\n \"display_name\": \"Path\",\n \"field_type\": \"file\",\n \"file_types\": TEXT_FILE_TYPES,\n \"info\": f\"Supported file types: {', '.join(TEXT_FILE_TYPES)}\",\n },\n \"silent_errors\": {\n \"display_name\": \"Silent Errors\",\n \"advanced\": True,\n \"info\": \"If true, errors will not raise an exception.\",\n },\n }\n\n def load_file(self, path: str, silent_errors: bool = False) -> Record:\n resolved_path = self.resolve_path(path)\n path_obj = Path(resolved_path)\n extension = path_obj.suffix[1:].lower()\n if extension == \"doc\":\n raise ValueError(\"doc files are not supported. Please save as .docx\")\n if extension not in TEXT_FILE_TYPES:\n raise ValueError(f\"Unsupported file type: {extension}\")\n record = parse_text_file_to_record(resolved_path, silent_errors)\n self.status = record if record else \"No data\"\n return record or Record()\n\n def build(\n self,\n path: str,\n silent_errors: bool = False,\n ) -> Record:\n record = self.load_file(path, silent_errors)\n self.status = record\n return record\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "silent_errors": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "silent_errors", + "display_name": "Silent Errors", + "advanced": true, + "dynamic": false, + "info": "If true, errors will not raise an exception.", + "load_from_db": false, + "title_case": false + }, + "_type": "CustomComponent" + }, + "description": "A generic file loader.", + "icon": "file-text", + "base_classes": [ + "Record" + ], + "display_name": "File", + "documentation": "", + "custom_fields": { + "path": null, + "silent_errors": null + }, + "output_types": [ + "Record" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "File-t0a6a" + }, + "selected": false, + "width": 384, + "height": 281, + "positionAbsolute": { + "x": 2257.233450682836, + "y": 1747.5389618367233 + }, + "dragging": false + }, + { + "id": "RecursiveCharacterTextSplitter-tR9QM", + "type": "genericNode", + "position": { + "x": 2791.013514133929, + "y": 1462.9588953494142 + }, + "data": { + "type": "RecursiveCharacterTextSplitter", + "node": { + "template": { + "inputs": { + "type": "Document", + "required": true, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "inputs", + "display_name": "Input", + "advanced": false, + "input_types": [ + "Document", + "Record" + ], + "dynamic": false, + "info": "The texts to split.", + "load_from_db": false, + "title_case": false + }, + "chunk_overlap": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 200, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "chunk_overlap", + "display_name": "Chunk Overlap", + "advanced": false, + "dynamic": false, + "info": "The amount of overlap between chunks.", + "load_from_db": false, + "title_case": false + }, + "chunk_size": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 1000, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "chunk_size", + "display_name": "Chunk Size", + "advanced": false, + "dynamic": false, + "info": "The maximum length of each chunk.", + "load_from_db": false, + "title_case": false + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional\n\nfrom langchain.text_splitter import RecursiveCharacterTextSplitter\nfrom langchain_core.documents import Document\n\nfrom langflow.interface.custom.custom_component import CustomComponent\nfrom langflow.schema import Record\nfrom langflow.utils.util import build_loader_repr_from_records, unescape_string\n\n\nclass RecursiveCharacterTextSplitterComponent(CustomComponent):\n display_name: str = \"Recursive Character Text Splitter\"\n description: str = \"Split text into chunks of a specified length.\"\n documentation: str = \"https://docs.langflow.org/components/text-splitters#recursivecharactertextsplitter\"\n\n def build_config(self):\n return {\n \"inputs\": {\n \"display_name\": \"Input\",\n \"info\": \"The texts to split.\",\n \"input_types\": [\"Document\", \"Record\"],\n },\n \"separators\": {\n \"display_name\": \"Separators\",\n \"info\": 'The characters to split on.\\nIf left empty defaults to [\"\\\\n\\\\n\", \"\\\\n\", \" \", \"\"].',\n \"is_list\": True,\n },\n \"chunk_size\": {\n \"display_name\": \"Chunk Size\",\n \"info\": \"The maximum length of each chunk.\",\n \"field_type\": \"int\",\n \"value\": 1000,\n },\n \"chunk_overlap\": {\n \"display_name\": \"Chunk Overlap\",\n \"info\": \"The amount of overlap between chunks.\",\n \"field_type\": \"int\",\n \"value\": 200,\n },\n \"code\": {\"show\": False},\n }\n\n def build(\n self,\n inputs: list[Document],\n separators: Optional[list[str]] = None,\n chunk_size: Optional[int] = 1000,\n chunk_overlap: Optional[int] = 200,\n ) -> list[Record]:\n \"\"\"\n Split text into chunks of a specified length.\n\n Args:\n separators (list[str]): The characters to split on.\n chunk_size (int): The maximum length of each chunk.\n chunk_overlap (int): The amount of overlap between chunks.\n length_function (function): The function to use to calculate the length of the text.\n\n Returns:\n list[str]: The chunks of text.\n \"\"\"\n\n if separators == \"\":\n separators = None\n elif separators:\n # check if the separators list has escaped characters\n # if there are escaped characters, unescape them\n separators = [unescape_string(x) for x in separators]\n\n # Make sure chunk_size and chunk_overlap are ints\n if isinstance(chunk_size, str):\n chunk_size = int(chunk_size)\n if isinstance(chunk_overlap, str):\n chunk_overlap = int(chunk_overlap)\n splitter = RecursiveCharacterTextSplitter(\n separators=separators,\n chunk_size=chunk_size,\n chunk_overlap=chunk_overlap,\n )\n documents = []\n for _input in inputs:\n if isinstance(_input, Record):\n documents.append(_input.to_lc_document())\n else:\n documents.append(_input)\n docs = splitter.split_documents(documents)\n records = self.to_records(docs)\n self.repr_value = build_loader_repr_from_records(records)\n return records\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "separators": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "separators", + "display_name": "Separators", + "advanced": false, + "dynamic": false, + "info": "The characters to split on.\nIf left empty defaults to [\"\\n\\n\", \"\\n\", \" \", \"\"].", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ], + "value": [ + "" + ] + }, + "_type": "CustomComponent" + }, + "description": "Split text into chunks of a specified length.", + "base_classes": [ + "Record" + ], + "display_name": "Recursive Character Text Splitter", + "documentation": "https://docs.langflow.org/components/text-splitters#recursivecharactertextsplitter", + "custom_fields": { + "inputs": null, + "separators": null, + "chunk_size": null, + "chunk_overlap": null + }, + "output_types": [ + "Record" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "RecursiveCharacterTextSplitter-tR9QM" + }, + "selected": false, + "width": 384, + "height": 501, + "positionAbsolute": { + "x": 2791.013514133929, + "y": 1462.9588953494142 + }, + "dragging": false + }, + { + "id": "AstraDBSearch-41nRz", + "type": "genericNode", + "position": { + "x": 1723.976434815103, + "y": 277.03317407245913 + }, + "data": { + "type": "AstraDBSearch", + "node": { + "template": { + "embedding": { + "type": "Embeddings", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "embedding", + "display_name": "Embedding", + "advanced": false, + "dynamic": false, + "info": "Embedding to use", + "load_from_db": false, + "title_case": false + }, + "input_value": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Input Value", + "advanced": false, + "dynamic": false, + "info": "Input value to search", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "api_endpoint": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "api_endpoint", + "display_name": "API Endpoint", + "advanced": false, + "dynamic": false, + "info": "API endpoint URL for the Astra DB service.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ], + "value": "" + }, + "batch_size": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "batch_size", + "display_name": "Batch Size", + "advanced": true, + "dynamic": false, + "info": "Optional number of records to process in a single batch.", + "load_from_db": false, + "title_case": false + }, + "bulk_delete_concurrency": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "bulk_delete_concurrency", + "display_name": "Bulk Delete Concurrency", + "advanced": true, + "dynamic": false, + "info": "Optional concurrency level for bulk delete operations.", + "load_from_db": false, + "title_case": false + }, + "bulk_insert_batch_concurrency": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "bulk_insert_batch_concurrency", + "display_name": "Bulk Insert Batch Concurrency", + "advanced": true, + "dynamic": false, + "info": "Optional concurrency level for bulk insert operations.", + "load_from_db": false, + "title_case": false + }, + "bulk_insert_overwrite_concurrency": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "bulk_insert_overwrite_concurrency", + "display_name": "Bulk Insert Overwrite Concurrency", + "advanced": true, + "dynamic": false, + "info": "Optional concurrency level for bulk insert operations that overwrite existing records.", + "load_from_db": false, + "title_case": false + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import List, Optional\n\nfrom langflow.components.vectorstores.AstraDB import AstraDBVectorStoreComponent\nfrom langflow.components.vectorstores.base.model import LCVectorStoreComponent\nfrom langflow.field_typing import Embeddings, Text\nfrom langflow.schema import Record\n\n\nclass AstraDBSearchComponent(LCVectorStoreComponent):\n display_name = \"Astra DB Search\"\n description = \"Searches an existing Astra DB Vector Store.\"\n icon = \"AstraDB\"\n field_order = [\"token\", \"api_endpoint\", \"collection_name\", \"input_value\", \"embedding\"]\n\n def build_config(self):\n return {\n \"search_type\": {\n \"display_name\": \"Search Type\",\n \"options\": [\"Similarity\", \"MMR\"],\n },\n \"input_value\": {\n \"display_name\": \"Input Value\",\n \"info\": \"Input value to search\",\n },\n \"embedding\": {\"display_name\": \"Embedding\", \"info\": \"Embedding to use\"},\n \"collection_name\": {\n \"display_name\": \"Collection Name\",\n \"info\": \"The name of the collection within Astra DB where the vectors will be stored.\",\n },\n \"token\": {\n \"display_name\": \"Token\",\n \"info\": \"Authentication token for accessing Astra DB.\",\n \"password\": True,\n },\n \"api_endpoint\": {\n \"display_name\": \"API Endpoint\",\n \"info\": \"API endpoint URL for the Astra DB service.\",\n },\n \"namespace\": {\n \"display_name\": \"Namespace\",\n \"info\": \"Optional namespace within Astra DB to use for the collection.\",\n \"advanced\": True,\n },\n \"metric\": {\n \"display_name\": \"Metric\",\n \"info\": \"Optional distance metric for vector comparisons in the vector store.\",\n \"advanced\": True,\n },\n \"batch_size\": {\n \"display_name\": \"Batch Size\",\n \"info\": \"Optional number of records to process in a single batch.\",\n \"advanced\": True,\n },\n \"bulk_insert_batch_concurrency\": {\n \"display_name\": \"Bulk Insert Batch Concurrency\",\n \"info\": \"Optional concurrency level for bulk insert operations.\",\n \"advanced\": True,\n },\n \"bulk_insert_overwrite_concurrency\": {\n \"display_name\": \"Bulk Insert Overwrite Concurrency\",\n \"info\": \"Optional concurrency level for bulk insert operations that overwrite existing records.\",\n \"advanced\": True,\n },\n \"bulk_delete_concurrency\": {\n \"display_name\": \"Bulk Delete Concurrency\",\n \"info\": \"Optional concurrency level for bulk delete operations.\",\n \"advanced\": True,\n },\n \"setup_mode\": {\n \"display_name\": \"Setup Mode\",\n \"info\": \"Configuration mode for setting up the vector store, with options like “Sync”, “Async”, or “Off”.\",\n \"options\": [\"Sync\", \"Async\", \"Off\"],\n \"advanced\": True,\n },\n \"pre_delete_collection\": {\n \"display_name\": \"Pre Delete Collection\",\n \"info\": \"Boolean flag to determine whether to delete the collection before creating a new one.\",\n \"advanced\": True,\n },\n \"metadata_indexing_include\": {\n \"display_name\": \"Metadata Indexing Include\",\n \"info\": \"Optional list of metadata fields to include in the indexing.\",\n \"advanced\": True,\n },\n \"metadata_indexing_exclude\": {\n \"display_name\": \"Metadata Indexing Exclude\",\n \"info\": \"Optional list of metadata fields to exclude from the indexing.\",\n \"advanced\": True,\n },\n \"collection_indexing_policy\": {\n \"display_name\": \"Collection Indexing Policy\",\n \"info\": \"Optional dictionary defining the indexing policy for the collection.\",\n \"advanced\": True,\n },\n \"number_of_results\": {\n \"display_name\": \"Number of Results\",\n \"info\": \"Number of results to return.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n embedding: Embeddings,\n collection_name: str,\n input_value: Text,\n token: str,\n api_endpoint: str,\n search_type: str = \"Similarity\",\n number_of_results: int = 4,\n namespace: Optional[str] = None,\n metric: Optional[str] = None,\n batch_size: Optional[int] = None,\n bulk_insert_batch_concurrency: Optional[int] = None,\n bulk_insert_overwrite_concurrency: Optional[int] = None,\n bulk_delete_concurrency: Optional[int] = None,\n setup_mode: str = \"Sync\",\n pre_delete_collection: bool = False,\n metadata_indexing_include: Optional[List[str]] = None,\n metadata_indexing_exclude: Optional[List[str]] = None,\n collection_indexing_policy: Optional[dict] = None,\n ) -> List[Record]:\n vector_store = AstraDBVectorStoreComponent().build(\n embedding=embedding,\n collection_name=collection_name,\n token=token,\n api_endpoint=api_endpoint,\n namespace=namespace,\n metric=metric,\n batch_size=batch_size,\n bulk_insert_batch_concurrency=bulk_insert_batch_concurrency,\n bulk_insert_overwrite_concurrency=bulk_insert_overwrite_concurrency,\n bulk_delete_concurrency=bulk_delete_concurrency,\n setup_mode=setup_mode,\n pre_delete_collection=pre_delete_collection,\n metadata_indexing_include=metadata_indexing_include,\n metadata_indexing_exclude=metadata_indexing_exclude,\n collection_indexing_policy=collection_indexing_policy,\n )\n try:\n return self.search_with_vector_store(input_value, search_type, vector_store, k=number_of_results)\n except KeyError as e:\n if \"content\" in str(e):\n raise ValueError(\n \"You should ingest data through Langflow (or LangChain) to query it in Langflow. Your collection does not contain a field name 'content'.\"\n )\n else:\n raise e\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "collection_indexing_policy": { + "type": "dict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "collection_indexing_policy", + "display_name": "Collection Indexing Policy", + "advanced": true, + "dynamic": false, + "info": "Optional dictionary defining the indexing policy for the collection.", + "load_from_db": false, + "title_case": false + }, + "collection_name": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "collection_name", + "display_name": "Collection Name", + "advanced": false, + "dynamic": false, + "info": "The name of the collection within Astra DB where the vectors will be stored.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ], + "value": "langflow" + }, + "metadata_indexing_exclude": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "metadata_indexing_exclude", + "display_name": "Metadata Indexing Exclude", + "advanced": true, + "dynamic": false, + "info": "Optional list of metadata fields to exclude from the indexing.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "metadata_indexing_include": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "metadata_indexing_include", + "display_name": "Metadata Indexing Include", + "advanced": true, + "dynamic": false, + "info": "Optional list of metadata fields to include in the indexing.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "metric": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "metric", + "display_name": "Metric", + "advanced": true, + "dynamic": false, + "info": "Optional distance metric for vector comparisons in the vector store.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "namespace": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "namespace", + "display_name": "Namespace", + "advanced": true, + "dynamic": false, + "info": "Optional namespace within Astra DB to use for the collection.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "number_of_results": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 4, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "number_of_results", + "display_name": "Number of Results", + "advanced": true, + "dynamic": false, + "info": "Number of results to return.", + "load_from_db": false, + "title_case": false + }, + "pre_delete_collection": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "pre_delete_collection", + "display_name": "Pre Delete Collection", + "advanced": true, + "dynamic": false, + "info": "Boolean flag to determine whether to delete the collection before creating a new one.", + "load_from_db": false, + "title_case": false + }, + "search_type": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "Similarity", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "Similarity", + "MMR" + ], + "name": "search_type", + "display_name": "Search Type", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "setup_mode": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "Sync", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "Sync", + "Async", + "Off" + ], + "name": "setup_mode", + "display_name": "Setup Mode", + "advanced": true, + "dynamic": false, + "info": "Configuration mode for setting up the vector store, with options like “Sync”, “Async”, or “Off”.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "token": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": true, + "name": "token", + "display_name": "Token", + "advanced": false, + "dynamic": false, + "info": "Authentication token for accessing Astra DB.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ], + "value": "" + }, + "_type": "CustomComponent" + }, + "description": "Searches an existing Astra DB Vector Store.", + "icon": "AstraDB", + "base_classes": [ + "Record" + ], + "display_name": "Astra DB Search", + "documentation": "", + "custom_fields": { + "embedding": null, + "collection_name": null, + "input_value": null, + "token": null, + "api_endpoint": null, + "search_type": null, + "number_of_results": null, + "namespace": null, + "metric": null, + "batch_size": null, + "bulk_insert_batch_concurrency": null, + "bulk_insert_overwrite_concurrency": null, + "bulk_delete_concurrency": null, + "setup_mode": null, + "pre_delete_collection": null, + "metadata_indexing_include": null, + "metadata_indexing_exclude": null, + "collection_indexing_policy": null + }, + "output_types": [ + "Record" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [ + "token", + "api_endpoint", + "collection_name", + "input_value", + "embedding" + ], + "beta": false + }, + "id": "AstraDBSearch-41nRz" + }, + "selected": false, + "width": 384, + "height": 713, + "dragging": false, + "positionAbsolute": { + "x": 1723.976434815103, + "y": 277.03317407245913 + } + }, + { + "id": "AstraDB-eUCSS", + "type": "genericNode", + "position": { + "x": 3372.04958055989, + "y": 1611.0742035495277 + }, + "data": { + "type": "AstraDB", + "node": { + "template": { + "embedding": { + "type": "Embeddings", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "embedding", + "display_name": "Embedding", + "advanced": false, + "dynamic": false, + "info": "Embedding to use", + "load_from_db": false, + "title_case": false + }, + "inputs": { + "type": "Record", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "inputs", + "display_name": "Inputs", + "advanced": false, + "dynamic": false, + "info": "Optional list of records to be processed and stored in the vector store.", + "load_from_db": false, + "title_case": false + }, + "api_endpoint": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "api_endpoint", + "display_name": "API Endpoint", + "advanced": false, + "dynamic": false, + "info": "API endpoint URL for the Astra DB service.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ], + "value": "" + }, + "batch_size": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "batch_size", + "display_name": "Batch Size", + "advanced": true, + "dynamic": false, + "info": "Optional number of records to process in a single batch.", + "load_from_db": false, + "title_case": false + }, + "bulk_delete_concurrency": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "bulk_delete_concurrency", + "display_name": "Bulk Delete Concurrency", + "advanced": true, + "dynamic": false, + "info": "Optional concurrency level for bulk delete operations.", + "load_from_db": false, + "title_case": false + }, + "bulk_insert_batch_concurrency": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "bulk_insert_batch_concurrency", + "display_name": "Bulk Insert Batch Concurrency", + "advanced": true, + "dynamic": false, + "info": "Optional concurrency level for bulk insert operations.", + "load_from_db": false, + "title_case": false + }, + "bulk_insert_overwrite_concurrency": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "bulk_insert_overwrite_concurrency", + "display_name": "Bulk Insert Overwrite Concurrency", + "advanced": true, + "dynamic": false, + "info": "Optional concurrency level for bulk insert operations that overwrite existing records.", + "load_from_db": false, + "title_case": false + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import List, Optional\n\nfrom langchain_astradb import AstraDBVectorStore\nfrom langchain_astradb.utils.astradb import SetupMode\n\nfrom langflow.custom import CustomComponent\nfrom langflow.field_typing import Embeddings, VectorStore\nfrom langflow.schema import Record\n\n\nclass AstraDBVectorStoreComponent(CustomComponent):\n display_name = \"Astra DB\"\n description = \"Builds or loads an Astra DB Vector Store.\"\n icon = \"AstraDB\"\n field_order = [\"token\", \"api_endpoint\", \"collection_name\", \"inputs\", \"embedding\"]\n\n def build_config(self):\n return {\n \"inputs\": {\n \"display_name\": \"Inputs\",\n \"info\": \"Optional list of records to be processed and stored in the vector store.\",\n },\n \"embedding\": {\"display_name\": \"Embedding\", \"info\": \"Embedding to use\"},\n \"collection_name\": {\n \"display_name\": \"Collection Name\",\n \"info\": \"The name of the collection within Astra DB where the vectors will be stored.\",\n },\n \"token\": {\n \"display_name\": \"Token\",\n \"info\": \"Authentication token for accessing Astra DB.\",\n \"password\": True,\n },\n \"api_endpoint\": {\n \"display_name\": \"API Endpoint\",\n \"info\": \"API endpoint URL for the Astra DB service.\",\n },\n \"namespace\": {\n \"display_name\": \"Namespace\",\n \"info\": \"Optional namespace within Astra DB to use for the collection.\",\n \"advanced\": True,\n },\n \"metric\": {\n \"display_name\": \"Metric\",\n \"info\": \"Optional distance metric for vector comparisons in the vector store.\",\n \"advanced\": True,\n },\n \"batch_size\": {\n \"display_name\": \"Batch Size\",\n \"info\": \"Optional number of records to process in a single batch.\",\n \"advanced\": True,\n },\n \"bulk_insert_batch_concurrency\": {\n \"display_name\": \"Bulk Insert Batch Concurrency\",\n \"info\": \"Optional concurrency level for bulk insert operations.\",\n \"advanced\": True,\n },\n \"bulk_insert_overwrite_concurrency\": {\n \"display_name\": \"Bulk Insert Overwrite Concurrency\",\n \"info\": \"Optional concurrency level for bulk insert operations that overwrite existing records.\",\n \"advanced\": True,\n },\n \"bulk_delete_concurrency\": {\n \"display_name\": \"Bulk Delete Concurrency\",\n \"info\": \"Optional concurrency level for bulk delete operations.\",\n \"advanced\": True,\n },\n \"setup_mode\": {\n \"display_name\": \"Setup Mode\",\n \"info\": \"Configuration mode for setting up the vector store, with options like “Sync”, “Async”, or “Off”.\",\n \"options\": [\"Sync\", \"Async\", \"Off\"],\n \"advanced\": True,\n },\n \"pre_delete_collection\": {\n \"display_name\": \"Pre Delete Collection\",\n \"info\": \"Boolean flag to determine whether to delete the collection before creating a new one.\",\n \"advanced\": True,\n },\n \"metadata_indexing_include\": {\n \"display_name\": \"Metadata Indexing Include\",\n \"info\": \"Optional list of metadata fields to include in the indexing.\",\n \"advanced\": True,\n },\n \"metadata_indexing_exclude\": {\n \"display_name\": \"Metadata Indexing Exclude\",\n \"info\": \"Optional list of metadata fields to exclude from the indexing.\",\n \"advanced\": True,\n },\n \"collection_indexing_policy\": {\n \"display_name\": \"Collection Indexing Policy\",\n \"info\": \"Optional dictionary defining the indexing policy for the collection.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n embedding: Embeddings,\n token: str,\n api_endpoint: str,\n collection_name: str,\n inputs: Optional[List[Record]] = None,\n namespace: Optional[str] = None,\n metric: Optional[str] = None,\n batch_size: Optional[int] = None,\n bulk_insert_batch_concurrency: Optional[int] = None,\n bulk_insert_overwrite_concurrency: Optional[int] = None,\n bulk_delete_concurrency: Optional[int] = None,\n setup_mode: str = \"Async\",\n pre_delete_collection: bool = False,\n metadata_indexing_include: Optional[List[str]] = None,\n metadata_indexing_exclude: Optional[List[str]] = None,\n collection_indexing_policy: Optional[dict] = None,\n ) -> VectorStore:\n try:\n setup_mode_value = SetupMode[setup_mode.upper()]\n except KeyError:\n raise ValueError(f\"Invalid setup mode: {setup_mode}\")\n if inputs:\n documents = [_input.to_lc_document() for _input in inputs]\n\n vector_store = AstraDBVectorStore.from_documents(\n documents=documents,\n embedding=embedding,\n collection_name=collection_name,\n token=token,\n api_endpoint=api_endpoint,\n namespace=namespace,\n metric=metric,\n batch_size=batch_size,\n bulk_insert_batch_concurrency=bulk_insert_batch_concurrency,\n bulk_insert_overwrite_concurrency=bulk_insert_overwrite_concurrency,\n bulk_delete_concurrency=bulk_delete_concurrency,\n setup_mode=setup_mode_value,\n pre_delete_collection=pre_delete_collection,\n metadata_indexing_include=metadata_indexing_include,\n metadata_indexing_exclude=metadata_indexing_exclude,\n collection_indexing_policy=collection_indexing_policy,\n )\n else:\n vector_store = AstraDBVectorStore(\n embedding=embedding,\n collection_name=collection_name,\n token=token,\n api_endpoint=api_endpoint,\n namespace=namespace,\n metric=metric,\n batch_size=batch_size,\n bulk_insert_batch_concurrency=bulk_insert_batch_concurrency,\n bulk_insert_overwrite_concurrency=bulk_insert_overwrite_concurrency,\n bulk_delete_concurrency=bulk_delete_concurrency,\n setup_mode=setup_mode_value,\n pre_delete_collection=pre_delete_collection,\n metadata_indexing_include=metadata_indexing_include,\n metadata_indexing_exclude=metadata_indexing_exclude,\n collection_indexing_policy=collection_indexing_policy,\n )\n\n return vector_store\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "collection_indexing_policy": { + "type": "dict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "collection_indexing_policy", + "display_name": "Collection Indexing Policy", + "advanced": true, + "dynamic": false, + "info": "Optional dictionary defining the indexing policy for the collection.", + "load_from_db": false, + "title_case": false + }, + "collection_name": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "collection_name", + "display_name": "Collection Name", + "advanced": false, + "dynamic": false, + "info": "The name of the collection within Astra DB where the vectors will be stored.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ], + "value": "langflow" + }, + "metadata_indexing_exclude": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "metadata_indexing_exclude", + "display_name": "Metadata Indexing Exclude", + "advanced": true, + "dynamic": false, + "info": "Optional list of metadata fields to exclude from the indexing.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "metadata_indexing_include": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "metadata_indexing_include", + "display_name": "Metadata Indexing Include", + "advanced": true, + "dynamic": false, + "info": "Optional list of metadata fields to include in the indexing.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "metric": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "metric", + "display_name": "Metric", + "advanced": true, + "dynamic": false, + "info": "Optional distance metric for vector comparisons in the vector store.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "namespace": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "namespace", + "display_name": "Namespace", + "advanced": true, + "dynamic": false, + "info": "Optional namespace within Astra DB to use for the collection.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "pre_delete_collection": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "pre_delete_collection", + "display_name": "Pre Delete Collection", + "advanced": true, + "dynamic": false, + "info": "Boolean flag to determine whether to delete the collection before creating a new one.", + "load_from_db": false, + "title_case": false + }, + "setup_mode": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "Async", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "Sync", + "Async", + "Off" + ], + "name": "setup_mode", + "display_name": "Setup Mode", + "advanced": true, + "dynamic": false, + "info": "Configuration mode for setting up the vector store, with options like “Sync”, “Async”, or “Off”.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "token": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": true, + "name": "token", + "display_name": "Token", + "advanced": false, + "dynamic": false, + "info": "Authentication token for accessing Astra DB.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ], + "value": "" + }, + "_type": "CustomComponent" + }, + "description": "Builds or loads an Astra DB Vector Store.", + "icon": "AstraDB", + "base_classes": [ + "VectorStore" + ], + "display_name": "Astra DB", + "documentation": "", + "custom_fields": { + "embedding": null, + "token": null, + "api_endpoint": null, + "collection_name": null, + "inputs": null, + "namespace": null, + "metric": null, + "batch_size": null, + "bulk_insert_batch_concurrency": null, + "bulk_insert_overwrite_concurrency": null, + "bulk_delete_concurrency": null, + "setup_mode": null, + "pre_delete_collection": null, + "metadata_indexing_include": null, + "metadata_indexing_exclude": null, + "collection_indexing_policy": null + }, + "output_types": [ + "VectorStore" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [ + "token", + "api_endpoint", + "collection_name", + "inputs", + "embedding" + ], + "beta": false + }, + "id": "AstraDB-eUCSS" + }, + "selected": false, + "width": 384, + "height": 573, + "positionAbsolute": { + "x": 3372.04958055989, + "y": 1611.0742035495277 + }, + "dragging": false + }, + { + "id": "OpenAIEmbeddings-9TPjc", + "type": "genericNode", + "position": { + "x": 2814.0402191223047, + "y": 1955.9268168273086 + }, + "data": { + "type": "OpenAIEmbeddings", + "node": { + "template": { + "allowed_special": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": [], + "fileTypes": [], + "file_path": "", + "password": false, + "name": "allowed_special", + "display_name": "Allowed Special", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "chunk_size": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 1000, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "chunk_size", + "display_name": "Chunk Size", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "client": { + "type": "Any", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "client", + "display_name": "Client", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Any, Dict, List, Optional\n\nfrom langchain_openai.embeddings.base import OpenAIEmbeddings\n\nfrom langflow.field_typing import Embeddings, NestedDict\nfrom langflow.interface.custom.custom_component import CustomComponent\n\n\nclass OpenAIEmbeddingsComponent(CustomComponent):\n display_name = \"OpenAI Embeddings\"\n description = \"Generate embeddings using OpenAI models.\"\n\n def build_config(self):\n return {\n \"allowed_special\": {\n \"display_name\": \"Allowed Special\",\n \"advanced\": True,\n \"field_type\": \"str\",\n \"is_list\": True,\n },\n \"default_headers\": {\n \"display_name\": \"Default Headers\",\n \"advanced\": True,\n \"field_type\": \"dict\",\n },\n \"default_query\": {\n \"display_name\": \"Default Query\",\n \"advanced\": True,\n \"field_type\": \"NestedDict\",\n },\n \"disallowed_special\": {\n \"display_name\": \"Disallowed Special\",\n \"advanced\": True,\n \"field_type\": \"str\",\n \"is_list\": True,\n },\n \"chunk_size\": {\"display_name\": \"Chunk Size\", \"advanced\": True},\n \"client\": {\"display_name\": \"Client\", \"advanced\": True},\n \"deployment\": {\"display_name\": \"Deployment\", \"advanced\": True},\n \"embedding_ctx_length\": {\n \"display_name\": \"Embedding Context Length\",\n \"advanced\": True,\n },\n \"max_retries\": {\"display_name\": \"Max Retries\", \"advanced\": True},\n \"model\": {\n \"display_name\": \"Model\",\n \"advanced\": False,\n \"options\": [\n \"text-embedding-3-small\",\n \"text-embedding-3-large\",\n \"text-embedding-ada-002\",\n ],\n },\n \"model_kwargs\": {\"display_name\": \"Model Kwargs\", \"advanced\": True},\n \"openai_api_base\": {\n \"display_name\": \"OpenAI API Base\",\n \"password\": True,\n \"advanced\": True,\n },\n \"openai_api_key\": {\"display_name\": \"OpenAI API Key\", \"password\": True},\n \"openai_api_type\": {\n \"display_name\": \"OpenAI API Type\",\n \"advanced\": True,\n \"password\": True,\n },\n \"openai_api_version\": {\n \"display_name\": \"OpenAI API Version\",\n \"advanced\": True,\n },\n \"openai_organization\": {\n \"display_name\": \"OpenAI Organization\",\n \"advanced\": True,\n },\n \"openai_proxy\": {\"display_name\": \"OpenAI Proxy\", \"advanced\": True},\n \"request_timeout\": {\"display_name\": \"Request Timeout\", \"advanced\": True},\n \"show_progress_bar\": {\n \"display_name\": \"Show Progress Bar\",\n \"advanced\": True,\n },\n \"skip_empty\": {\"display_name\": \"Skip Empty\", \"advanced\": True},\n \"tiktoken_model_name\": {\n \"display_name\": \"TikToken Model Name\",\n \"advanced\": True,\n },\n \"tiktoken_enable\": {\"display_name\": \"TikToken Enable\", \"advanced\": True},\n }\n\n def build(\n self,\n openai_api_key: str,\n default_headers: Optional[Dict[str, str]] = None,\n default_query: Optional[NestedDict] = {},\n allowed_special: List[str] = [],\n disallowed_special: List[str] = [\"all\"],\n chunk_size: int = 1000,\n client: Optional[Any] = None,\n deployment: str = \"text-embedding-ada-002\",\n embedding_ctx_length: int = 8191,\n max_retries: int = 6,\n model: str = \"text-embedding-ada-002\",\n model_kwargs: NestedDict = {},\n openai_api_base: Optional[str] = None,\n openai_api_type: Optional[str] = None,\n openai_api_version: Optional[str] = None,\n openai_organization: Optional[str] = None,\n openai_proxy: Optional[str] = None,\n request_timeout: Optional[float] = None,\n show_progress_bar: bool = False,\n skip_empty: bool = False,\n tiktoken_enable: bool = True,\n tiktoken_model_name: Optional[str] = None,\n ) -> Embeddings:\n # This is to avoid errors with Vector Stores (e.g Chroma)\n if disallowed_special == [\"all\"]:\n disallowed_special = \"all\" # type: ignore\n\n return OpenAIEmbeddings(\n tiktoken_enabled=tiktoken_enable,\n default_headers=default_headers,\n default_query=default_query,\n allowed_special=set(allowed_special),\n disallowed_special=\"all\",\n chunk_size=chunk_size,\n client=client,\n deployment=deployment,\n embedding_ctx_length=embedding_ctx_length,\n max_retries=max_retries,\n model=model,\n model_kwargs=model_kwargs,\n base_url=openai_api_base,\n api_key=openai_api_key,\n openai_api_type=openai_api_type,\n api_version=openai_api_version,\n organization=openai_organization,\n openai_proxy=openai_proxy,\n timeout=request_timeout,\n show_progress_bar=show_progress_bar,\n skip_empty=skip_empty,\n tiktoken_model_name=tiktoken_model_name,\n )\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "default_headers": { + "type": "dict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "default_headers", + "display_name": "Default Headers", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "default_query": { + "type": "NestedDict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": {}, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "default_query", + "display_name": "Default Query", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "deployment": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "text-embedding-ada-002", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "deployment", + "display_name": "Deployment", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "disallowed_special": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": [ + "all" + ], + "fileTypes": [], + "file_path": "", + "password": false, + "name": "disallowed_special", + "display_name": "Disallowed Special", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "embedding_ctx_length": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 8191, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "embedding_ctx_length", + "display_name": "Embedding Context Length", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "max_retries": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 6, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "max_retries", + "display_name": "Max Retries", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "model": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "text-embedding-ada-002", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "text-embedding-3-small", + "text-embedding-3-large", + "text-embedding-ada-002" + ], + "name": "model", + "display_name": "Model", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "model_kwargs": { + "type": "NestedDict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": {}, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "model_kwargs", + "display_name": "Model Kwargs", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "openai_api_base": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": true, + "name": "openai_api_base", + "display_name": "OpenAI API Base", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_api_key": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": true, + "name": "openai_api_key", + "display_name": "OpenAI API Key", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ], + "value": "" + }, + "openai_api_type": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": true, + "name": "openai_api_type", + "display_name": "OpenAI API Type", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_api_version": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "openai_api_version", + "display_name": "OpenAI API Version", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_organization": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "openai_organization", + "display_name": "OpenAI Organization", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_proxy": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "openai_proxy", + "display_name": "OpenAI Proxy", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "request_timeout": { + "type": "float", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "request_timeout", + "display_name": "Request Timeout", + "advanced": true, + "dynamic": false, + "info": "", + "rangeSpec": { + "step_type": "float", + "min": -1, + "max": 1, + "step": 0.1 + }, + "load_from_db": false, + "title_case": false + }, + "show_progress_bar": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "show_progress_bar", + "display_name": "Show Progress Bar", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "skip_empty": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "skip_empty", + "display_name": "Skip Empty", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "tiktoken_enable": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": true, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "tiktoken_enable", + "display_name": "TikToken Enable", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "tiktoken_model_name": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "tiktoken_model_name", + "display_name": "TikToken Model Name", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "_type": "CustomComponent" + }, + "description": "Generate embeddings using OpenAI models.", + "base_classes": [ + "Embeddings" + ], + "display_name": "OpenAI Embeddings", + "documentation": "", + "custom_fields": { + "openai_api_key": null, + "default_headers": null, + "default_query": null, + "allowed_special": null, + "disallowed_special": null, + "chunk_size": null, + "client": null, + "deployment": null, + "embedding_ctx_length": null, + "max_retries": null, + "model": null, + "model_kwargs": null, + "openai_api_base": null, + "openai_api_type": null, + "openai_api_version": null, + "openai_organization": null, + "openai_proxy": null, + "request_timeout": null, + "show_progress_bar": null, + "skip_empty": null, + "tiktoken_enable": null, + "tiktoken_model_name": null + }, + "output_types": [ + "Embeddings" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "OpenAIEmbeddings-9TPjc" + }, + "selected": false, + "width": 384, + "height": 383, + "positionAbsolute": { + "x": 2814.0402191223047, + "y": 1955.9268168273086 + }, + "dragging": false + } + ], + "edges": [ + { + "source": "TextOutput-BDknO", + "target": "Prompt-xeI6K", + "sourceHandle": "{œbaseClassesœ:[œobjectœ,œTextœ,œstrœ],œdataTypeœ:œTextOutputœ,œidœ:œTextOutput-BDknOœ}", + "targetHandle": "{œfieldNameœ:œcontextœ,œidœ:œPrompt-xeI6Kœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-TextOutput-BDknO{œbaseClassesœ:[œobjectœ,œTextœ,œstrœ],œdataTypeœ:œTextOutputœ,œidœ:œTextOutput-BDknOœ}-Prompt-xeI6K{œfieldNameœ:œcontextœ,œidœ:œPrompt-xeI6Kœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "context", + "id": "Prompt-xeI6K", + "inputTypes": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "object", + "Text", + "str" + ], + "dataType": "TextOutput", + "id": "TextOutput-BDknO" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "selected": false + }, + { + "source": "ChatInput-yxMKE", + "target": "Prompt-xeI6K", + "sourceHandle": "{œbaseClassesœ:[œTextœ,œstrœ,œobjectœ,œRecordœ],œdataTypeœ:œChatInputœ,œidœ:œChatInput-yxMKEœ}", + "targetHandle": "{œfieldNameœ:œquestionœ,œidœ:œPrompt-xeI6Kœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-ChatInput-yxMKE{œbaseClassesœ:[œTextœ,œstrœ,œobjectœ,œRecordœ],œdataTypeœ:œChatInputœ,œidœ:œChatInput-yxMKEœ}-Prompt-xeI6K{œfieldNameœ:œquestionœ,œidœ:œPrompt-xeI6Kœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "question", + "id": "Prompt-xeI6K", + "inputTypes": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "Text", + "str", + "object", + "Record" + ], + "dataType": "ChatInput", + "id": "ChatInput-yxMKE" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "selected": false + }, + { + "source": "Prompt-xeI6K", + "target": "OpenAIModel-EjXlN", + "sourceHandle": "{œbaseClassesœ:[œobjectœ,œTextœ,œstrœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-xeI6Kœ}", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-EjXlNœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-Prompt-xeI6K{œbaseClassesœ:[œobjectœ,œTextœ,œstrœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-xeI6Kœ}-OpenAIModel-EjXlN{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-EjXlNœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "input_value", + "id": "OpenAIModel-EjXlN", + "inputTypes": [ + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "object", + "Text", + "str" + ], + "dataType": "Prompt", + "id": "Prompt-xeI6K" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "selected": false + }, + { + "source": "OpenAIModel-EjXlN", + "target": "ChatOutput-Q39I8", + "sourceHandle": "{œbaseClassesœ:[œobjectœ,œTextœ,œstrœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-EjXlNœ}", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-Q39I8œ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-OpenAIModel-EjXlN{œbaseClassesœ:[œobjectœ,œTextœ,œstrœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-EjXlNœ}-ChatOutput-Q39I8{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-Q39I8œ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "input_value", + "id": "ChatOutput-Q39I8", + "inputTypes": [ + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "object", + "Text", + "str" + ], + "dataType": "OpenAIModel", + "id": "OpenAIModel-EjXlN" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "selected": false + }, + { + "source": "File-t0a6a", + "target": "RecursiveCharacterTextSplitter-tR9QM", + "sourceHandle": "{œbaseClassesœ:[œRecordœ],œdataTypeœ:œFileœ,œidœ:œFile-t0a6aœ}", + "targetHandle": "{œfieldNameœ:œinputsœ,œidœ:œRecursiveCharacterTextSplitter-tR9QMœ,œinputTypesœ:[œDocumentœ,œRecordœ],œtypeœ:œDocumentœ}", + "id": "reactflow__edge-File-t0a6a{œbaseClassesœ:[œRecordœ],œdataTypeœ:œFileœ,œidœ:œFile-t0a6aœ}-RecursiveCharacterTextSplitter-tR9QM{œfieldNameœ:œinputsœ,œidœ:œRecursiveCharacterTextSplitter-tR9QMœ,œinputTypesœ:[œDocumentœ,œRecordœ],œtypeœ:œDocumentœ}", + "data": { + "targetHandle": { + "fieldName": "inputs", + "id": "RecursiveCharacterTextSplitter-tR9QM", + "inputTypes": [ + "Document", + "Record" + ], + "type": "Document" + }, + "sourceHandle": { + "baseClasses": [ + "Record" + ], + "dataType": "File", + "id": "File-t0a6a" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "selected": false + }, + { + "source": "OpenAIEmbeddings-ZlOk1", + "sourceHandle": "{œbaseClassesœ:[œEmbeddingsœ],œdataTypeœ:œOpenAIEmbeddingsœ,œidœ:œOpenAIEmbeddings-ZlOk1œ}", + "target": "AstraDBSearch-41nRz", + "targetHandle": "{œfieldNameœ:œembeddingœ,œidœ:œAstraDBSearch-41nRzœ,œinputTypesœ:null,œtypeœ:œEmbeddingsœ}", + "data": { + "targetHandle": { + "fieldName": "embedding", + "id": "AstraDBSearch-41nRz", + "inputTypes": null, + "type": "Embeddings" + }, + "sourceHandle": { + "baseClasses": [ + "Embeddings" + ], + "dataType": "OpenAIEmbeddings", + "id": "OpenAIEmbeddings-ZlOk1" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-OpenAIEmbeddings-ZlOk1{œbaseClassesœ:[œEmbeddingsœ],œdataTypeœ:œOpenAIEmbeddingsœ,œidœ:œOpenAIEmbeddings-ZlOk1œ}-AstraDBSearch-41nRz{œfieldNameœ:œembeddingœ,œidœ:œAstraDBSearch-41nRzœ,œinputTypesœ:null,œtypeœ:œEmbeddingsœ}" + }, + { + "source": "ChatInput-yxMKE", + "sourceHandle": "{œbaseClassesœ:[œTextœ,œstrœ,œobjectœ,œRecordœ],œdataTypeœ:œChatInputœ,œidœ:œChatInput-yxMKEœ}", + "target": "AstraDBSearch-41nRz", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œAstraDBSearch-41nRzœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "input_value", + "id": "AstraDBSearch-41nRz", + "inputTypes": [ + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "Text", + "str", + "object", + "Record" + ], + "dataType": "ChatInput", + "id": "ChatInput-yxMKE" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-ChatInput-yxMKE{œbaseClassesœ:[œTextœ,œstrœ,œobjectœ,œRecordœ],œdataTypeœ:œChatInputœ,œidœ:œChatInput-yxMKEœ}-AstraDBSearch-41nRz{œfieldNameœ:œinput_valueœ,œidœ:œAstraDBSearch-41nRzœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}" + }, + { + "source": "RecursiveCharacterTextSplitter-tR9QM", + "sourceHandle": "{œbaseClassesœ:[œRecordœ],œdataTypeœ:œRecursiveCharacterTextSplitterœ,œidœ:œRecursiveCharacterTextSplitter-tR9QMœ}", + "target": "AstraDB-eUCSS", + "targetHandle": "{œfieldNameœ:œinputsœ,œidœ:œAstraDB-eUCSSœ,œinputTypesœ:null,œtypeœ:œRecordœ}", + "data": { + "targetHandle": { + "fieldName": "inputs", + "id": "AstraDB-eUCSS", + "inputTypes": null, + "type": "Record" + }, + "sourceHandle": { + "baseClasses": [ + "Record" + ], + "dataType": "RecursiveCharacterTextSplitter", + "id": "RecursiveCharacterTextSplitter-tR9QM" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-RecursiveCharacterTextSplitter-tR9QM{œbaseClassesœ:[œRecordœ],œdataTypeœ:œRecursiveCharacterTextSplitterœ,œidœ:œRecursiveCharacterTextSplitter-tR9QMœ}-AstraDB-eUCSS{œfieldNameœ:œinputsœ,œidœ:œAstraDB-eUCSSœ,œinputTypesœ:null,œtypeœ:œRecordœ}", + "selected": false + }, + { + "source": "OpenAIEmbeddings-9TPjc", + "sourceHandle": "{œbaseClassesœ:[œEmbeddingsœ],œdataTypeœ:œOpenAIEmbeddingsœ,œidœ:œOpenAIEmbeddings-9TPjcœ}", + "target": "AstraDB-eUCSS", + "targetHandle": "{œfieldNameœ:œembeddingœ,œidœ:œAstraDB-eUCSSœ,œinputTypesœ:null,œtypeœ:œEmbeddingsœ}", + "data": { + "targetHandle": { + "fieldName": "embedding", + "id": "AstraDB-eUCSS", + "inputTypes": null, + "type": "Embeddings" + }, + "sourceHandle": { + "baseClasses": [ + "Embeddings" + ], + "dataType": "OpenAIEmbeddings", + "id": "OpenAIEmbeddings-9TPjc" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-OpenAIEmbeddings-9TPjc{œbaseClassesœ:[œEmbeddingsœ],œdataTypeœ:œOpenAIEmbeddingsœ,œidœ:œOpenAIEmbeddings-9TPjcœ}-AstraDB-eUCSS{œfieldNameœ:œembeddingœ,œidœ:œAstraDB-eUCSSœ,œinputTypesœ:null,œtypeœ:œEmbeddingsœ}", + "selected": false + }, + { + "source": "AstraDBSearch-41nRz", + "sourceHandle": "{œbaseClassesœ:[œRecordœ],œdataTypeœ:œAstraDBSearchœ,œidœ:œAstraDBSearch-41nRzœ}", + "target": "TextOutput-BDknO", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œTextOutput-BDknOœ,œinputTypesœ:[œRecordœ,œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "input_value", + "id": "TextOutput-BDknO", + "inputTypes": [ + "Record", + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "Record" + ], + "dataType": "AstraDBSearch", + "id": "AstraDBSearch-41nRz" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-AstraDBSearch-41nRz{œbaseClassesœ:[œRecordœ],œdataTypeœ:œAstraDBSearchœ,œidœ:œAstraDBSearch-41nRzœ}-TextOutput-BDknO{œfieldNameœ:œinput_valueœ,œidœ:œTextOutput-BDknOœ,œinputTypesœ:[œRecordœ,œTextœ],œtypeœ:œstrœ}" + } + ], + "viewport": { + "x": -259.6782520315529, + "y": 90.3428735006047, + "zoom": 0.2687057134854984 + } + }, + "description": "Visit https://pre-release.langflow.org/guides/rag-with-astradb for a detailed guide of this project.\nThis project give you both Ingestion and RAG in a single file. You'll need to visit https://astra.datastax.com/ to create an Astra DB instance, your Token and grab an API Endpoint.\nRunning this project requires you to add a file in the Files component, then define a Collection Name and click on the Play icon on the Astra DB component. \n\nAfter the ingestion ends you are ready to click on the Run button at the lower left corner and start asking questions about your data.", + "name": "Vector Store RAG", + "last_tested_version": "1.0.0a0", + "is_component": false +} \ No newline at end of file diff --git a/docs/static/img/add-new-variable.png b/docs/static/img/add-new-variable.png new file mode 100644 index 0000000000000000000000000000000000000000..178cab67c0ec12e7c9b2ae6700488f18b852fc00 GIT binary patch literal 49435 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 OM|8CfwaPReg#RxiixLz7 literal 0 HcmV?d00001 diff --git a/docs/static/img/astra-configure-deployment.png b/docs/static/img/astra-configure-deployment.png new file mode 100644 index 0000000000000000000000000000000000000000..803f150d1de531e1c94b5ddf2d2f1ca96f7a249f GIT binary patch literal 207197 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 z%0D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 ?)9_y@#?N!b^tXo;E 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 I+eZHX1Hor%H2?qr literal 0 HcmV?d00001 diff --git a/docs/static/img/astra-create-database.png b/docs/static/img/astra-create-database.png new file mode 100644 index 0000000000000000000000000000000000000000..96e7f15c862a7be3c7f8cacf90c1625d590c2cc0 GIT binary patch literal 37699 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 F{|D39q`&|G literal 0 HcmV?d00001 diff --git a/docs/static/img/astra-generate-token.png b/docs/static/img/astra-generate-token.png new file mode 100644 index 0000000000000000000000000000000000000000..b4131049154c9abbb5aaa6f101fc85f14a6571f4 GIT binary patch literal 75966 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

+z*52Y|*BNzMci(W0hC$}*x3)^zIL6JA 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 D&4=Qq literal 0 HcmV?d00001 diff --git a/docs/static/img/astra-ingestion-fields.png b/docs/static/img/astra-ingestion-fields.png new file mode 100644 index 0000000000000000000000000000000000000000..e19c65e1992e0cafff250fa481acad1131e16b8b GIT binary patch literal 225568 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ƌ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 literal 0 HcmV?d00001 diff --git a/docs/static/img/astra-ingestion-flow.png b/docs/static/img/astra-ingestion-flow.png new file mode 100644 index 0000000000000000000000000000000000000000..8ee2567bcd30928f6198f3dde3d1920537af7f44 GIT binary patch literal 81772 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
GCt;uGqq^tfNo)lV_B@>v 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

eJ+)F9pn{^g{p1T*BStOlFjWBUzUsf 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 z zQ;jWEKFbr{xx+1-al1W++^mv+dB3B8zX(;ja?2+;D0Lgq40^3~_3?+i?f}A(@jV7v zHN9Vy9e8dh+jT0sGAZ<@z9`#`Hgw^I|!y04n=HG8xiw=%*emmI;uYn5(wVy6%k;bPx(iHmi5# z^(uvj^UcZUQI^%v-EBAMqw-XrOMOHDMR+3O%QUou6UCUO#VQQm7Y^6LrW zqLoGcL1M0{2h8%=%h?u#d&F_4syhQdyTv^)KbaD9ogD)4$oFCt{rnlDqB zKz$x7!sab-w!{V=N5cQI*V;9ndDJ-jQ7!7SqMTiGOdnvekdm4BU_sS4KD#Wi)4*ez z(Rhpu5Spkq@>@w+L)q`XKCctioAw#?Vb<4(=VqcQN_wo`YP}ECv*<7eE$DxDxK?ArccX2FD(Nqg*xkmE_j(vA@}8}NJ6 zRdMRoJ^L;BC`fCzZ+-0ZR|vukb$4+M_7%IEu10X|zCj^Y&$qLni5=hA=wX-Lr$Yp) z9`-j{u$I;slrD=$BiRl@nZzVF6!V&-N0c&k{Wq}o&zx3D7Z8>9 z7IL#a+d1{zN$Yj< zo*9U6tv1^-V>#2^B}O89vNecR!QC&q!pOuNJz2}^d^vdSvpW}hL)mCWM09B=Hdopu zhIuk|c%fK&0jR?BV~PJq3rXNf{pAXxvQLt7YANS0^TlT79zg6!!QPT~C5Q zyml;`GPB#n!_mdVVTC>nspNThuu}uSVc5L_-@cQh$7Zr5&;Z8+PPssP1Uqxa$Vl+cwEHnwdNqA z$h(>x)3#bNhL*+;9W5&Ra4G(%s4>#p%)6}EGaIYyy5pJx+>DzUCcLpqqz0@j&Lz}# zJS+3KDV_y6aY^!XKHvCMAUS$K+VQ}japFFka-4XuwBjNz2L|qIO0zxuTwxnIHf}qf z#0gIdX~PHkEZTT{Q;%XsVqCH5<1X8n9~_n!n%$mAy$*)a{P0|3sg~$fxc0Qo1HO<* zs|(g~03g)jss_1mje$r$Gbo*A_kh2UCSZz56j8=)Z8xs0l!ZlJm5iONE6h=mM`X&u zmnh1X&e$f(HQapDvRBw+HjRA^He;Y>!Vi#Y8rRtNF!?%6+n+HG%hZbJ=RYu~yY${FKjK%WK3t@pG4tel$#_#~LEgoaFJ&)h z0F}VtoU1-zM$0@o`96^s(<&Q&z9g2n+^Hl^w~;IgN6ue{hnzglpya#ULjan$K$+l9 z;K!P3!6kvY4D*gX!}PeJ1Dj+^@6(}yqQ!+Zhx_rdVT?1ZHI`NaU6zXp0u0FS{64)#ZTEi}8NvQMH zHABu)K!f+`{29%e$kfhXMqjql{fg9L0kQ>#hIEv-w>+G{{f6SJPI>i$=!s&M3>x%|xj3($fk?ZiKH0c!@l3 zW`4>zX%_WQ`M+J84LaMzZ&Qb=`rKw6WyN$(TOLcMKV&J0e2b@6Ih8qh0w7=jWwkJ3 z?socO?vw+Y@=neZ82S1i)BDx4)f`Z}Ll{S}9VsF|=n}jEvnEUI+NpOR_{l|v{jmBs z3%x&g;A43TP{@p3#|P(9U!)}i8Q*cwXmQu&-2161mWWNypYctuUn+7bEO1_H*b*QX zdh$qsoKs!QiU#e#yj`&^PxNgYsov_ubEC(AAI11-+jot4Av{27m6Po$a(P+vRlGJD z?)b$$tpS3tWmDL+={h1s>KYTVY4HNY0?%Q0?y*zJ2OW8_1(|&eJYSdnp<8xcUch!- z_ipbz{&W6Xx{0Vynvfz zPa^yEiG_L$D16^#tRo`+=Jz5a6C*IW40Oej{9i2^r zbQUBRX8P1pSaDZe#ssrmUAHzNb>2`0$G96rItIGfk>j~JKL1%W2uN;JH-m)!7YT?&f*UNj3d>2j? zeI{g8RPzK|lL2EhdmGuWThitK7-tjxa9^CTJ*L6m7fd!>$-4(fOk##9qS?Tt&U+Jr zo?aX!AeVl=|JHnSOHt!lcBeFoik$Va574TW>b{@cAU-4x(Q&sTMZ9z<@L;+q`dD_c zarsDh-IFRSh*v6@U-rF(7gLYs%B;}|md8NIxT@KY+1U*nOLf_(iF5TK&0nXo+HBP1;=_RrcnjZZ+0;KD1Dh5>9{qG`F3j z-t}040N2eX{hpDqjyR?=-ct^4a`36&z#A-hu9mEMw)L2@Csh%2ypUD?L6){nx!)py zBp$R0-fks1cw+bSwjE!}sruFtU)GpbQPi>$WlH%8(E(La@KpN6QvcKQ%E8#R?C_)j z{evV;WP77?>~Jr&q$r!UTOBUf-sCaR*N*VgP91@#{3h=bdzr65%csAUv0aD5Qi&qv z(|0Cd4a+$8_n((jj206m4SDu$`t~X>di{JIVEwu{ zgd}Evh|#(@^myf$MMw9EdeIY9%UdTazun<6{zpb(tL@o`C#C4}h@}kEfU!JoyHZvr zniAsRl+Du6&qC;MhWddmotwD$ zq~6&Lc`&t5!~@9q_b}T*HsS1PY8wj4fBM6YUy=9;@=>8TEA;{T*eua`8gZH4(OU)}L z@h}uc={6jDcfKw=Xxs`t*>*$fbH0oJ%ny!l1F6WOnFm&pSqqdMSRWcFZ^Sk9dRr|# zb6iIGUMUuJ~5*F&xkNizr&dO`WOI?p{urI(%4u$&FEj51n z7SET1oW#o(iom66@o=Mdo**$?tw3U7h+-v&%Z4f{1NDXa?3buG_g=lcxNp;Lf?{&Kz6b_mv z*bMtheLJwmT_{HG4dk2Y1KBp%z^!=`RrIH&{RZf~IXPNWjHlTJ{b5TB?9Vju^By7(p_=w0lcP$}!YDN>AI zO(F!ZOjIQaT!z;bf6{1YvFs}axl5KrSqINX+h7Mguq5&n&GDs~zNzn2(E-S3@E3t9 zk4~j18{|60vj3{ugs)HFNQ2kv+w?xZg}&sCOU6rEKPm{(GE>Z8)kf%^toPbjLg53K zSHoi}@PR#9(O(L98$(9uh|bS86KO5N{V1!&alUzW5KMW{pqEBYt;BKGtE8!0vhHX$ zc+q=%(xYU=ROx6s%nKXKTbU%cM)%w2SucF$Y~9q!3T0a`Rq&WM@kJv?oSVyipvzjs z4wp8rOr77H;$1f{C8u;CAQ&mJQlCVyHAG;e2^~HA2U94=`}B}OzMg5#$G+*lU_Q(B zF0glFs)P^pw(V?NbWM6Lt4_h5!%jURJY~1NJf~CKvS)R{^moUvueShHz!OlMOPoPB zcrwrhcCe6+y3(GT1jW*LsE=4WiSc^mAq}N|Ef!Ws2NL51ep%C|VqU zQc!Xk|IVKyJ1zWI$!2ttxhtn+Y9jjOaP0(;aURNFlqT&6maa#ChXXNHhs%=b2X>Oa zo6}$Xw9QH5{PY@eTECn_Y3ceBP46#?i391Kru{GCgX2Z;hx|GzHYkH2^qMRzjQ{me zAdo-lQ!5N8wR8d{qA$oxJ({;Cjf)_0`I^5dEe74I`|s8q6>ssRF6GFbLo7$w0t zhF>r_pYK2HW#dy4ZpbZu86~a$)RH@4&coDi1isvmJDcjtyfRkKU72`8>PFE)E#Fd` zQ&ajoGaY36R(@=}oSI-t$wHHfsUJJ+vx}UW4AD~&Y68mJ(pZxiPMvaw3t%M2`53T_ z*A~#(9105OM$63#5AY4El?Z8PQN7lSQuCRHgImO#McE1}CGJ3v-V(ZfM* zYvkKf709v{kmZeV^y1hPd{2g<+acJ=Chtnh$np#aLx1L@QM$S*EN)A~nF0JI2BWPQK1E$5I~CEAbQ4G8V1xLn+%b0M)a6#|a7 zI$4D6kRUc2@*n?W@C*Q5 z>KC?bl61(b0c!06IV;^$Vm`>AMX|qKOo;y3ej)CJ2sS=f9i`=b_xK&x!C$({TG79d zC%jH_CG{3o-}obRb?Um%CIH{ymb%8F?eFsvNw^&)`X2hXH8ogYg>c;}sLlx8B~-;T z5@!P4iAh_nEc0b8?`*F518EyF2awKEGHz)80g1VFCnU>yr@Z>1zxv4An@OXU#kXnb z{^s4ebu|PKUr#n>Dh7C`tX9CsyPC<9WXS^Fcm4mwuq9-jkUFJVrS%^49zFrq^aK(} z84vJ&i<$5Fr(Rt6`@>s_QNh96(~`KIZMdYsFGzSdW!Pv|K((PF-x30@C-dFop8i)AR1@OAC+zMtCHGuVEs2%`IHEjM!O4(KmMr~<`|w_ zS+B+D*o~*u)YME97PEszS6tG8q4mRYTQoQOuJ;GOe{Meh(V+ensTY#Q{7>Qw{Y85=R`lFrx z;m`V)SGV+l>j-((6Z0QbssDJZa_3hZwQ%ri)xWgQ|8{~GZUNV!q5}GBSglG<3P6Lr zXyEwK;)@*fzLe{ESbC&Bl=(4VqgE8*YPGg=h}z*>O) znzqcY8=x>5$+L9-WrKNa`Q=BN#ac-MydL;ImTxC!#AmM}3Jh)j7X)nh%&oRsXKanl z4N;O|om2T_K{CKw9#-I%wy=8dzC1WjZ_<)q&hp>-!atAYq|jSLY23M)c1a{I&UvEv z$p?dn-pRjR7mm}vmi|}IT?Nf_3qA*CYf3RdFA8FL0D9=Xty^)p{Lbww0P|e)^f`V+ zU$x|4J?fn6^cQ#xoi%=O-pUn=U7U)83sShGoE@fA9eRNJjbWkXZUJ19#clw)!sK0g zxAb2l+~x#wd{|3O2dWorX4TYwvEvF5cJS|9GGGU~(6(QYyjyzgV9Mccm_rq9_(>*B zNIeMgFWutbpD6H)kRIAIXI9*>K-NFgO=EPcJ}WEuzNVZ?F^eIMbn(;|VKZl^bE2Qo z(JL*l=k3Zh{ug-9BFFX{1ANyC?RNZGVAKWp%4P=^ElhZg*;4hXN%^)PG z^~b>df1MNX;EDri!H)WO@)=mTQX)uIhEp<^OllxkRhFbJ=y455{0rO;fadwD8-F6C z>6RW!)KwA}^&fryKi;ZXvIAYwL^Ess56$_%o>Dx}6<1$;h7J5xlQ}^PF#<*&OA$Z# zU(&Eua&&$nE8~Cks{Qp4Fl6*=X0DsV{xSLex9bj(695J%os06^(f@IM|Na)}_@~Z} z49D63%VOcbwU3p2U_6#HU2~TF%You=Wg0LK>bV-vglD#GWnysXzFm z{?%_8$=O3MUs~Of_;2fnzaLY{{H<7m=IiHK{uC%3R3?Z_0fBll?BI?q;n=3#B+z@b z%pJ7x)7;(*zLpdHe#C`zC%2Ug3dfx?z)0q5&r zF6;XAC5a$(nx$<3lKi=f^S1lb+kufT^^)=~C?kON_ZO!XM?35pso2T0SY6(S+8@vG z+ptUQ-EtVU?_uN%0&TPqK`;v3+(b_C{DtH%{;TlY!8piG44JHC+s1a>u4*g8TW2yo zzrmM}wg9F|m-VSaP@<8sIAX1#&U99+tRNFE9eYVG&?}`y^}hPKE6h?$|ItYPcv~zO z0u*1M4lRzBhla6wfA1J5#H|v}UGchdgLE)7yO%D8Jmhz<@+K%AgGMZi9=>(4#p5!7 zIxnfRq|DgE0H?1n49e>WX5}qOoKm1by;mY>Ri=Aq;{F^*TkQSo8z@sd^Z^;5m78phh5ZOMya7YkfU#A0**MHj-Kl@2(@!=JSYT(?T)e# z7Ym8XiKA3HhP01)Z7HU~N555?`}IkSST+qUWr9VQTcSN&xvF;2hj~YtPBrnilFJll zARc)p6b^6?Pb)~n`OB){V6VaIU}`8mXy)rfRa7=(i_>;wHdM;f`Lc{-T`tyx?6QVf z;o=PTN7rsY76R>LDFsDvf{2pN`;TDHV4%W8OJkw*A}<^lNVxF%;9SYVD3mTLsd4^d zda8)@)b*EE(Y4S&JHN16`G(sLd3Y%AIc~}kKI>2N z#WUB0G^V?*J70LSjd>>|EwP7(yq9%X4i^?I{QZ7pdV98SZ}XP-5fG=IEH3cd%)*7{ z*!^hij%+4QsxN%LnI%QX$RfhGZ=VcSn}iZkJy7!66I+YeSY;U>{9f@BgVKTgJtE!@ z$D;b`j-2TD@u4{(y{rl)!qZH!LZlZpO>mINyeJkPXIABfA@_c7T&=Vl^3bclYI-uA z5NOk+v>WK0B{@LP+jpBI)29#sE&g=%|5~z`hNJ{DB|%m++8ONjr;4m^`*=ZbUs|9B z5f9|mM5#MmdsJ?*F&liLYt6I)O|!kVFS>cZYZa8X9>bsLQ50N*-v zKYl(m;Ua12Js`VqY7jr#dm ziTh-G-t17-OUfua$H~^O4O?}NW1{jd&m&@aoEFAaV1wT^4A5=dl_pZAM?@MLk-)Yd z<(`BRi8Tb9Ndz|=fbj{LS1H zrYLhrG{a@!)5C?DGB;_$-o7Ny#nId^nW2tVic`Z!kfL=Vtxsmpj+?f;i6n%gV3a4_ zg<1vTM0d}(J&5@6-MLpb)!=XlJVcfLCZ=E#UNX$;joc7ZbTqD!S`{w<5+$VUymZM{ z%EKe?)2kMfr}DJ|zALk_9!m8kj!vB8eoeIZ1tJ}xT(KTB9R~nLHA`ITl(bq{*qJ4P zyTx<5gsN{4<&j-e%mG#1(rvA%YyYQEWxbTj%~V+5U0H7~89kb|`!RQ0ca8U(_gY0& z(JcWR4cL(v<<_==c68JfMVy8Ea$Vu5%v4e4&hUmCH+{lJ6D1sKU2WS+M3H1th{ZZrg!Do>R8@R@r*r!|*}2GhXD-Gj_E{p@9Kt@aV1YxWGx z7MC}taMF2Aj%7*g3zT5e2A#q?Fw^vY?)BG#fSPsop^9qS6<+#>UqUTgCqI+*RDXnq z>OQQ_+r03wI`px@yH{62uRKb;+OlUw*DOotBQAkRUyD0|#UE3U5W++w1}gD3(DUVn zwvLi8N;lokZrrTB4qAwR7}@7Ck&~1l3|%wzsml9vr9|a+NXNDFt)#fqxRv2uWbvqt zdKp}%GufK$H{QYR2al`QMLpVp;&}O4nW^{5TekZ7IV9nTXhw=-MCcP4_gEeW`U5)ArTKj8`L2+U|p5n3IVmA21BDUQ9|o|&^jtK$5d zw_+4WE&CIHlLS}$?2MiM&H3YCT{n{=ZD^QWUm@sIQ+NISh_@i)rtUXSp3{Yf9cnp5 z6d{(VE7pcMe1hX@WQ9txz*}QbrU2I!DZ42orErDfO+OLCv&Asg%=-|@C#`l-#B}B~ zE0~Yv`!OOgk(pC^q>@|@n4_1TjLMn?pPCkv8~tfA6* z>zmzS{*&zqiC9MGk>D>jx;TukcTF+`XP@o=6iW5@Ae==+2p_raMTdAQA*D^%;UlAw6WL(4Ledn8Lvlg|rJM^`rU)k+f|Hf1$xEM2$DGJ4*wyDhvL3c@x@+=YmKiMtVlh8fp; zYdb;%ZyEEl?!scpW24nxR6|agZQQHrc>og1S$(X>Qej^AL3c9PfPrma?{dQ;Tn|q> z4q<)F^2Tw1xu3weSMQSClX*3JFW~01>0$4g=5T`z1R^i$GAXeqQ)%+@yWwLk(!q56 z8@k6_XL*&tQJ%i|MaCfiuI#JVF{%Gx0gMpudViM@2knn$spNu;H(uHeM`upASjR$| z)Tvo=BbTYW*`_G0X?0T{TSXAp`9+)5+8Rfq@nX+Ac3Dh`z1KsD14(ne#rw{#c3jep z4e$hayN%`QyklXrB-_a06N}Z>{9Peok!wLKpEVPOLH2@H9=vM)hOuk4>KQOn;h=_Mfv9Sr00v^g&mBo zYC!YgFpNOYbkQ#g`Vo9%F<<(6CXVRNnXz<0+oJ*4xO<}^9JPXf4l!fhim!ZytR(`d=Vux_p^nY-;{ zIrs77nc~=Be##vKFC9%0E)}5<%2OKh-!f$5=SqdraQFR_>LRXH=v5}vf+xRFr5Pzs zBw7RQy}c+?V#SPyfjD2fbosSp>6S;mf+l8<6K@G>bB`pAh;VD98%Jjbq-=!M(EXVX z6_Ud7274lRve6#`9#4H4Ey}7`l)_5%ean99$mQjDs;5y|#_Z`YsYQ7dqYCZe0}@+q zN$c+{=Nh{sqSGHP9t&BFrEk@OT)NH{H1QoPcjLiNRC4-q zJ>5xW82OM1vU&h>-Ce0GOk3Dn5HVN0UkP@{GUHb!pT^FLGF=q$xVSn}x;#|3y=2hW zDK?^4>H+K0UM1O&0*k)eG>1lt|EhY{zA8&)*iO2etTBq%?hVL$lUT+LSnfJ&c z|2!CQivNS+)91o@gshGUjX*Yki)a)ScPS4cD2)~|)^IY=!Pq8%w3p6(r& z2pX-Lx)t6h{Nm!e8_O$-f`2nlx`|ta!?e&-Y=a{V(>%g1EE%0FsmpnBsP+H_(UA=1 z|49_v-SL4X2WQ^KI_@zZX0Rh4<3^I-1;|%8jbtU^5qo2!4$=d%Oz+u6oG&U)X;x@8 z^Oav&=fi+HvL!%%BaIwzSDfg>z!1Ydf3$!1n@_F=#~A{7YO(Q-82fjieR`qX4a;ie zhBSIe9%aVf*J2HmK5CquAeyg0O)AZ>oxw-TrlXbG zLO>S)T9wX_`Jy6o(bKJ5!}qLpX_Ml1E6je4?dHFSg>F#Dk%o{e%`#}An0vG6gPgl# zP|4LH>#vPf=Jl>V((*+w9|ja-7%vBnJ7V4`rE}dK>bu4^DU!K?x`tshFHvTC`2Iqi ze_bgfdW~o?tzp%XeluA}rNKP#8l!rkm(Rs#q&4hy^_cH(_F5VKTp~Vs{!RLc+(utC zX?0{?qj43UK0iM?x&7k8N`De@K`ie5ij_lCBxRlLXuf7aP+~qY%k6!y=8_mXT{;20 zm?>0dT=kIM}K?>jz z8^o$B)1}9TvG{7JWywodyXC?4I=x6Gf%QD-fzc6-gkpcVR9~{0R4MM;Hx$%!Sg98xe_mB3Br;GZ*8~l#bAoPVqJTBzn%8mWOPt84?6x*LEzdQ5e}Q#s*(+mVLs5XH#iCK4 zsxtkc?}mUtBy2e(OyGXBT=ZY`yt}F)LwQ;^8!$c9*vTOBn(YGsF9<$;k!QeD>(QeR zaW~!t(7wL;a)TNri&x+J`EcD*J4+l5>qfYuOfRo`#TJRwh5!5!v)+!k&re(*S=iQ` z(58W)B{2saQq^|vdaXyx-}*S{!8RTsrEq@btM(d#i-E@l`h#P)^At5bZ&ipCqFx=m~H(Uak`9L zX(^DJ>qpFYqpB+A1n@DE_|9fVK9LX*`14+uZ*s-S-{%8oy>j6G8-;t_8jQYhPnb0PhDfj0uekZSwQG zR)lV`=QqbVo!wA46W29gKrs7|7;aPsg6O6P%)~kdYowESUrg+4)cB+24m{h08%t*C zw)?)`*l^9tF&(%%snW_3hD@9nGRB6evFJ?tFW%oq?NE9hnt@Z7T;CW-fXr@43!@A`BA+r&(jB8D6&*Bvu6cw;M-5ml$Z4Hjo zWO34iCkXHHQwhD6)^GPaIAq*}tb_ORf>4VhPaO#NBjX{-tGN33@82I335*54=IZcf zER>&^3%a~xidqf1xh8u>JI5WfAhJDklP;h1qvAW?iS_M!YhFtcQCDJ|2vruTalKIcUaC6WWolVCy=wy>V7Ea_AY6gPxc%7zmF8sV>F;xA z^Qb+yTHG_4^pr~yM-j^QZ1QPld@Ky$+x&)(;|(FTO|>PkCbMDB%qC;605mu%-(s?+ zaY=pgwZy})ARp!Zd{Zx^dThD_BWt>OYJi-AV{9^_1Jeib84)u_>boK-ssW~SpSThv z=If40A2riul6YkGX^laa#RPwdXf5mnCDnBtwaz{{^RP~PQDuiM=;}(;AQaGPi6y4tu6=N0Ju^aH=ZLePhCyQu+D?3@D8VL+ zl>m-t+I2f7A^5t@6%p9>1MiO8_LGl-E^ajJ-9cC`iVxX$S)0Kfe!9IYoxeJA6q7bk z6oR>?9@Ft5yR9pn!|*fRpk{Ja5({_z1207hd$A8UG)*4wmfCAlCAPbgL~wR(Q^X4A zo)-bi{^b!IeiBgPyyj_rSKMa<(i;9|V?}nD`{Nd~VLR+QDeqTL`+}D?J@hHfunOVP zXD{y_RF^-k(*ah%VC(EG-I8-5_s>Oo@*MtY;OKj@iWcas_v&^&^C19LGmyJM=C8w* z(j*cXcF(hH6cia&=$lG*EQuydI$gN^pg5pqL<%EXu?=Vi5kXL(yFMVTo|t;N%FF_J0nM( z<4(hAoi9%!8(6$uTSLRxCOp#>mx$YqPwBW< zd!tKx58VY3-h_{x#%t=A-KUJa`JvE;4Sw4NpwBUf$exh_c&Zy%ai8P+ES_7~Z|N+dbq zOT(i$soGzp9CGGfBryu--Q;Ugo<7UfVSt*M3jRG>6xm@~mHMG1kt3TN%bP#aqYymc ztcTBLNC-iWVy9L*Hca(>L+FUU)x`>k)W)n4yf#j_`dC<|Sw*DKOwK0Ia*J$BAALe_fvvTU!9HR4Ql%Je6=YHEWJngx$$LRAqf zklNZ9%f+u?)ltlwe>W)nOW5y~^%YHYnp7+}4_Q0X*OMwi33~R-bTQ7n9-8Njhik{Z zocnMu{LG{9mv&(w_f)2lM*K!_1I+Y7rd!n>ch%T8iilZ_q1T(XPsSwEg2(LFttXpx zPs;AC@Ryxqsg>_Sh)j{2B~rG~v*bp4(2*`NoB0+x?^OZALj^4}h0>(q~Vs_QWhl|0?-aMJ)CsihkLkciGRRN=#h6^J4-_N9k zvnJ5vbR}!o@%2-^TnfIMAM8vg4*gCue~%2{C70X#?544h2tD`c`>I3nla110>*|pb zcxTGdaz;FRSCUs~TJo@G|$V4l=J+*H7M1KvB(scZ6o>0&#pazzgKoLYO(PvJk84gODnx8rQc8fQ)N zC4A>Yh*-kReWZJ(sP4vuPUioryf*-t1#c%JlEmDsI!$EV1QnnDufn-rr*D6E@WPAr z{#ju4?-Az^FTk&;#qs~K_nrYwZA;j&Ak9Ltp>(i-QdN2ls0b=e=^do^PJj>sqN1RH z^j<^(>AgchM0zg)LQ^_{gqi>$F%E){=k_kMlx>8K)7&F<)xzl}=&_C>%FfV;e6hzlwGk1#(#xJLsI zwzPi#FXKLl1@J{nHO5JNf0LE`!wxJ11IO{pi2P@8mMnYC(WD{>Kkfg^q$(Z_?7mTa z=f8~Gf7D;I27TEo{g-h+9%;h=RPY$f_5TAEEXlI7`(ud b2e*|zR7 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 literal 0 HcmV?d00001 diff --git a/docs/static/img/interaction-panel-with-chat-input.png b/docs/static/img/interaction-panel-with-chat-input.png new file mode 100644 index 0000000000000000000000000000000000000000..c5f7c79980793efda2bb3f79cc99c324cd43e901 GIT binary patch literal 127949 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 literal 0 HcmV?d00001 diff --git a/docs/static/img/ollama-gv.png b/docs/static/img/ollama-gv.png new file mode 100644 index 0000000000000000000000000000000000000000..0ee7540ee81c102fe35c553bdc98357b7c94952e GIT binary patch literal 50068 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 literal 0 HcmV?d00001 diff --git a/docs/static/img/prompt-with-template.png b/docs/static/img/prompt-with-template.png new file mode 100644 index 0000000000000000000000000000000000000000..0312b899f3df655791aa561271d2d527128d588f GIT binary patch literal 55738 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
Sh^;(IC4kdHc9dEX@(>ON2%4<3zg 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 literal 0 HcmV?d00001 diff --git a/docs/static/img/prompt.png b/docs/static/img/prompt.png new file mode 100644 index 0000000000000000000000000000000000000000..6d4260bed1db131c81a035fbd024eb1579ccf3a5 GIT binary patch literal 41403 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
0xF0Y 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≪zEudLq3!66E`b8P&qb)L>Ml3 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 literal 0 HcmV?d00001 diff --git a/docs/static/img/text-input.png b/docs/static/img/text-input.png new file mode 100644 index 0000000000000000000000000000000000000000..e8f8da24891524bec276d80d9035c97b6a82830b GIT binary patch literal 39820 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 literal 0 HcmV?d00001 diff --git a/docs/static/json_files/SearchApi_Tool.json b/docs/static/json_files/SearchApi_Tool.json index 304f191f1..8179d7c07 100644 --- a/docs/static/json_files/SearchApi_Tool.json +++ b/docs/static/json_files/SearchApi_Tool.json @@ -1 +1,1747 @@ -{"id":"7fc56f82-3493-4742-9c85-82b144127aff","data":{"nodes":[{"id":"ChatOpenAI-4Mfuz","type":"genericNode","position":{"x":-2243.8068684913856,"y":-2026.350019258601},"data":{"type":"ChatOpenAI","node":{"template":{"callbacks":{"type":"langchain_core.callbacks.base.BaseCallbackHandler","required":false,"placeholder":"","list":true,"show":false,"multiline":false,"fileTypes":[],"password":false,"name":"callbacks","advanced":false,"dynamic":false,"info":""},"async_client":{"type":"Any","required":false,"placeholder":"","list":false,"show":false,"multiline":false,"fileTypes":[],"password":false,"name":"async_client","advanced":false,"dynamic":false,"info":""},"cache":{"type":"bool","required":false,"placeholder":"","list":false,"show":false,"multiline":false,"fileTypes":[],"password":false,"name":"cache","advanced":false,"dynamic":false,"info":""},"client":{"type":"Any","required":false,"placeholder":"","list":false,"show":false,"multiline":false,"fileTypes":[],"password":false,"name":"client","advanced":false,"dynamic":false,"info":""},"default_headers":{"type":"dict","required":false,"placeholder":"","list":false,"show":false,"multiline":false,"fileTypes":[],"password":false,"name":"default_headers","advanced":false,"dynamic":false,"info":""},"default_query":{"type":"dict","required":false,"placeholder":"","list":false,"show":false,"multiline":false,"fileTypes":[],"password":false,"name":"default_query","advanced":false,"dynamic":false,"info":""},"http_client":{"type":"Any","required":false,"placeholder":"","list":false,"show":false,"multiline":false,"fileTypes":[],"password":false,"name":"http_client","advanced":false,"dynamic":false,"info":""},"max_retries":{"type":"int","required":false,"placeholder":"","list":false,"show":false,"multiline":false,"value":2,"fileTypes":[],"password":false,"name":"max_retries","advanced":false,"dynamic":false,"info":""},"max_tokens":{"type":"int","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"password":true,"name":"max_tokens","advanced":false,"dynamic":false,"info":"","value":""},"metadata":{"type":"dict","required":false,"placeholder":"","list":false,"show":false,"multiline":false,"fileTypes":[],"password":false,"name":"metadata","advanced":false,"dynamic":false,"info":""},"model_kwargs":{"type":"dict","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"password":false,"name":"model_kwargs","advanced":true,"dynamic":false,"info":""},"model_name":{"type":"str","required":false,"placeholder":"","list":true,"show":true,"multiline":false,"value":"gpt-3.5-turbo-16k","fileTypes":[],"password":false,"options":["gpt-4-1106-preview","gpt-4-vision-preview","gpt-4","gpt-4-32k","gpt-3.5-turbo","gpt-3.5-turbo-16k"],"name":"model_name","advanced":false,"dynamic":false,"info":""},"n":{"type":"int","required":false,"placeholder":"","list":false,"show":false,"multiline":false,"value":1,"fileTypes":[],"password":false,"name":"n","advanced":false,"dynamic":false,"info":""},"name":{"type":"str","required":false,"placeholder":"","list":false,"show":false,"multiline":false,"fileTypes":[],"password":false,"name":"name","advanced":false,"dynamic":false,"info":""},"openai_api_base":{"type":"str","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"password":false,"name":"openai_api_base","display_name":"OpenAI API Base","advanced":false,"dynamic":false,"info":"\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\n"},"openai_api_key":{"type":"str","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"value":"","fileTypes":[],"password":true,"name":"openai_api_key","display_name":"OpenAI API Key","advanced":false,"dynamic":false,"info":""},"openai_organization":{"type":"str","required":false,"placeholder":"","list":false,"show":false,"multiline":false,"fileTypes":[],"password":false,"name":"openai_organization","display_name":"OpenAI Organization","advanced":false,"dynamic":false,"info":""},"openai_proxy":{"type":"str","required":false,"placeholder":"","list":false,"show":false,"multiline":false,"fileTypes":[],"password":false,"name":"openai_proxy","display_name":"OpenAI Proxy","advanced":false,"dynamic":false,"info":""},"request_timeout":{"type":"float","required":false,"placeholder":"","list":false,"show":false,"multiline":false,"fileTypes":[],"password":false,"name":"request_timeout","advanced":false,"dynamic":false,"info":"","rangeSpec":{"min":-1,"max":1,"step":0.1}},"streaming":{"type":"bool","required":false,"placeholder":"","list":false,"show":false,"multiline":false,"value":false,"fileTypes":[],"password":false,"name":"streaming","advanced":false,"dynamic":false,"info":""},"tags":{"type":"str","required":false,"placeholder":"","list":true,"show":false,"multiline":false,"fileTypes":[],"password":false,"name":"tags","advanced":false,"dynamic":false,"info":""},"temperature":{"type":"float","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"value":"0.5","fileTypes":[],"password":false,"name":"temperature","advanced":false,"dynamic":false,"info":"","rangeSpec":{"min":-1,"max":1,"step":0.1}},"tiktoken_model_name":{"type":"str","required":false,"placeholder":"","list":false,"show":false,"multiline":false,"fileTypes":[],"password":false,"name":"tiktoken_model_name","advanced":false,"dynamic":false,"info":""},"verbose":{"type":"bool","required":false,"placeholder":"","list":false,"show":false,"multiline":false,"value":false,"fileTypes":[],"password":false,"name":"verbose","advanced":false,"dynamic":false,"info":""},"_type":"ChatOpenAI"},"description":"[*Deprecated*] `OpenAI` Chat large language models API.","base_classes":["BaseLanguageModel","BaseChatModel","ChatOpenAI","BaseLLM"],"display_name":"ChatOpenAI","documentation":"https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai","custom_fields":{},"output_types":[],"field_formatters":{},"beta":false},"id":"ChatOpenAI-4Mfuz"},"selected":false,"width":384,"height":649,"positionAbsolute":{"x":-2243.8068684913856,"y":-2026.350019258601},"dragging":false},{"id":"CharacterTextSplitter-WVMFU","type":"genericNode","position":{"x":-2661.4749778477553,"y":-1608.9437055023366},"data":{"type":"CharacterTextSplitter","node":{"template":{"documents":{"type":"Document","required":true,"placeholder":"","list":true,"show":true,"multiline":false,"value":"","fileTypes":[],"file_path":"","password":false,"name":"documents","advanced":false,"dynamic":false,"info":""},"chunk_overlap":{"type":"int","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"value":200,"fileTypes":[],"file_path":"","password":false,"name":"chunk_overlap","display_name":"Chunk Overlap","advanced":false,"dynamic":false,"info":""},"chunk_size":{"type":"int","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"value":"2000","fileTypes":[],"file_path":"","password":false,"name":"chunk_size","display_name":"Chunk Size","advanced":false,"dynamic":false,"info":""},"separator":{"type":"str","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"value":"\"","fileTypes":[],"file_path":"","password":false,"name":"separator","display_name":"Separator","advanced":false,"dynamic":false,"info":""},"_type":"CharacterTextSplitter"},"description":"Splitting text that looks at characters.","base_classes":["Document"],"display_name":"CharacterTextSplitter","documentation":"https://python.langchain.com/docs/modules/data_connection/document_transformers/text_splitters/character_text_splitter","custom_fields":{},"output_types":["Document"],"field_formatters":{},"beta":false},"id":"CharacterTextSplitter-WVMFU"},"selected":false,"width":384,"height":501,"positionAbsolute":{"x":-2661.4749778477553,"y":-1608.9437055023366},"dragging":false},{"id":"Chroma-OtYDg","type":"genericNode","position":{"x":-2194.2051907050227,"y":-1370.1637632208287},"data":{"type":"Chroma","node":{"template":{"documents":{"type":"Document","required":false,"placeholder":"","list":true,"show":true,"multiline":false,"fileTypes":[],"file_path":"","password":false,"name":"documents","display_name":"Documents","advanced":false,"dynamic":false,"info":""},"embedding":{"type":"Embeddings","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"file_path":"","password":false,"name":"embedding","display_name":"Embedding","advanced":false,"dynamic":false,"info":""},"chroma_server_cors_allow_origins":{"type":"str","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"file_path":"","password":false,"name":"chroma_server_cors_allow_origins","display_name":"Server CORS Allow Origins","advanced":true,"dynamic":false,"info":""},"chroma_server_grpc_port":{"type":"int","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"file_path":"","password":false,"name":"chroma_server_grpc_port","display_name":"Server gRPC Port","advanced":true,"dynamic":false,"info":""},"chroma_server_host":{"type":"str","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"file_path":"","password":false,"name":"chroma_server_host","display_name":"Server Host","advanced":true,"dynamic":false,"info":""},"chroma_server_port":{"type":"int","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"file_path":"","password":false,"name":"chroma_server_port","display_name":"Server Port","advanced":true,"dynamic":false,"info":""},"chroma_server_ssl_enabled":{"type":"bool","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"value":false,"fileTypes":[],"file_path":"","password":false,"name":"chroma_server_ssl_enabled","display_name":"Server SSL Enabled","advanced":true,"dynamic":false,"info":""},"code":{"type":"code","required":true,"placeholder":"","list":false,"show":true,"multiline":true,"value":"from typing import List, Optional, Union\n\nimport chromadb # type: ignore\nfrom langchain.embeddings.base import Embeddings\nfrom langchain.schema import BaseRetriever, Document\nfrom langchain.vectorstores import Chroma\nfrom langchain.vectorstores.base import VectorStore\n\nfrom langflow import CustomComponent\n\n\nclass ChromaComponent(CustomComponent):\n \"\"\"\n A custom component for implementing a Vector Store using Chroma.\n \"\"\"\n\n display_name: str = \"Chroma\"\n description: str = \"Implementation of Vector Store using Chroma\"\n documentation = \"https://python.langchain.com/docs/integrations/vectorstores/chroma\"\n beta: bool = True\n\n def build_config(self):\n \"\"\"\n Builds the configuration for the component.\n\n Returns:\n - dict: A dictionary containing the configuration options for the component.\n \"\"\"\n return {\n \"collection_name\": {\"display_name\": \"Collection Name\", \"value\": \"langflow\"},\n \"persist\": {\"display_name\": \"Persist\"},\n \"persist_directory\": {\"display_name\": \"Persist Directory\"},\n \"code\": {\"show\": False, \"display_name\": \"Code\"},\n \"documents\": {\"display_name\": \"Documents\", \"is_list\": True},\n \"embedding\": {\"display_name\": \"Embedding\"},\n \"chroma_server_cors_allow_origins\": {\n \"display_name\": \"Server CORS Allow Origins\",\n \"advanced\": True,\n },\n \"chroma_server_host\": {\"display_name\": \"Server Host\", \"advanced\": True},\n \"chroma_server_port\": {\"display_name\": \"Server Port\", \"advanced\": True},\n \"chroma_server_grpc_port\": {\n \"display_name\": \"Server gRPC Port\",\n \"advanced\": True,\n },\n \"chroma_server_ssl_enabled\": {\n \"display_name\": \"Server SSL Enabled\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n collection_name: str,\n persist: bool,\n embedding: Embeddings,\n chroma_server_ssl_enabled: bool,\n persist_directory: Optional[str] = None,\n documents: Optional[List[Document]] = None,\n chroma_server_cors_allow_origins: Optional[str] = None,\n chroma_server_host: Optional[str] = None,\n chroma_server_port: Optional[int] = None,\n chroma_server_grpc_port: Optional[int] = None,\n ) -> Union[VectorStore, BaseRetriever]:\n \"\"\"\n Builds the Vector Store or BaseRetriever object.\n\n Args:\n - collection_name (str): The name of the collection.\n - persist_directory (Optional[str]): The directory to persist the Vector Store to.\n - chroma_server_ssl_enabled (bool): Whether to enable SSL for the Chroma server.\n - persist (bool): Whether to persist the Vector Store or not.\n - embedding (Optional[Embeddings]): The embeddings to use for the Vector Store.\n - documents (Optional[Document]): The documents to use for the Vector Store.\n - chroma_server_cors_allow_origins (Optional[str]): The CORS allow origins for the Chroma server.\n - chroma_server_host (Optional[str]): The host for the Chroma server.\n - chroma_server_port (Optional[int]): The port for the Chroma server.\n - chroma_server_grpc_port (Optional[int]): The gRPC port for the Chroma server.\n\n Returns:\n - Union[VectorStore, BaseRetriever]: The Vector Store or BaseRetriever object.\n \"\"\"\n\n # Chroma settings\n chroma_settings = None\n\n if chroma_server_host is not None:\n chroma_settings = chromadb.config.Settings(\n chroma_server_cors_allow_origins=chroma_server_cors_allow_origins or None,\n chroma_server_host=chroma_server_host,\n chroma_server_port=chroma_server_port or None,\n chroma_server_grpc_port=chroma_server_grpc_port or None,\n chroma_server_ssl_enabled=chroma_server_ssl_enabled,\n )\n\n # If documents, then we need to create a Chroma instance using .from_documents\n if documents is not None and embedding is not None:\n if len(documents) == 0:\n raise ValueError(\"If documents are provided, there must be at least one document.\")\n return Chroma.from_documents(\n documents=documents, # type: ignore\n persist_directory=persist_directory if persist else None,\n collection_name=collection_name,\n embedding=embedding,\n client_settings=chroma_settings,\n )\n\n return Chroma(persist_directory=persist_directory, client_settings=chroma_settings)\n","fileTypes":[],"file_path":"","password":false,"name":"code","advanced":false,"dynamic":true,"info":""},"collection_name":{"type":"str","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"value":"video","fileTypes":[],"file_path":"","password":false,"name":"collection_name","display_name":"Collection Name","advanced":false,"dynamic":false,"info":""},"persist":{"type":"bool","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"value":false,"fileTypes":[],"file_path":"","password":false,"name":"persist","display_name":"Persist","advanced":false,"dynamic":false,"info":""},"persist_directory":{"type":"str","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"file_path":"","password":false,"name":"persist_directory","display_name":"Persist Directory","advanced":false,"dynamic":false,"info":""},"_type":"CustomComponent"},"description":"Implementation of Vector Store using Chroma","base_classes":["VectorStore","BaseRetriever"],"display_name":"Chroma","documentation":"https://python.langchain.com/docs/integrations/vectorstores/chroma","custom_fields":{"chroma_server_cors_allow_origins":null,"chroma_server_grpc_port":null,"chroma_server_host":null,"chroma_server_port":null,"chroma_server_ssl_enabled":null,"collection_name":null,"documents":null,"embedding":null,"persist":null,"persist_directory":null},"output_types":["Chroma"],"field_formatters":{},"beta":true},"id":"Chroma-OtYDg"},"selected":false,"width":384,"height":625,"positionAbsolute":{"x":-2194.2051907050227,"y":-1370.1637632208287},"dragging":false},{"id":"OpenAIEmbeddings-9yqtI","type":"genericNode","position":{"x":-2653.011009324626,"y":-1103.8414515074774},"data":{"type":"OpenAIEmbeddings","node":{"template":{"allowed_special":{"type":"str","required":false,"placeholder":"","list":true,"show":true,"multiline":false,"value":[],"fileTypes":[],"password":false,"name":"allowed_special","advanced":true,"dynamic":false,"info":""},"async_client":{"type":"Any","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"password":false,"name":"async_client","advanced":true,"dynamic":false,"info":""},"chunk_size":{"type":"int","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"value":1000,"fileTypes":[],"password":false,"name":"chunk_size","advanced":true,"dynamic":false,"info":""},"client":{"type":"Any","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"password":false,"name":"client","advanced":true,"dynamic":false,"info":""},"default_headers":{"type":"dict","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"password":false,"name":"default_headers","advanced":true,"dynamic":false,"info":""},"default_query":{"type":"dict","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"password":false,"name":"default_query","advanced":true,"dynamic":false,"info":""},"deployment":{"type":"str","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"value":"text-embedding-ada-002","fileTypes":[],"password":false,"name":"deployment","advanced":true,"dynamic":false,"info":""},"disallowed_special":{"type":"str","required":false,"placeholder":"","list":true,"show":true,"multiline":false,"value":"all","fileTypes":[],"password":false,"name":"disallowed_special","advanced":true,"dynamic":false,"info":""},"embedding_ctx_length":{"type":"int","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"value":8191,"fileTypes":[],"password":false,"name":"embedding_ctx_length","advanced":true,"dynamic":false,"info":""},"headers":{"type":"Any","required":false,"placeholder":"","list":false,"show":false,"multiline":true,"value":"{\"Authorization\": \"Bearer \"}","fileTypes":[],"password":false,"name":"headers","advanced":true,"dynamic":false,"info":""},"http_client":{"type":"Any","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"password":false,"name":"http_client","advanced":true,"dynamic":false,"info":""},"max_retries":{"type":"int","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"value":2,"fileTypes":[],"password":false,"name":"max_retries","advanced":true,"dynamic":false,"info":""},"model":{"type":"str","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"value":"text-embedding-ada-002","fileTypes":[],"password":false,"name":"model","advanced":true,"dynamic":false,"info":""},"model_kwargs":{"type":"dict","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"password":false,"name":"model_kwargs","advanced":true,"dynamic":false,"info":""},"openai_api_base":{"type":"str","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"password":true,"name":"openai_api_base","display_name":"OpenAI API Base","advanced":true,"dynamic":false,"info":"","value":""},"openai_api_key":{"type":"str","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"value":"","fileTypes":[],"password":true,"name":"openai_api_key","display_name":"OpenAI API Key","advanced":false,"dynamic":false,"info":""},"openai_api_type":{"type":"str","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"password":true,"name":"openai_api_type","display_name":"OpenAI API Type","advanced":true,"dynamic":false,"info":"","value":""},"openai_api_version":{"type":"str","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"password":true,"name":"openai_api_version","display_name":"OpenAI API Version","advanced":true,"dynamic":false,"info":"","value":""},"openai_organization":{"type":"str","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"password":false,"name":"openai_organization","display_name":"OpenAI Organization","advanced":true,"dynamic":false,"info":""},"openai_proxy":{"type":"str","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"password":false,"name":"openai_proxy","display_name":"OpenAI Proxy","advanced":true,"dynamic":false,"info":""},"request_timeout":{"type":"float","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"password":false,"name":"request_timeout","advanced":true,"dynamic":false,"info":"","rangeSpec":{"min":-1,"max":1,"step":0.1}},"retry_max_seconds":{"type":"int","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"value":20,"fileTypes":[],"password":false,"name":"retry_max_seconds","advanced":true,"dynamic":false,"info":""},"retry_min_seconds":{"type":"int","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"value":4,"fileTypes":[],"password":false,"name":"retry_min_seconds","advanced":true,"dynamic":false,"info":""},"show_progress_bar":{"type":"bool","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"value":false,"fileTypes":[],"password":false,"name":"show_progress_bar","advanced":true,"dynamic":false,"info":""},"skip_empty":{"type":"bool","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"value":false,"fileTypes":[],"password":false,"name":"skip_empty","advanced":true,"dynamic":false,"info":""},"tiktoken_enabled":{"type":"bool","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"value":"","fileTypes":[],"password":true,"name":"tiktoken_enabled","advanced":false,"dynamic":false,"info":""},"tiktoken_model_name":{"type":"str","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"password":true,"name":"tiktoken_model_name","advanced":false,"dynamic":false,"info":"","value":""},"_type":"OpenAIEmbeddings"},"description":"[*Deprecated*] OpenAI embedding models.","base_classes":["Embeddings","OpenAIEmbeddings"],"display_name":"OpenAIEmbeddings","documentation":"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/openai","custom_fields":{},"output_types":[],"field_formatters":{},"beta":false},"id":"OpenAIEmbeddings-9yqtI"},"selected":false,"width":384,"height":443,"positionAbsolute":{"x":-2653.011009324626,"y":-1103.8414515074774},"dragging":false},{"id":"RetrievalQA-DpylI","type":"genericNode","position":{"x":-1757.239471200792,"y":-1258.2132589352987},"data":{"type":"RetrievalQA","node":{"template":{"callbacks":{"type":"langchain_core.callbacks.base.BaseCallbackHandler","required":false,"placeholder":"","list":true,"show":false,"multiline":false,"fileTypes":[],"password":false,"name":"callbacks","advanced":false,"dynamic":false,"info":""},"combine_documents_chain":{"type":"BaseCombineDocumentsChain","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"password":false,"name":"combine_documents_chain","advanced":false,"dynamic":false,"info":""},"memory":{"type":"BaseMemory","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"password":false,"name":"memory","advanced":false,"dynamic":false,"info":""},"retriever":{"type":"BaseRetriever","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"password":false,"name":"retriever","advanced":false,"dynamic":false,"info":""},"input_key":{"type":"str","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"value":"query","fileTypes":[],"password":false,"name":"input_key","advanced":true,"dynamic":false,"info":""},"metadata":{"type":"dict","required":false,"placeholder":"","list":false,"show":false,"multiline":false,"fileTypes":[],"password":false,"name":"metadata","advanced":false,"dynamic":false,"info":""},"name":{"type":"str","required":false,"placeholder":"","list":false,"show":false,"multiline":false,"fileTypes":[],"password":false,"name":"name","advanced":false,"dynamic":false,"info":""},"output_key":{"type":"str","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"value":"result","fileTypes":[],"password":false,"name":"output_key","advanced":true,"dynamic":false,"info":""},"return_source_documents":{"type":"bool","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"value":true,"fileTypes":[],"password":false,"name":"return_source_documents","advanced":true,"dynamic":false,"info":""},"tags":{"type":"str","required":false,"placeholder":"","list":true,"show":false,"multiline":false,"fileTypes":[],"password":false,"name":"tags","advanced":false,"dynamic":false,"info":""},"verbose":{"type":"bool","required":false,"placeholder":"","list":false,"show":false,"multiline":false,"fileTypes":[],"password":false,"name":"verbose","advanced":true,"dynamic":false,"info":""},"_type":"RetrievalQA"},"description":"Chain for question-answering against an index.","base_classes":["Chain","RetrievalQA","BaseRetrievalQA","Callable"],"display_name":"RetrievalQA","documentation":"https://python.langchain.com/docs/modules/chains/popular/vector_db_qa","custom_fields":{},"output_types":[],"field_formatters":{},"beta":false},"id":"RetrievalQA-DpylI"},"selected":false,"width":384,"height":339,"positionAbsolute":{"x":-1757.239471200792,"y":-1258.2132589352987},"dragging":true},{"id":"CombineDocsChain-afKOq","type":"genericNode","position":{"x":-1775.9040057312934,"y":-1644.0423777157919},"data":{"type":"CombineDocsChain","node":{"template":{"llm":{"type":"BaseLanguageModel","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"value":"","fileTypes":[],"file_path":"","password":false,"name":"llm","display_name":"LLM","advanced":false,"dynamic":false,"info":""},"chain_type":{"type":"str","required":true,"placeholder":"","list":true,"show":true,"multiline":false,"value":"refine","fileTypes":[],"file_path":"","password":false,"options":["stuff","map_reduce","map_rerank","refine"],"name":"chain_type","advanced":false,"dynamic":false,"info":""},"_type":"load_qa_chain"},"description":"Load question answering chain.","base_classes":["BaseCombineDocumentsChain","Callable"],"display_name":"CombineDocsChain","documentation":"","custom_fields":{},"output_types":[],"field_formatters":{},"beta":false},"id":"CombineDocsChain-afKOq"},"selected":false,"width":384,"height":333,"dragging":false,"positionAbsolute":{"x":-1775.9040057312934,"y":-1644.0423777157919}},{"id":"SearchApi-kZmEj","type":"genericNode","position":{"x":-3074.364183247263,"y":-1782.5742787937606},"data":{"type":"SearchApi","node":{"template":{"api_key":{"type":"str","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"file_path":"","password":true,"name":"api_key","display_name":"API Key","advanced":false,"dynamic":false,"info":"The API key to use SearchApi.","value":""},"code":{"type":"code","required":true,"placeholder":"","list":false,"show":true,"multiline":true,"value":"from langflow import CustomComponent\nfrom langchain.schema import Document\nfrom langflow.services.database.models.base import orjson_dumps\nfrom langchain_community.utilities.searchapi import SearchApiAPIWrapper\nfrom typing import Optional\n\n\nclass SearchApi(CustomComponent):\n display_name: str = \"SearchApi\"\n description: str = \"Real-time search engines API.\"\n output_types: list[str] = [\"Document\"]\n documentation: str = \"https://www.searchapi.io/docs/google\"\n field_config = {\n \"engine\": {\n \"display_name\": \"Engine\",\n \"field_type\": \"str\",\n \"info\": \"The search engine to use.\",\n },\n \"params\": {\n \"display_name\": \"Parameters\",\n \"info\": \"The parameters to send with the request.\",\n },\n \"code\": {\"show\": False},\n \"api_key\": {\n \"display_name\": \"API Key\",\n \"field_type\": \"str\",\n \"required\": True, \n \"password\": True,\n \"info\": \"The API key to use SearchApi.\",\n },\n }\n\n def build(\n self,\n engine: str,\n api_key: str,\n params: Optional[dict] = None,\n ) -> Document:\n if params is None:\n params = {}\n\n search_api_wrapper = SearchApiAPIWrapper(engine=engine, searchapi_api_key=api_key)\n\n query = params.pop(\"query\", \"default query\") \n results = search_api_wrapper.results(query, **params)\n\n result = orjson_dumps(results, indent_2=False)\n \n document = Document(page_content=result) \n\n return document","fileTypes":[],"file_path":"","password":false,"name":"code","advanced":false,"dynamic":true,"info":""},"engine":{"type":"str","required":true,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"file_path":"","password":false,"name":"engine","display_name":"Engine","advanced":false,"dynamic":false,"info":"The search engine to use.","value":"youtube_transcripts"},"params":{"type":"dict","required":false,"placeholder":"","list":false,"show":true,"multiline":false,"fileTypes":[],"file_path":"","password":false,"name":"params","display_name":"Parameters","advanced":false,"dynamic":false,"info":"The parameters to send with the request.","value":[{"video_id":"krsBRQbOPQ4"}]},"_type":"CustomComponent"},"description":"Real-time search engines API.","base_classes":["Document"],"display_name":"SearchApi","documentation":"https://www.searchapi.io/docs/google","custom_fields":{"api_key":null,"engine":null,"params":null},"output_types":["SearchApi"],"field_formatters":{},"beta":true},"id":"SearchApi-kZmEj"},"selected":false,"width":384,"height":539,"dragging":false,"positionAbsolute":{"x":-3074.364183247263,"y":-1782.5742787937606}}],"edges":[{"source":"CharacterTextSplitter-WVMFU","sourceHandle":"{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œCharacterTextSplitterœ,œidœ:œCharacterTextSplitter-WVMFUœ}","target":"Chroma-OtYDg","targetHandle":"{œfieldNameœ:œdocumentsœ,œidœ:œChroma-OtYDgœ,œinputTypesœ:null,œtypeœ:œDocumentœ}","data":{"targetHandle":{"fieldName":"documents","id":"Chroma-OtYDg","inputTypes":null,"type":"Document"},"sourceHandle":{"baseClasses":["Document"],"dataType":"CharacterTextSplitter","id":"CharacterTextSplitter-WVMFU"}},"style":{"stroke":"#555"},"className":"stroke-gray-900 stroke-connection","animated":false,"id":"reactflow__edge-CharacterTextSplitter-WVMFU{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œCharacterTextSplitterœ,œidœ:œCharacterTextSplitter-WVMFUœ}-Chroma-OtYDg{œfieldNameœ:œdocumentsœ,œidœ:œChroma-OtYDgœ,œinputTypesœ:null,œtypeœ:œDocumentœ}"},{"source":"OpenAIEmbeddings-9yqtI","sourceHandle":"{œbaseClassesœ:[œEmbeddingsœ,œOpenAIEmbeddingsœ],œdataTypeœ:œOpenAIEmbeddingsœ,œidœ:œOpenAIEmbeddings-9yqtIœ}","target":"Chroma-OtYDg","targetHandle":"{œfieldNameœ:œembeddingœ,œidœ:œChroma-OtYDgœ,œinputTypesœ:null,œtypeœ:œEmbeddingsœ}","data":{"targetHandle":{"fieldName":"embedding","id":"Chroma-OtYDg","inputTypes":null,"type":"Embeddings"},"sourceHandle":{"baseClasses":["Embeddings","OpenAIEmbeddings"],"dataType":"OpenAIEmbeddings","id":"OpenAIEmbeddings-9yqtI"}},"style":{"stroke":"#555"},"className":"stroke-gray-900 stroke-connection","animated":false,"id":"reactflow__edge-OpenAIEmbeddings-9yqtI{œbaseClassesœ:[œEmbeddingsœ,œOpenAIEmbeddingsœ],œdataTypeœ:œOpenAIEmbeddingsœ,œidœ:œOpenAIEmbeddings-9yqtIœ}-Chroma-OtYDg{œfieldNameœ:œembeddingœ,œidœ:œChroma-OtYDgœ,œinputTypesœ:null,œtypeœ:œEmbeddingsœ}"},{"source":"Chroma-OtYDg","sourceHandle":"{œbaseClassesœ:[œVectorStoreœ,œBaseRetrieverœ],œdataTypeœ:œChromaœ,œidœ:œChroma-OtYDgœ}","target":"RetrievalQA-DpylI","targetHandle":"{œfieldNameœ:œretrieverœ,œidœ:œRetrievalQA-DpylIœ,œinputTypesœ:null,œtypeœ:œBaseRetrieverœ}","data":{"targetHandle":{"fieldName":"retriever","id":"RetrievalQA-DpylI","inputTypes":null,"type":"BaseRetriever"},"sourceHandle":{"baseClasses":["VectorStore","BaseRetriever"],"dataType":"Chroma","id":"Chroma-OtYDg"}},"style":{"stroke":"#555"},"className":"stroke-gray-900 stroke-connection","animated":false,"id":"reactflow__edge-Chroma-OtYDg{œbaseClassesœ:[œVectorStoreœ,œBaseRetrieverœ],œdataTypeœ:œChromaœ,œidœ:œChroma-OtYDgœ}-RetrievalQA-DpylI{œfieldNameœ:œretrieverœ,œidœ:œRetrievalQA-DpylIœ,œinputTypesœ:null,œtypeœ:œBaseRetrieverœ}"},{"source":"ChatOpenAI-4Mfuz","sourceHandle":"{œbaseClassesœ:[œBaseLanguageModelœ,œBaseChatModelœ,œChatOpenAIœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-4Mfuzœ}","target":"CombineDocsChain-afKOq","targetHandle":"{œfieldNameœ:œllmœ,œidœ:œCombineDocsChain-afKOqœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}","data":{"targetHandle":{"fieldName":"llm","id":"CombineDocsChain-afKOq","inputTypes":null,"type":"BaseLanguageModel"},"sourceHandle":{"baseClasses":["BaseLanguageModel","BaseChatModel","ChatOpenAI","BaseLLM"],"dataType":"ChatOpenAI","id":"ChatOpenAI-4Mfuz"}},"style":{"stroke":"#555"},"className":"stroke-gray-900 stroke-connection","animated":false,"id":"reactflow__edge-ChatOpenAI-4Mfuz{œbaseClassesœ:[œBaseLanguageModelœ,œBaseChatModelœ,œChatOpenAIœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-4Mfuzœ}-CombineDocsChain-afKOq{œfieldNameœ:œllmœ,œidœ:œCombineDocsChain-afKOqœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}"},{"source":"CombineDocsChain-afKOq","sourceHandle":"{œbaseClassesœ:[œBaseCombineDocumentsChainœ,œCallableœ],œdataTypeœ:œCombineDocsChainœ,œidœ:œCombineDocsChain-afKOqœ}","target":"RetrievalQA-DpylI","targetHandle":"{œfieldNameœ:œcombine_documents_chainœ,œidœ:œRetrievalQA-DpylIœ,œinputTypesœ:null,œtypeœ:œBaseCombineDocumentsChainœ}","data":{"targetHandle":{"fieldName":"combine_documents_chain","id":"RetrievalQA-DpylI","inputTypes":null,"type":"BaseCombineDocumentsChain"},"sourceHandle":{"baseClasses":["BaseCombineDocumentsChain","Callable"],"dataType":"CombineDocsChain","id":"CombineDocsChain-afKOq"}},"style":{"stroke":"#555"},"className":"stroke-gray-900 stroke-connection","animated":false,"id":"reactflow__edge-CombineDocsChain-afKOq{œbaseClassesœ:[œBaseCombineDocumentsChainœ,œCallableœ],œdataTypeœ:œCombineDocsChainœ,œidœ:œCombineDocsChain-afKOqœ}-RetrievalQA-DpylI{œfieldNameœ:œcombine_documents_chainœ,œidœ:œRetrievalQA-DpylIœ,œinputTypesœ:null,œtypeœ:œBaseCombineDocumentsChainœ}"},{"source":"SearchApi-kZmEj","sourceHandle":"{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œSearchApiœ,œidœ:œSearchApi-kZmEjœ}","target":"CharacterTextSplitter-WVMFU","targetHandle":"{œfieldNameœ:œdocumentsœ,œidœ:œCharacterTextSplitter-WVMFUœ,œinputTypesœ:null,œtypeœ:œDocumentœ}","data":{"targetHandle":{"fieldName":"documents","id":"CharacterTextSplitter-WVMFU","inputTypes":null,"type":"Document"},"sourceHandle":{"baseClasses":["Document"],"dataType":"SearchApi","id":"SearchApi-kZmEj"}},"style":{"stroke":"#555"},"className":"stroke-gray-900 stroke-connection","animated":false,"id":"reactflow__edge-SearchApi-kZmEj{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œSearchApiœ,œidœ:œSearchApi-kZmEjœ}-CharacterTextSplitter-WVMFU{œfieldNameœ:œdocumentsœ,œidœ:œCharacterTextSplitter-WVMFUœ,œinputTypesœ:null,œtypeœ:œDocumentœ}"}],"viewport":{"x":2046.3642433866817,"y":1270.2852546488134,"zoom":0.6177254407441625}},"description":"Real-time Google Search engine q&a.","name":"SearchApi Tool","last_tested_version":"0.6.5a9","is_component":false} \ No newline at end of file +{ + "id": "7fc56f82-3493-4742-9c85-82b144127aff", + "data": { + "nodes": [ + { + "id": "ChatOpenAI-4Mfuz", + "type": "genericNode", + "position": { + "x": -2243.8068684913856, + "y": -2026.350019258601 + }, + "data": { + "type": "ChatOpenAI", + "node": { + "template": { + "callbacks": { + "type": "langchain_core.callbacks.base.BaseCallbackHandler", + "required": false, + "placeholder": "", + "list": true, + "show": false, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "callbacks", + "advanced": false, + "dynamic": false, + "info": "" + }, + "async_client": { + "type": "Any", + "required": false, + "placeholder": "", + "list": false, + "show": false, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "async_client", + "advanced": false, + "dynamic": false, + "info": "" + }, + "cache": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": false, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "cache", + "advanced": false, + "dynamic": false, + "info": "" + }, + "client": { + "type": "Any", + "required": false, + "placeholder": "", + "list": false, + "show": false, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "client", + "advanced": false, + "dynamic": false, + "info": "" + }, + "default_headers": { + "type": "dict", + "required": false, + "placeholder": "", + "list": false, + "show": false, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "default_headers", + "advanced": false, + "dynamic": false, + "info": "" + }, + "default_query": { + "type": "dict", + "required": false, + "placeholder": "", + "list": false, + "show": false, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "default_query", + "advanced": false, + "dynamic": false, + "info": "" + }, + "http_client": { + "type": "Any", + "required": false, + "placeholder": "", + "list": false, + "show": false, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "http_client", + "advanced": false, + "dynamic": false, + "info": "" + }, + "max_retries": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": false, + "multiline": false, + "value": 2, + "fileTypes": [], + "password": false, + "name": "max_retries", + "advanced": false, + "dynamic": false, + "info": "" + }, + "max_tokens": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "password": true, + "name": "max_tokens", + "advanced": false, + "dynamic": false, + "info": "", + "value": "" + }, + "metadata": { + "type": "dict", + "required": false, + "placeholder": "", + "list": false, + "show": false, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "metadata", + "advanced": false, + "dynamic": false, + "info": "" + }, + "model_kwargs": { + "type": "dict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "model_kwargs", + "advanced": true, + "dynamic": false, + "info": "" + }, + "model_name": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "gpt-3.5-turbo-16k", + "fileTypes": [], + "password": false, + "options": [ + "gpt-4-1106-preview", + "gpt-4-vision-preview", + "gpt-4", + "gpt-4-32k", + "gpt-3.5-turbo", + "gpt-3.5-turbo-16k" + ], + "name": "model_name", + "advanced": false, + "dynamic": false, + "info": "" + }, + "n": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": false, + "multiline": false, + "value": 1, + "fileTypes": [], + "password": false, + "name": "n", + "advanced": false, + "dynamic": false, + "info": "" + }, + "name": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": false, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "name", + "advanced": false, + "dynamic": false, + "info": "" + }, + "openai_api_base": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "openai_api_base", + "display_name": "OpenAI API Base", + "advanced": false, + "dynamic": false, + "info": "\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\n" + }, + "openai_api_key": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "", + "fileTypes": [], + "password": true, + "name": "openai_api_key", + "display_name": "OpenAI API Key", + "advanced": false, + "dynamic": false, + "info": "" + }, + "openai_organization": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": false, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "openai_organization", + "display_name": "OpenAI Organization", + "advanced": false, + "dynamic": false, + "info": "" + }, + "openai_proxy": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": false, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "openai_proxy", + "display_name": "OpenAI Proxy", + "advanced": false, + "dynamic": false, + "info": "" + }, + "request_timeout": { + "type": "float", + "required": false, + "placeholder": "", + "list": false, + "show": false, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "request_timeout", + "advanced": false, + "dynamic": false, + "info": "", + "rangeSpec": { + "min": -1, + "max": 1, + "step": 0.1 + } + }, + "streaming": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": false, + "multiline": false, + "value": false, + "fileTypes": [], + "password": false, + "name": "streaming", + "advanced": false, + "dynamic": false, + "info": "" + }, + "tags": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": false, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "tags", + "advanced": false, + "dynamic": false, + "info": "" + }, + "temperature": { + "type": "float", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "0.5", + "fileTypes": [], + "password": false, + "name": "temperature", + "advanced": false, + "dynamic": false, + "info": "", + "rangeSpec": { + "min": -1, + "max": 1, + "step": 0.1 + } + }, + "tiktoken_model_name": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": false, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "tiktoken_model_name", + "advanced": false, + "dynamic": false, + "info": "" + }, + "verbose": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": false, + "multiline": false, + "value": false, + "fileTypes": [], + "password": false, + "name": "verbose", + "advanced": false, + "dynamic": false, + "info": "" + }, + "_type": "ChatOpenAI" + }, + "description": "[*Deprecated*] `OpenAI` Chat large language models API.", + "base_classes": [ + "BaseLanguageModel", + "BaseChatModel", + "ChatOpenAI", + "BaseLLM" + ], + "display_name": "ChatOpenAI", + "documentation": "https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai", + "custom_fields": {}, + "output_types": [], + "field_formatters": {}, + "beta": false + }, + "id": "ChatOpenAI-4Mfuz" + }, + "selected": false, + "width": 384, + "height": 649, + "positionAbsolute": { + "x": -2243.8068684913856, + "y": -2026.350019258601 + }, + "dragging": false + }, + { + "id": "CharacterTextSplitter-WVMFU", + "type": "genericNode", + "position": { + "x": -2661.4749778477553, + "y": -1608.9437055023366 + }, + "data": { + "type": "CharacterTextSplitter", + "node": { + "template": { + "documents": { + "type": "Document", + "required": true, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "documents", + "advanced": false, + "dynamic": false, + "info": "" + }, + "chunk_overlap": { + "type": "int", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 200, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "chunk_overlap", + "display_name": "Chunk Overlap", + "advanced": false, + "dynamic": false, + "info": "" + }, + "chunk_size": { + "type": "int", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "2000", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "chunk_size", + "display_name": "Chunk Size", + "advanced": false, + "dynamic": false, + "info": "" + }, + "separator": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "\"", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "separator", + "display_name": "Separator", + "advanced": false, + "dynamic": false, + "info": "" + }, + "_type": "CharacterTextSplitter" + }, + "description": "Splitting text that looks at characters.", + "base_classes": [ + "Document" + ], + "display_name": "CharacterTextSplitter", + "documentation": "https://python.langchain.com/docs/modules/data_connection/document_transformers/text_splitters/character_text_splitter", + "custom_fields": {}, + "output_types": [ + "Document" + ], + "field_formatters": {}, + "beta": false + }, + "id": "CharacterTextSplitter-WVMFU" + }, + "selected": false, + "width": 384, + "height": 501, + "positionAbsolute": { + "x": -2661.4749778477553, + "y": -1608.9437055023366 + }, + "dragging": false + }, + { + "id": "Chroma-OtYDg", + "type": "genericNode", + "position": { + "x": -2194.2051907050227, + "y": -1370.1637632208287 + }, + "data": { + "type": "Chroma", + "node": { + "template": { + "documents": { + "type": "Document", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "documents", + "display_name": "Documents", + "advanced": false, + "dynamic": false, + "info": "" + }, + "embedding": { + "type": "Embeddings", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "embedding", + "display_name": "Embedding", + "advanced": false, + "dynamic": false, + "info": "" + }, + "chroma_server_cors_allow_origins": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "chroma_server_cors_allow_origins", + "display_name": "Server CORS Allow Origins", + "advanced": true, + "dynamic": false, + "info": "" + }, + "chroma_server_grpc_port": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "chroma_server_grpc_port", + "display_name": "Server gRPC Port", + "advanced": true, + "dynamic": false, + "info": "" + }, + "chroma_server_host": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "chroma_server_host", + "display_name": "Server Host", + "advanced": true, + "dynamic": false, + "info": "" + }, + "chroma_server_port": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "chroma_server_port", + "display_name": "Server Port", + "advanced": true, + "dynamic": false, + "info": "" + }, + "chroma_server_ssl_enabled": { + "type": "bool", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "chroma_server_ssl_enabled", + "display_name": "Server SSL Enabled", + "advanced": true, + "dynamic": false, + "info": "" + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import List, Optional, Union\n\nimport chromadb # type: ignore\nfrom langchain.embeddings.base import Embeddings\nfrom langchain.schema import BaseRetriever, Document\nfrom langchain.vectorstores import Chroma\nfrom langchain.vectorstores.base import VectorStore\n\nfrom langflow.custom import CustomComponent\n\n\nclass ChromaComponent(CustomComponent):\n \"\"\"\n A custom component for implementing a Vector Store using Chroma.\n \"\"\"\n\n display_name: str = \"Chroma\"\n description: str = \"Implementation of Vector Store using Chroma\"\n documentation = \"https://python.langchain.com/docs/integrations/vectorstores/chroma\"\n beta: bool = True\n\n def build_config(self):\n \"\"\"\n Builds the configuration for the component.\n\n Returns:\n - dict: A dictionary containing the configuration options for the component.\n \"\"\"\n return {\n \"collection_name\": {\"display_name\": \"Collection Name\", \"value\": \"langflow\"},\n \"persist\": {\"display_name\": \"Persist\"},\n \"persist_directory\": {\"display_name\": \"Persist Directory\"},\n \"code\": {\"show\": False, \"display_name\": \"Code\"},\n \"documents\": {\"display_name\": \"Documents\", \"is_list\": True},\n \"embedding\": {\"display_name\": \"Embedding\"},\n \"chroma_server_cors_allow_origins\": {\n \"display_name\": \"Server CORS Allow Origins\",\n \"advanced\": True,\n },\n \"chroma_server_host\": {\"display_name\": \"Server Host\", \"advanced\": True},\n \"chroma_server_port\": {\"display_name\": \"Server Port\", \"advanced\": True},\n \"chroma_server_grpc_port\": {\n \"display_name\": \"Server gRPC Port\",\n \"advanced\": True,\n },\n \"chroma_server_ssl_enabled\": {\n \"display_name\": \"Server SSL Enabled\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n collection_name: str,\n persist: bool,\n embedding: Embeddings,\n chroma_server_ssl_enabled: bool,\n persist_directory: Optional[str] = None,\n documents: Optional[List[Document]] = None,\n chroma_server_cors_allow_origins: Optional[str] = None,\n chroma_server_host: Optional[str] = None,\n chroma_server_port: Optional[int] = None,\n chroma_server_grpc_port: Optional[int] = None,\n ) -> Union[VectorStore, BaseRetriever]:\n \"\"\"\n Builds the Vector Store or BaseRetriever object.\n\n Args:\n - collection_name (str): The name of the collection.\n - persist_directory (Optional[str]): The directory to persist the Vector Store to.\n - chroma_server_ssl_enabled (bool): Whether to enable SSL for the Chroma server.\n - persist (bool): Whether to persist the Vector Store or not.\n - embedding (Optional[Embeddings]): The embeddings to use for the Vector Store.\n - documents (Optional[Document]): The documents to use for the Vector Store.\n - chroma_server_cors_allow_origins (Optional[str]): The CORS allow origins for the Chroma server.\n - chroma_server_host (Optional[str]): The host for the Chroma server.\n - chroma_server_port (Optional[int]): The port for the Chroma server.\n - chroma_server_grpc_port (Optional[int]): The gRPC port for the Chroma server.\n\n Returns:\n - Union[VectorStore, BaseRetriever]: The Vector Store or BaseRetriever object.\n \"\"\"\n\n # Chroma settings\n chroma_settings = None\n\n if chroma_server_host is not None:\n chroma_settings = chromadb.config.Settings(\n chroma_server_cors_allow_origins=chroma_server_cors_allow_origins or None,\n chroma_server_host=chroma_server_host,\n chroma_server_port=chroma_server_port or None,\n chroma_server_grpc_port=chroma_server_grpc_port or None,\n chroma_server_ssl_enabled=chroma_server_ssl_enabled,\n )\n\n # If documents, then we need to create a Chroma instance using .from_documents\n if documents is not None and embedding is not None:\n if len(documents) == 0:\n raise ValueError(\"If documents are provided, there must be at least one document.\")\n return Chroma.from_documents(\n documents=documents, # type: ignore\n persist_directory=persist_directory if persist else None,\n collection_name=collection_name,\n embedding=embedding,\n client_settings=chroma_settings,\n )\n\n return Chroma(persist_directory=persist_directory, client_settings=chroma_settings)\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": false, + "dynamic": true, + "info": "" + }, + "collection_name": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "video", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "collection_name", + "display_name": "Collection Name", + "advanced": false, + "dynamic": false, + "info": "" + }, + "persist": { + "type": "bool", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "persist", + "display_name": "Persist", + "advanced": false, + "dynamic": false, + "info": "" + }, + "persist_directory": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "persist_directory", + "display_name": "Persist Directory", + "advanced": false, + "dynamic": false, + "info": "" + }, + "_type": "CustomComponent" + }, + "description": "Implementation of Vector Store using Chroma", + "base_classes": [ + "VectorStore", + "BaseRetriever" + ], + "display_name": "Chroma", + "documentation": "https://python.langchain.com/docs/integrations/vectorstores/chroma", + "custom_fields": { + "chroma_server_cors_allow_origins": null, + "chroma_server_grpc_port": null, + "chroma_server_host": null, + "chroma_server_port": null, + "chroma_server_ssl_enabled": null, + "collection_name": null, + "documents": null, + "embedding": null, + "persist": null, + "persist_directory": null + }, + "output_types": [ + "Chroma" + ], + "field_formatters": {}, + "beta": true + }, + "id": "Chroma-OtYDg" + }, + "selected": false, + "width": 384, + "height": 625, + "positionAbsolute": { + "x": -2194.2051907050227, + "y": -1370.1637632208287 + }, + "dragging": false + }, + { + "id": "OpenAIEmbeddings-9yqtI", + "type": "genericNode", + "position": { + "x": -2653.011009324626, + "y": -1103.8414515074774 + }, + "data": { + "type": "OpenAIEmbeddings", + "node": { + "template": { + "allowed_special": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": [], + "fileTypes": [], + "password": false, + "name": "allowed_special", + "advanced": true, + "dynamic": false, + "info": "" + }, + "async_client": { + "type": "Any", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "async_client", + "advanced": true, + "dynamic": false, + "info": "" + }, + "chunk_size": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 1000, + "fileTypes": [], + "password": false, + "name": "chunk_size", + "advanced": true, + "dynamic": false, + "info": "" + }, + "client": { + "type": "Any", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "client", + "advanced": true, + "dynamic": false, + "info": "" + }, + "default_headers": { + "type": "dict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "default_headers", + "advanced": true, + "dynamic": false, + "info": "" + }, + "default_query": { + "type": "dict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "default_query", + "advanced": true, + "dynamic": false, + "info": "" + }, + "deployment": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "text-embedding-ada-002", + "fileTypes": [], + "password": false, + "name": "deployment", + "advanced": true, + "dynamic": false, + "info": "" + }, + "disallowed_special": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "all", + "fileTypes": [], + "password": false, + "name": "disallowed_special", + "advanced": true, + "dynamic": false, + "info": "" + }, + "embedding_ctx_length": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 8191, + "fileTypes": [], + "password": false, + "name": "embedding_ctx_length", + "advanced": true, + "dynamic": false, + "info": "" + }, + "headers": { + "type": "Any", + "required": false, + "placeholder": "", + "list": false, + "show": false, + "multiline": true, + "value": "{\"Authorization\": \"Bearer \"}", + "fileTypes": [], + "password": false, + "name": "headers", + "advanced": true, + "dynamic": false, + "info": "" + }, + "http_client": { + "type": "Any", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "http_client", + "advanced": true, + "dynamic": false, + "info": "" + }, + "max_retries": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 2, + "fileTypes": [], + "password": false, + "name": "max_retries", + "advanced": true, + "dynamic": false, + "info": "" + }, + "model": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "text-embedding-ada-002", + "fileTypes": [], + "password": false, + "name": "model", + "advanced": true, + "dynamic": false, + "info": "" + }, + "model_kwargs": { + "type": "dict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "model_kwargs", + "advanced": true, + "dynamic": false, + "info": "" + }, + "openai_api_base": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "password": true, + "name": "openai_api_base", + "display_name": "OpenAI API Base", + "advanced": true, + "dynamic": false, + "info": "", + "value": "" + }, + "openai_api_key": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "", + "fileTypes": [], + "password": true, + "name": "openai_api_key", + "display_name": "OpenAI API Key", + "advanced": false, + "dynamic": false, + "info": "" + }, + "openai_api_type": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "password": true, + "name": "openai_api_type", + "display_name": "OpenAI API Type", + "advanced": true, + "dynamic": false, + "info": "", + "value": "" + }, + "openai_api_version": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "password": true, + "name": "openai_api_version", + "display_name": "OpenAI API Version", + "advanced": true, + "dynamic": false, + "info": "", + "value": "" + }, + "openai_organization": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "openai_organization", + "display_name": "OpenAI Organization", + "advanced": true, + "dynamic": false, + "info": "" + }, + "openai_proxy": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "openai_proxy", + "display_name": "OpenAI Proxy", + "advanced": true, + "dynamic": false, + "info": "" + }, + "request_timeout": { + "type": "float", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "request_timeout", + "advanced": true, + "dynamic": false, + "info": "", + "rangeSpec": { + "min": -1, + "max": 1, + "step": 0.1 + } + }, + "retry_max_seconds": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 20, + "fileTypes": [], + "password": false, + "name": "retry_max_seconds", + "advanced": true, + "dynamic": false, + "info": "" + }, + "retry_min_seconds": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 4, + "fileTypes": [], + "password": false, + "name": "retry_min_seconds", + "advanced": true, + "dynamic": false, + "info": "" + }, + "show_progress_bar": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "password": false, + "name": "show_progress_bar", + "advanced": true, + "dynamic": false, + "info": "" + }, + "skip_empty": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "password": false, + "name": "skip_empty", + "advanced": true, + "dynamic": false, + "info": "" + }, + "tiktoken_enabled": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "", + "fileTypes": [], + "password": true, + "name": "tiktoken_enabled", + "advanced": false, + "dynamic": false, + "info": "" + }, + "tiktoken_model_name": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "password": true, + "name": "tiktoken_model_name", + "advanced": false, + "dynamic": false, + "info": "", + "value": "" + }, + "_type": "OpenAIEmbeddings" + }, + "description": "[*Deprecated*] OpenAI embedding models.", + "base_classes": [ + "Embeddings", + "OpenAIEmbeddings" + ], + "display_name": "OpenAIEmbeddings", + "documentation": "https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/openai", + "custom_fields": {}, + "output_types": [], + "field_formatters": {}, + "beta": false + }, + "id": "OpenAIEmbeddings-9yqtI" + }, + "selected": false, + "width": 384, + "height": 443, + "positionAbsolute": { + "x": -2653.011009324626, + "y": -1103.8414515074774 + }, + "dragging": false + }, + { + "id": "RetrievalQA-DpylI", + "type": "genericNode", + "position": { + "x": -1757.239471200792, + "y": -1258.2132589352987 + }, + "data": { + "type": "RetrievalQA", + "node": { + "template": { + "callbacks": { + "type": "langchain_core.callbacks.base.BaseCallbackHandler", + "required": false, + "placeholder": "", + "list": true, + "show": false, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "callbacks", + "advanced": false, + "dynamic": false, + "info": "" + }, + "combine_documents_chain": { + "type": "BaseCombineDocumentsChain", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "combine_documents_chain", + "advanced": false, + "dynamic": false, + "info": "" + }, + "memory": { + "type": "BaseMemory", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "memory", + "advanced": false, + "dynamic": false, + "info": "" + }, + "retriever": { + "type": "BaseRetriever", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "retriever", + "advanced": false, + "dynamic": false, + "info": "" + }, + "input_key": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "query", + "fileTypes": [], + "password": false, + "name": "input_key", + "advanced": true, + "dynamic": false, + "info": "" + }, + "metadata": { + "type": "dict", + "required": false, + "placeholder": "", + "list": false, + "show": false, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "metadata", + "advanced": false, + "dynamic": false, + "info": "" + }, + "name": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": false, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "name", + "advanced": false, + "dynamic": false, + "info": "" + }, + "output_key": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "result", + "fileTypes": [], + "password": false, + "name": "output_key", + "advanced": true, + "dynamic": false, + "info": "" + }, + "return_source_documents": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": true, + "fileTypes": [], + "password": false, + "name": "return_source_documents", + "advanced": true, + "dynamic": false, + "info": "" + }, + "tags": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": false, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "tags", + "advanced": false, + "dynamic": false, + "info": "" + }, + "verbose": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": false, + "multiline": false, + "fileTypes": [], + "password": false, + "name": "verbose", + "advanced": true, + "dynamic": false, + "info": "" + }, + "_type": "RetrievalQA" + }, + "description": "Chain for question-answering against an index.", + "base_classes": [ + "Chain", + "RetrievalQA", + "BaseRetrievalQA", + "Callable" + ], + "display_name": "RetrievalQA", + "documentation": "https://python.langchain.com/docs/modules/chains/popular/vector_db_qa", + "custom_fields": {}, + "output_types": [], + "field_formatters": {}, + "beta": false + }, + "id": "RetrievalQA-DpylI" + }, + "selected": false, + "width": 384, + "height": 339, + "positionAbsolute": { + "x": -1757.239471200792, + "y": -1258.2132589352987 + }, + "dragging": true + }, + { + "id": "CombineDocsChain-afKOq", + "type": "genericNode", + "position": { + "x": -1775.9040057312934, + "y": -1644.0423777157919 + }, + "data": { + "type": "CombineDocsChain", + "node": { + "template": { + "llm": { + "type": "BaseLanguageModel", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "llm", + "display_name": "LLM", + "advanced": false, + "dynamic": false, + "info": "" + }, + "chain_type": { + "type": "str", + "required": true, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "refine", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "stuff", + "map_reduce", + "map_rerank", + "refine" + ], + "name": "chain_type", + "advanced": false, + "dynamic": false, + "info": "" + }, + "_type": "load_qa_chain" + }, + "description": "Load question answering chain.", + "base_classes": [ + "BaseCombineDocumentsChain", + "Callable" + ], + "display_name": "CombineDocsChain", + "documentation": "", + "custom_fields": {}, + "output_types": [], + "field_formatters": {}, + "beta": false + }, + "id": "CombineDocsChain-afKOq" + }, + "selected": false, + "width": 384, + "height": 333, + "dragging": false, + "positionAbsolute": { + "x": -1775.9040057312934, + "y": -1644.0423777157919 + } + }, + { + "id": "SearchApi-kZmEj", + "type": "genericNode", + "position": { + "x": -3074.364183247263, + "y": -1782.5742787937606 + }, + "data": { + "type": "SearchApi", + "node": { + "template": { + "api_key": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": true, + "name": "api_key", + "display_name": "API Key", + "advanced": false, + "dynamic": false, + "info": "The API key to use SearchApi.", + "value": "" + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from langflow.custom import CustomComponent\nfrom langchain.schema import Document\nfrom langflow.services.database.models.base import orjson_dumps\nfrom langchain_community.utilities.searchapi import SearchApiAPIWrapper\nfrom typing import Optional\n\n\nclass SearchApi(CustomComponent):\n display_name: str = \"SearchApi\"\n description: str = \"Real-time search engines API.\"\n output_types: list[str] = [\"Document\"]\n documentation: str = \"https://www.searchapi.io/docs/google\"\n field_config = {\n \"engine\": {\n \"display_name\": \"Engine\",\n \"field_type\": \"str\",\n \"info\": \"The search engine to use.\",\n },\n \"params\": {\n \"display_name\": \"Parameters\",\n \"info\": \"The parameters to send with the request.\",\n },\n \"code\": {\"show\": False},\n \"api_key\": {\n \"display_name\": \"API Key\",\n \"field_type\": \"str\",\n \"required\": True, \n \"password\": True,\n \"info\": \"The API key to use SearchApi.\",\n },\n }\n\n def build(\n self,\n engine: str,\n api_key: str,\n params: Optional[dict] = None,\n ) -> Document:\n if params is None:\n params = {}\n\n search_api_wrapper = SearchApiAPIWrapper(engine=engine, searchapi_api_key=api_key)\n\n query = params.pop(\"query\", \"default query\") \n results = search_api_wrapper.results(query, **params)\n\n result = orjson_dumps(results, indent_2=False)\n \n document = Document(page_content=result) \n\n return document", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": false, + "dynamic": true, + "info": "" + }, + "engine": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "engine", + "display_name": "Engine", + "advanced": false, + "dynamic": false, + "info": "The search engine to use.", + "value": "youtube_transcripts" + }, + "params": { + "type": "dict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "params", + "display_name": "Parameters", + "advanced": false, + "dynamic": false, + "info": "The parameters to send with the request.", + "value": [ + { + "video_id": "krsBRQbOPQ4" + } + ] + }, + "_type": "CustomComponent" + }, + "description": "Real-time search engines API.", + "base_classes": [ + "Document" + ], + "display_name": "SearchApi", + "documentation": "https://www.searchapi.io/docs/google", + "custom_fields": { + "api_key": null, + "engine": null, + "params": null + }, + "output_types": [ + "SearchApi" + ], + "field_formatters": {}, + "beta": true + }, + "id": "SearchApi-kZmEj" + }, + "selected": false, + "width": 384, + "height": 539, + "dragging": false, + "positionAbsolute": { + "x": -3074.364183247263, + "y": -1782.5742787937606 + } + } + ], + "edges": [ + { + "source": "CharacterTextSplitter-WVMFU", + "sourceHandle": "{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œCharacterTextSplitterœ,œidœ:œCharacterTextSplitter-WVMFUœ}", + "target": "Chroma-OtYDg", + "targetHandle": "{œfieldNameœ:œdocumentsœ,œidœ:œChroma-OtYDgœ,œinputTypesœ:null,œtypeœ:œDocumentœ}", + "data": { + "targetHandle": { + "fieldName": "documents", + "id": "Chroma-OtYDg", + "inputTypes": null, + "type": "Document" + }, + "sourceHandle": { + "baseClasses": [ + "Document" + ], + "dataType": "CharacterTextSplitter", + "id": "CharacterTextSplitter-WVMFU" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "animated": false, + "id": "reactflow__edge-CharacterTextSplitter-WVMFU{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œCharacterTextSplitterœ,œidœ:œCharacterTextSplitter-WVMFUœ}-Chroma-OtYDg{œfieldNameœ:œdocumentsœ,œidœ:œChroma-OtYDgœ,œinputTypesœ:null,œtypeœ:œDocumentœ}" + }, + { + "source": "OpenAIEmbeddings-9yqtI", + "sourceHandle": "{œbaseClassesœ:[œEmbeddingsœ,œOpenAIEmbeddingsœ],œdataTypeœ:œOpenAIEmbeddingsœ,œidœ:œOpenAIEmbeddings-9yqtIœ}", + "target": "Chroma-OtYDg", + "targetHandle": "{œfieldNameœ:œembeddingœ,œidœ:œChroma-OtYDgœ,œinputTypesœ:null,œtypeœ:œEmbeddingsœ}", + "data": { + "targetHandle": { + "fieldName": "embedding", + "id": "Chroma-OtYDg", + "inputTypes": null, + "type": "Embeddings" + }, + "sourceHandle": { + "baseClasses": [ + "Embeddings", + "OpenAIEmbeddings" + ], + "dataType": "OpenAIEmbeddings", + "id": "OpenAIEmbeddings-9yqtI" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "animated": false, + "id": "reactflow__edge-OpenAIEmbeddings-9yqtI{œbaseClassesœ:[œEmbeddingsœ,œOpenAIEmbeddingsœ],œdataTypeœ:œOpenAIEmbeddingsœ,œidœ:œOpenAIEmbeddings-9yqtIœ}-Chroma-OtYDg{œfieldNameœ:œembeddingœ,œidœ:œChroma-OtYDgœ,œinputTypesœ:null,œtypeœ:œEmbeddingsœ}" + }, + { + "source": "Chroma-OtYDg", + "sourceHandle": "{œbaseClassesœ:[œVectorStoreœ,œBaseRetrieverœ],œdataTypeœ:œChromaœ,œidœ:œChroma-OtYDgœ}", + "target": "RetrievalQA-DpylI", + "targetHandle": "{œfieldNameœ:œretrieverœ,œidœ:œRetrievalQA-DpylIœ,œinputTypesœ:null,œtypeœ:œBaseRetrieverœ}", + "data": { + "targetHandle": { + "fieldName": "retriever", + "id": "RetrievalQA-DpylI", + "inputTypes": null, + "type": "BaseRetriever" + }, + "sourceHandle": { + "baseClasses": [ + "VectorStore", + "BaseRetriever" + ], + "dataType": "Chroma", + "id": "Chroma-OtYDg" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "animated": false, + "id": "reactflow__edge-Chroma-OtYDg{œbaseClassesœ:[œVectorStoreœ,œBaseRetrieverœ],œdataTypeœ:œChromaœ,œidœ:œChroma-OtYDgœ}-RetrievalQA-DpylI{œfieldNameœ:œretrieverœ,œidœ:œRetrievalQA-DpylIœ,œinputTypesœ:null,œtypeœ:œBaseRetrieverœ}" + }, + { + "source": "ChatOpenAI-4Mfuz", + "sourceHandle": "{œbaseClassesœ:[œBaseLanguageModelœ,œBaseChatModelœ,œChatOpenAIœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-4Mfuzœ}", + "target": "CombineDocsChain-afKOq", + "targetHandle": "{œfieldNameœ:œllmœ,œidœ:œCombineDocsChain-afKOqœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}", + "data": { + "targetHandle": { + "fieldName": "llm", + "id": "CombineDocsChain-afKOq", + "inputTypes": null, + "type": "BaseLanguageModel" + }, + "sourceHandle": { + "baseClasses": [ + "BaseLanguageModel", + "BaseChatModel", + "ChatOpenAI", + "BaseLLM" + ], + "dataType": "ChatOpenAI", + "id": "ChatOpenAI-4Mfuz" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "animated": false, + "id": "reactflow__edge-ChatOpenAI-4Mfuz{œbaseClassesœ:[œBaseLanguageModelœ,œBaseChatModelœ,œChatOpenAIœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-4Mfuzœ}-CombineDocsChain-afKOq{œfieldNameœ:œllmœ,œidœ:œCombineDocsChain-afKOqœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}" + }, + { + "source": "CombineDocsChain-afKOq", + "sourceHandle": "{œbaseClassesœ:[œBaseCombineDocumentsChainœ,œCallableœ],œdataTypeœ:œCombineDocsChainœ,œidœ:œCombineDocsChain-afKOqœ}", + "target": "RetrievalQA-DpylI", + "targetHandle": "{œfieldNameœ:œcombine_documents_chainœ,œidœ:œRetrievalQA-DpylIœ,œinputTypesœ:null,œtypeœ:œBaseCombineDocumentsChainœ}", + "data": { + "targetHandle": { + "fieldName": "combine_documents_chain", + "id": "RetrievalQA-DpylI", + "inputTypes": null, + "type": "BaseCombineDocumentsChain" + }, + "sourceHandle": { + "baseClasses": [ + "BaseCombineDocumentsChain", + "Callable" + ], + "dataType": "CombineDocsChain", + "id": "CombineDocsChain-afKOq" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "animated": false, + "id": "reactflow__edge-CombineDocsChain-afKOq{œbaseClassesœ:[œBaseCombineDocumentsChainœ,œCallableœ],œdataTypeœ:œCombineDocsChainœ,œidœ:œCombineDocsChain-afKOqœ}-RetrievalQA-DpylI{œfieldNameœ:œcombine_documents_chainœ,œidœ:œRetrievalQA-DpylIœ,œinputTypesœ:null,œtypeœ:œBaseCombineDocumentsChainœ}" + }, + { + "source": "SearchApi-kZmEj", + "sourceHandle": "{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œSearchApiœ,œidœ:œSearchApi-kZmEjœ}", + "target": "CharacterTextSplitter-WVMFU", + "targetHandle": "{œfieldNameœ:œdocumentsœ,œidœ:œCharacterTextSplitter-WVMFUœ,œinputTypesœ:null,œtypeœ:œDocumentœ}", + "data": { + "targetHandle": { + "fieldName": "documents", + "id": "CharacterTextSplitter-WVMFU", + "inputTypes": null, + "type": "Document" + }, + "sourceHandle": { + "baseClasses": [ + "Document" + ], + "dataType": "SearchApi", + "id": "SearchApi-kZmEj" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "animated": false, + "id": "reactflow__edge-SearchApi-kZmEj{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œSearchApiœ,œidœ:œSearchApi-kZmEjœ}-CharacterTextSplitter-WVMFU{œfieldNameœ:œdocumentsœ,œidœ:œCharacterTextSplitter-WVMFUœ,œinputTypesœ:null,œtypeœ:œDocumentœ}" + } + ], + "viewport": { + "x": 2046.3642433866817, + "y": 1270.2852546488134, + "zoom": 0.6177254407441625 + } + }, + "description": "Real-time Google Search engine q&a.", + "name": "SearchApi Tool", + "last_tested_version": "0.6.5a9", + "is_component": false +} \ No newline at end of file diff --git a/lcserve.Dockerfile b/lcserve.Dockerfile deleted file mode 100644 index 883a2c040..000000000 --- a/lcserve.Dockerfile +++ /dev/null @@ -1,16 +0,0 @@ -# This file is used by `lc-serve` to build the image. -# Don't change the name of this file. - -FROM jinawolf/serving-gateway:${version} - -RUN apt-get update \ - && apt-get install --no-install-recommends -y build-essential libpq-dev - -COPY . /appdir/ - -RUN pip install poetry==1.4.0 && cd /appdir && pip install . && \ - pip uninstall -y poetry && \ - apt-get remove --auto-remove -y build-essential libpq-dev && \ - apt-get autoremove && apt-get clean && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/* - -ENTRYPOINT [ "jina", "gateway", "--uses", "config.yml" ] \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index f6dd53297..dc6cb7649 100644 --- a/poetry.lock +++ b/poetry.lock @@ -239,6 +239,43 @@ typing-extensions = {version = ">=4", markers = "python_version < \"3.11\""} [package.extras] tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] +[[package]] +name = "assemblyai" +version = "0.23.1" +description = "AssemblyAI Python SDK" +optional = false +python-versions = ">=3.8" +files = [ + {file = "assemblyai-0.23.1-py3-none-any.whl", hash = "sha256:2887c7983fa911717cbe37a38d38fcdc8188e62687385b8b6f979546c58354f4"}, + {file = "assemblyai-0.23.1.tar.gz", hash = "sha256:4a3d4d8c4f6c956c6243f0873147ba29da4c6cf5edd6a1b52e6bdaa209526998"}, +] + +[package.dependencies] +httpx = ">=0.19.0" +pydantic = ">=1.7.0,<1.10.7 || >1.10.7" +typing-extensions = ">=3.7" +websockets = ">=11.0" + +[package.extras] +extras = ["pyaudio (>=0.2.13)"] + +[[package]] +name = "astrapy" +version = "0.7.7" +description = "AstraPy is a Pythonic SDK for DataStax Astra" +optional = false +python-versions = ">=3.8.0,<4.0.0" +files = [ + {file = "astrapy-0.7.7-py3-none-any.whl", hash = "sha256:e5def4e3c5ceb06dfc996471250dc0c972b729c06336ea4aac006dadfc071a9a"}, + {file = "astrapy-0.7.7.tar.gz", hash = "sha256:4bf81096a0c26cce18a14a34bb5f699649fd7d90b4ec6050f3d7c0274722d769"}, +] + +[package.dependencies] +cassio = ">=0.1.4,<0.2.0" +deprecation = ">=2.1.0,<2.2.0" +httpx = {version = ">=0.25.2,<1", extras = ["http2"]} +toml = ">=0.10.2,<0.11.0" + [[package]] name = "asttokens" version = "2.4.1" @@ -383,6 +420,17 @@ charset-normalizer = ["charset-normalizer"] html5lib = ["html5lib"] lxml = ["lxml"] +[[package]] +name = "bidict" +version = "0.23.1" +description = "The bidirectional mapping library for Python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "bidict-0.23.1-py3-none-any.whl", hash = "sha256:5dae8d4d79b552a71cbabc7deb25dfe8ce710b17ff41711e13010ead2abfc3e5"}, + {file = "bidict-0.23.1.tar.gz", hash = "sha256:03069d763bc387bbd20e7d49914e75fc4132a41937fa3405417e1a5a2d006d71"}, +] + [[package]] name = "billiard" version = "4.2.0" @@ -407,17 +455,17 @@ files = [ [[package]] name = "boto3" -version = "1.34.73" +version = "1.34.77" description = "The AWS SDK for Python" optional = false python-versions = ">=3.8" files = [ - {file = "boto3-1.34.73-py3-none-any.whl", hash = "sha256:4d68e7c7c1339e251c661fd6e2a34e31d281177106326712417fed839907fa84"}, - {file = "boto3-1.34.73.tar.gz", hash = "sha256:f45503333286c03fb692a3ce497b6fdb4e88c51c98a3b8ff05071d7f56571448"}, + {file = "boto3-1.34.77-py3-none-any.whl", hash = "sha256:7abd327980258ec2ae980d2ff7fc32ede7448146b14d34c56bf0be074e2a149b"}, + {file = "boto3-1.34.77.tar.gz", hash = "sha256:8ebed4fa5a3b84dd4037f28226985af00e00fb860d739fc8b1ed6381caa4b330"}, ] [package.dependencies] -botocore = ">=1.34.73,<1.35.0" +botocore = ">=1.34.77,<1.35.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.10.0,<0.11.0" @@ -426,22 +474,19 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.34.73" +version = "1.34.77" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">=3.8" files = [ - {file = "botocore-1.34.73-py3-none-any.whl", hash = "sha256:88d660b711cc5b5b049e15d547cb09526f86e48c15b78dacad78522109502b91"}, - {file = "botocore-1.34.73.tar.gz", hash = "sha256:8df020b6682b9f1e9ee7b0554d5d0c14b7b23e3de070c85bcdf07fb20bfe4e2b"}, + {file = "botocore-1.34.77-py3-none-any.whl", hash = "sha256:6d6a402032ca0b89525212356a865397f8f2839683dd53d41b8cee1aa84b2b4b"}, + {file = "botocore-1.34.77.tar.gz", hash = "sha256:6dab60261cdbfb7d0059488ea39408d5522fad419c004ba5db3484e6df854ea8"}, ] [package.dependencies] jmespath = ">=0.7.1,<2.0.0" python-dateutil = ">=2.1,<3.0.0" -urllib3 = [ - {version = ">=1.25.4,<1.27", markers = "python_version < \"3.10\""}, - {version = ">=1.25.4,<2.2.0 || >2.2.0,<3", markers = "python_version >= \"3.10\""}, -] +urllib3 = {version = ">=1.25.4,<2.2.0 || >2.2.0,<3", markers = "python_version >= \"3.10\""} [package.extras] crt = ["awscrt (==0.19.19)"] @@ -574,6 +619,69 @@ files = [ {file = "cachetools-5.3.3.tar.gz", hash = "sha256:ba29e2dfa0b8b556606f097407ed1aa62080ee108ab0dc5ec9d6a723a007d105"}, ] +[[package]] +name = "cassandra-driver" +version = "3.29.1" +description = "DataStax Driver for Apache Cassandra" +optional = false +python-versions = "*" +files = [ + {file = "cassandra-driver-3.29.1.tar.gz", hash = "sha256:38e9c2a2f2a9664bb03f1f852d5fccaeff2163942b5db35dffcf8bf32a51cfe5"}, + {file = "cassandra_driver-3.29.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a8f175c7616a63ca48cb8bd4acc443e2a3d889964d5157cead761f23cc8db7bd"}, + {file = "cassandra_driver-3.29.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7d66398952b9cd21c40edff56e22b6d3bce765edc94b207ddb5896e7bc9aa088"}, + {file = "cassandra_driver-3.29.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bbc6f575ef109ce5d4abfa2033bf36c394032abd83e32ab671159ce68e7e17b"}, + {file = "cassandra_driver-3.29.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78f241af75696adb3e470209e2fbb498804c99e2b197d24d74774eee6784f283"}, + {file = "cassandra_driver-3.29.1-cp310-cp310-win32.whl", hash = "sha256:54d9e651a742d6ca3d874ef8d06a40fa032d2dba97142da2d36f60c5675e39f8"}, + {file = "cassandra_driver-3.29.1-cp310-cp310-win_amd64.whl", hash = "sha256:630dc5423cd40eba0ee9db31065e2238098ff1a25a6b1bd36360f85738f26e4b"}, + {file = "cassandra_driver-3.29.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0b841d38c96bb878d31df393954863652d6d3a85f47bcc00fd1d70a5ea73023f"}, + {file = "cassandra_driver-3.29.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:19cc7375f673e215bd4cbbefae2de9f07830be7dabef55284a2d2ff8d8691efe"}, + {file = "cassandra_driver-3.29.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b74b355be3dcafe652fffda8f14f385ccc1a8dae9df28e6080cc660da39b45f"}, + {file = "cassandra_driver-3.29.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e6dac7eddd3f4581859f180383574068a3f113907811b4dad755a8ace4c3fbd"}, + {file = "cassandra_driver-3.29.1-cp311-cp311-win32.whl", hash = "sha256:293a79dba417112b56320ed0013d71fd7520f5fc4a5fd2ac8000c762c6dd5b07"}, + {file = "cassandra_driver-3.29.1-cp311-cp311-win_amd64.whl", hash = "sha256:7c2374fdf1099047a6c9c8329c79d71ad11e61d9cca7de92a0f49655da4bdd8a"}, + {file = "cassandra_driver-3.29.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4431a0c836f33a33c733c84997fbdb6398be005c4d18a8c8525c469fdc29393c"}, + {file = "cassandra_driver-3.29.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d23b08381b171a9e42ace483a82457edcddada9e8367e31677b97538cde2dc34"}, + {file = "cassandra_driver-3.29.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4beb29a0139e63a10a5b9a3c7b72c30a4e6e20c9f0574f9d22c0d4144fe3d348"}, + {file = "cassandra_driver-3.29.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b206423cc454a78f16b411e7cb641dddc26168ac2e18f2c13665f5f3c89868c"}, + {file = "cassandra_driver-3.29.1-cp312-cp312-win32.whl", hash = "sha256:ac898cca7303a3a2a3070513eee12ef0f1be1a0796935c5b8aa13dae8c0a7f7e"}, + {file = "cassandra_driver-3.29.1-cp312-cp312-win_amd64.whl", hash = "sha256:4ad0c9fb2229048ad6ff8c6ddbf1fdc78b111f2b061c66237c2257fcc4a31b14"}, + {file = "cassandra_driver-3.29.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4282c5deac462e4bb0f6fd0553a33d514dbd5ee99d0812594210080330ddd1a2"}, + {file = "cassandra_driver-3.29.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:41ca7eea069754002418d3bdfbd3dfd150ea12cb9db474ab1a01fa4679a05bcb"}, + {file = "cassandra_driver-3.29.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6639ccb268c4dc754bc45e03551711780d0e02cb298ab26cde1f42b7bcc74f8"}, + {file = "cassandra_driver-3.29.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a9d7d3b1be24a7f113b5404186ccccc977520401303a8fe78ba34134cad2482"}, + {file = "cassandra_driver-3.29.1-cp38-cp38-win32.whl", hash = "sha256:81c8fd556c6e1bb93577e69c1f10a3fadf7ddb93958d226ccbb72389396e9a92"}, + {file = "cassandra_driver-3.29.1-cp38-cp38-win_amd64.whl", hash = "sha256:cfe70ed0f27af949de2767ea9cef4092584e8748759374a55bf23c30746c7b23"}, + {file = "cassandra_driver-3.29.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a2c03c1d834ac1a0ae39f9af297a8cd38829003ce910b08b324fb3abe488ce2b"}, + {file = "cassandra_driver-3.29.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9a3e1e2b01f3b7a5cf75c97401bce830071d99c42464352087d7475e0161af93"}, + {file = "cassandra_driver-3.29.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90c42006665a4e490b0766b70f3d637f36a30accbef2da35d6d4081c0e0bafc3"}, + {file = "cassandra_driver-3.29.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c1aca41f45772f9759e8246030907d92bc35fbbdc91525a3cb9b49939b80ad7"}, + {file = "cassandra_driver-3.29.1-cp39-cp39-win32.whl", hash = "sha256:ce4a66245d4a0c8b07fdcb6398698c2c42eb71245fb49cff39435bb702ff7be6"}, + {file = "cassandra_driver-3.29.1-cp39-cp39-win_amd64.whl", hash = "sha256:4cae69ceb1b1d9383e988a1b790115253eacf7867ceb15ed2adb736e3ce981be"}, +] + +[package.dependencies] +geomet = ">=0.1,<0.3" + +[package.extras] +cle = ["cryptography (>=35.0)"] +graph = ["gremlinpython (==3.4.6)"] + +[[package]] +name = "cassio" +version = "0.1.5" +description = "A framework-agnostic Python library to seamlessly integrate Apache Cassandra(R) with ML/LLM/genAI workloads." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cassio-0.1.5-py3-none-any.whl", hash = "sha256:cf1d11f255c040bc0aede4963ca020840133377aa54f7f15d2f819d6553d52ce"}, + {file = "cassio-0.1.5.tar.gz", hash = "sha256:88c50c34d46a1bfffca1e0b600318a6efef45e6c18a56ddabe208cbede8dcc27"}, +] + +[package.dependencies] +cassandra-driver = ">=3.28.0" +numpy = ">=1.0" +requests = ">=2" + [[package]] name = "celery" version = "5.3.6" @@ -904,6 +1012,58 @@ typer = ">=0.9.0" typing-extensions = ">=4.5.0" uvicorn = {version = ">=0.18.3", extras = ["standard"]} +[[package]] +name = "clevercsv" +version = "0.8.2" +description = "A Python package for handling messy CSV files" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "clevercsv-0.8.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:67ab7dc8490ed391add1f26db262d09067796be7e76948bde0a9c6f1dddb7508"}, + {file = "clevercsv-0.8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bcf2402578f2f1c655ed21370e668f44098d9734129804f0fba1779dab7f2c47"}, + {file = "clevercsv-0.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7a65d9722303e3db439124418ee312fcab6a75897175842690eae94bdf51b72b"}, + {file = "clevercsv-0.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:755369a540d40295ea2898343c44dc8a4886e7c9e2fd5f5a780d2995a5516e1d"}, + {file = "clevercsv-0.8.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0fe155a8e39160692869f3b9b8a8bca9ba215cc350b9c804437edaa90ede4d16"}, + {file = "clevercsv-0.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:1e38761cd3f1977f8298a1a4cac3981c953aaf2226c0f1cc3f1ccf2172100ba4"}, + {file = "clevercsv-0.8.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3502c7af7a4b7a50b923a5972a9357ae2a37aa857dd96c7489c201d104e5d0b9"}, + {file = "clevercsv-0.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1ed99467ba2d47a2e1e81e990f74c7542d2cd0da120d922c5c992c17ac3ba026"}, + {file = "clevercsv-0.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1be9c6f2e73117a77d0b0491c07738fd177ba5e2bf996ac9a221417b223162d7"}, + {file = "clevercsv-0.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b942ee944264e5c4dbf276de579a502d11d3571daec97af5ebe54e6cadf2b77"}, + {file = "clevercsv-0.8.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48a8a81c1f324e2a5589e0de9b6bd965f1dd19b54b0e9e7f97cab5edf888d486"}, + {file = "clevercsv-0.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:e474cc07167010c4cb6b1a65588309bc855537cae01ab63cdf61a511e69b4722"}, + {file = "clevercsv-0.8.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:2bfa4fe39b3b51bcf07d2f8cf033d7ac53bac5292ef7b9a88bae7c9e6689f366"}, + {file = "clevercsv-0.8.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3e2528f89ee483878c3c8030a2d2da4eef2a8a7ac3036adad0767c1025a99df7"}, + {file = "clevercsv-0.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8832093b49defb2f224a98158265fe0bbee9ed6a70a8105cf8d7c4b949a8e95b"}, + {file = "clevercsv-0.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b68a7fbddef0e1746d3ec5e4d114e1900eb1a86d71250b0b208622daa5d2c7c"}, + {file = "clevercsv-0.8.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9cb807e7bea5a18cca4d51d1abc58e2f975759b7a0bcb78e1677c56ac7827e9a"}, + {file = "clevercsv-0.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:74133c7225037052247584cf2df99b052fce4659a423c30f0ea84532e0a30924"}, + {file = "clevercsv-0.8.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:cb9241fe5d6a2e3330c52c04fd18b7c279bbdeb7d0ecef8c4267f14336021d78"}, + {file = "clevercsv-0.8.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c1129f1328c0940b13b9b08a72f04c8b0a85a6a021994999f34cd3abe19ca206"}, + {file = "clevercsv-0.8.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7f75f46a4d6b75380f2c0b8190fed6fbb7c1400246ce52a71c68f59baf1ec362"}, + {file = "clevercsv-0.8.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bf6058a4930fde2ff00ab82e0ec961247b6e2dd503f67a16f51382b8654cbc2"}, + {file = "clevercsv-0.8.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d9f29bb3fb4c0d35416cc0baf9221d1476f3bee4c367c3618f81ac0f45b71af"}, + {file = "clevercsv-0.8.2-cp38-cp38-win_amd64.whl", hash = "sha256:17455184e44ce60bb4d21eddd477c7f505b735faff82012d5c857dd31a22e0aa"}, + {file = "clevercsv-0.8.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:dcf560e643c1fb37d3523a11b0dfbce0bda63ac831d8c71fa2973b262bc1603f"}, + {file = "clevercsv-0.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:41513c6ff653baded084a96318e4bdc078a9cce4ff5f9b4656d49aa2421e2e74"}, + {file = "clevercsv-0.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:71b88f1181fba6e5f6a46292d27f068bdc50200b5660b82a770adfcfb5ae076e"}, + {file = "clevercsv-0.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff57768d060ac6509dd33a65fa1d2a0fbb70cd62d0075d80a96367a2a9150765"}, + {file = "clevercsv-0.8.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f9514a169270fd095827698d1d5d80a8a3785f600441a11fb3a469ad5209eeb"}, + {file = "clevercsv-0.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:850f9c112377a73b0bac093df45b846513d34509ba3774fe04061ba4a4afca92"}, + {file = "clevercsv-0.8.2.tar.gz", hash = "sha256:fac1b9671bd77e7835f5fe22898df88b1a11cfd924ff71fc2d0f066065dea940"}, +] + +[package.dependencies] +chardet = ">=3.0" +packaging = ">=23.0" +regex = ">=2018.11" + +[package.extras] +dev = ["faust-cchardet (>=2.1.18)", "furo", "green", "m2r2", "pandas (>=1.0.0)", "pytest (>=2.6)", "sphinx", "tabview (>=1.4)", "termcolor", "wilderness (>=0.1.5)"] +docs = ["furo", "m2r2", "sphinx"] +full = ["faust-cchardet (>=2.1.18)", "pandas (>=1.0.0)", "tabview (>=1.4)", "wilderness (>=0.1.5)"] +precommit = ["wilderness (>=0.1.5)"] +tests = ["faust-cchardet (>=2.1.18)", "pandas (>=1.0.0)", "tabview (>=1.4)", "wilderness (>=0.1.5)"] + [[package]] name = "click" version = "8.1.7" @@ -969,22 +1129,23 @@ testing = ["pytest (>=7.2.1)", "pytest-cov (>=4.0.0)", "tox (>=4.4.3)"] [[package]] name = "cohere" -version = "4.57" -description = "Python SDK for the Cohere API" +version = "5.2.1" +description = "" optional = false -python-versions = ">=3.8,<4.0" +python-versions = "<4.0,>=3.8" files = [ - {file = "cohere-4.57-py3-none-any.whl", hash = "sha256:479bdea81ae119e53f671f1ae808fcff9df88211780525d7ef2f7b99dfb32e59"}, - {file = "cohere-4.57.tar.gz", hash = "sha256:71ace0204a92d1a2a8d4b949b88b353b4f22fc645486851924284cc5a0eb700d"}, + {file = "cohere-5.2.1-py3-none-any.whl", hash = "sha256:c694f9d2cdafd87443f54ea5238b51a0fb807f119673e00b814c2a2993368e38"}, + {file = "cohere-5.2.1.tar.gz", hash = "sha256:7cd5522bb162c05c67b2db0b7aba2a103622e17ece9e885f5ef2de66bb67a324"}, ] [package.dependencies] -aiohttp = ">=3.0,<4.0" -backoff = ">=2.0,<3.0" -fastavro = ">=1.8,<2.0" -importlib_metadata = ">=6.0,<7.0" -requests = ">=2.25.0,<3.0.0" -urllib3 = ">=1.26,<3" +fastavro = ">=1.9.4,<2.0.0" +httpx = ">=0.21.2" +pydantic = ">=1.9.2" +requests = ">=2.31.0,<3.0.0" +tokenizers = ">=0.15.2,<0.16.0" +types-requests = ">=2.31.0.20240311,<3.0.0.0" +typing_extensions = ">=4.0.0" [[package]] name = "colorama" @@ -1025,6 +1186,23 @@ humanfriendly = ">=9.1" [package.extras] cron = ["capturer (>=2.4)"] +[[package]] +name = "colorlog" +version = "6.8.2" +description = "Add colours to the output of Python's logging module." +optional = false +python-versions = ">=3.6" +files = [ + {file = "colorlog-6.8.2-py3-none-any.whl", hash = "sha256:4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33"}, + {file = "colorlog-6.8.2.tar.gz", hash = "sha256:3e3e079a41feb5a1b64f978b5ea4f46040a94f11f0e8bbb8261e3dbbeca64d44"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} + +[package.extras] +development = ["black", "flake8", "mypy", "pytest", "types-colorama"] + [[package]] name = "comm" version = "0.2.2" @@ -1134,6 +1312,33 @@ tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.1 [package.extras] toml = ["tomli"] +[[package]] +name = "crewai" +version = "0.22.5" +description = "Cutting-edge framework for orchestrating role-playing, autonomous AI agents. By fostering collaborative intelligence, CrewAI empowers agents to work together seamlessly, tackling complex tasks." +optional = false +python-versions = ">=3.10,<=3.13" +files = [ + {file = "crewai-0.22.5-py3-none-any.whl", hash = "sha256:9f254d8b2ebd7fae9a43d0ebab116a3f536c6620ca3bc955cb796fc8bb9beb7d"}, + {file = "crewai-0.22.5.tar.gz", hash = "sha256:03c76a04f46a432a1c3d9e5e0c8e039f983b25019194b0ab2ec594762ac380cf"}, +] + +[package.dependencies] +click = ">=8.1.7,<9.0.0" +instructor = ">=0.5.2,<0.6.0" +langchain = ">=0.1.10,<0.2.0" +langchain-openai = ">=0.0.5,<0.0.6" +openai = ">=1.13.3,<2.0.0" +opentelemetry-api = ">=1.22.0,<2.0.0" +opentelemetry-exporter-otlp-proto-http = ">=1.22.0,<2.0.0" +opentelemetry-sdk = ">=1.22.0,<2.0.0" +pydantic = ">=2.4.2,<3.0.0" +python-dotenv = "1.0.0" +regex = ">=2023.12.25,<2024.0.0" + +[package.extras] +tools = ["crewai-tools (>=0.0.15,<0.0.16)"] + [[package]] name = "cryptography" version = "42.0.5" @@ -1223,6 +1428,49 @@ files = [ marshmallow = ">=3.18.0,<4.0.0" typing-inspect = ">=0.4.0,<1" +[[package]] +name = "datasets" +version = "2.14.7" +description = "HuggingFace community-driven open-source library of datasets" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "datasets-2.14.7-py3-none-any.whl", hash = "sha256:1a64041a7da4f4130f736fc371c1f528b8ddd208cebe156400f65719bdbba79d"}, + {file = "datasets-2.14.7.tar.gz", hash = "sha256:394cf9b4ec0694b25945977b16ad5d18d5c15fb0e94141713eb8ead7452caf9e"}, +] + +[package.dependencies] +aiohttp = "*" +dill = ">=0.3.0,<0.3.8" +fsspec = {version = ">=2023.1.0,<=2023.10.0", extras = ["http"]} +huggingface-hub = ">=0.14.0,<1.0.0" +multiprocess = "*" +numpy = ">=1.17" +packaging = "*" +pandas = "*" +pyarrow = ">=8.0.0" +pyarrow-hotfix = "*" +pyyaml = ">=5.1" +requests = ">=2.19.0" +tqdm = ">=4.62.1" +xxhash = "*" + +[package.extras] +apache-beam = ["apache-beam (>=2.26.0,<2.44.0)"] +audio = ["librosa", "soundfile (>=0.12.1)"] +benchmarks = ["tensorflow (==2.12.0)", "torch (==2.0.1)", "transformers (==4.30.1)"] +dev = ["Pillow (>=6.2.1)", "absl-py", "apache-beam (>=2.26.0,<2.44.0)", "black (>=23.1,<24.0)", "elasticsearch (<8.0.0)", "faiss-cpu (>=1.6.4)", "joblib (<1.3.0)", "joblibspark", "librosa", "lz4", "py7zr", "pyspark (>=3.4)", "pytest", "pytest-datadir", "pytest-xdist", "pyyaml (>=5.3.1)", "rarfile (>=4.0)", "ruff (>=0.0.241)", "s3fs", "s3fs (>=2021.11.1)", "soundfile (>=0.12.1)", "sqlalchemy (<2.0.0)", "tensorflow (>=2.2.0,!=2.6.0,!=2.6.1)", "tensorflow (>=2.3,!=2.6.0,!=2.6.1)", "tensorflow-macos", "tiktoken", "torch", "transformers", "zstandard"] +docs = ["s3fs", "tensorflow (>=2.2.0,!=2.6.0,!=2.6.1)", "tensorflow-macos", "torch", "transformers"] +jax = ["jax (>=0.2.8,!=0.3.2,<=0.3.25)", "jaxlib (>=0.1.65,<=0.3.25)"] +metrics-tests = ["Werkzeug (>=1.0.1)", "accelerate", "bert-score (>=0.3.6)", "jiwer", "langdetect", "mauve-text", "nltk", "requests-file (>=1.5.1)", "rouge-score", "sacrebleu", "sacremoses", "scikit-learn", "scipy", "sentencepiece", "seqeval", "six (>=1.15.0,<1.16.0)", "spacy (>=3.0.0)", "texttable (>=1.6.3)", "tldextract", "tldextract (>=3.1.0)", "toml (>=0.10.1)", "typer (<0.5.0)"] +quality = ["black (>=23.1,<24.0)", "pyyaml (>=5.3.1)", "ruff (>=0.0.241)"] +s3 = ["s3fs"] +tensorflow = ["tensorflow (>=2.2.0,!=2.6.0,!=2.6.1)", "tensorflow-macos"] +tensorflow-gpu = ["tensorflow-gpu (>=2.2.0,!=2.6.0,!=2.6.1)"] +tests = ["Pillow (>=6.2.1)", "absl-py", "apache-beam (>=2.26.0,<2.44.0)", "elasticsearch (<8.0.0)", "faiss-cpu (>=1.6.4)", "joblib (<1.3.0)", "joblibspark", "librosa", "lz4", "py7zr", "pyspark (>=3.4)", "pytest", "pytest-datadir", "pytest-xdist", "rarfile (>=4.0)", "s3fs (>=2021.11.1)", "soundfile (>=0.12.1)", "sqlalchemy (<2.0.0)", "tensorflow (>=2.3,!=2.6.0,!=2.6.1)", "tensorflow-macos", "tiktoken", "torch", "transformers", "zstandard"] +torch = ["torch"] +vision = ["Pillow (>=6.2.1)"] + [[package]] name = "debugpy" version = "1.8.1" @@ -1327,18 +1575,17 @@ packaging = "*" [[package]] name = "dill" -version = "0.3.8" +version = "0.3.7" description = "serialize all of Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.7" files = [ - {file = "dill-0.3.8-py3-none-any.whl", hash = "sha256:c36ca9ffb54365bdd2f8eb3eff7d2a21237f8452b57ace88b1ac615b7e815bd7"}, - {file = "dill-0.3.8.tar.gz", hash = "sha256:3ebe3c479ad625c4553aca177444d89b486b1d84982eeacded644afc0cf797ca"}, + {file = "dill-0.3.7-py3-none-any.whl", hash = "sha256:76b122c08ef4ce2eedcd4d1abd8e641114bfc6c2867f49f3c41facf65bf19f5e"}, + {file = "dill-0.3.7.tar.gz", hash = "sha256:cc1c8b182eb3013e24bd475ff2e9295af86c1a38eb1aff128dac8962a9ce3c03"}, ] [package.extras] graph = ["objgraph (>=1.7.2)"] -profile = ["gprof2dot (>=2022.7.29)"] [[package]] name = "dirtyjson" @@ -1425,6 +1672,89 @@ files = [ {file = "docstring_parser-0.15.tar.gz", hash = "sha256:48ddc093e8b1865899956fcc03b03e66bb7240c310fac5af81814580c55bf682"}, ] +[[package]] +name = "dspy-ai" +version = "2.4.0" +description = "DSPy" +optional = false +python-versions = ">=3.9" +files = [ + {file = "dspy-ai-2.4.0.tar.gz", hash = "sha256:d646ec015270b70bd51916346c01680923ccfa386c9e5474caac6d4366148678"}, + {file = "dspy_ai-2.4.0-py3-none-any.whl", hash = "sha256:edea508dc315702f61ae39568eaf2d8789ba4f8682102e730e016801b9102703"}, +] + +[package.dependencies] +backoff = ">=2.2.1,<2.3.0" +datasets = ">=2.14.6,<2.15.0" +joblib = ">=1.3.2,<1.4.0" +openai = ">=0.28.1,<2.0.0" +optuna = "*" +pandas = "*" +pydantic = "2.5.0" +regex = "*" +requests = "*" +tqdm = "*" +ujson = "*" + +[package.extras] +chromadb = ["chromadb (>=0.4.14,<0.5.0)"] +dev = ["pytest (>=6.2.5)"] +docs = ["autodoc-pydantic", "docutils (<0.17)", "furo (>=2023.3.27)", "m2r2", "myst-nb", "myst-parser", "sphinx (>=4.3.0)", "sphinx-autobuild", "sphinx-automodapi (==0.16.0)", "sphinx-reredirects (>=0.1.2)", "sphinx-rtd-theme"] +faiss-cpu = ["faiss-cpu", "sentence-transformers"] +marqo = ["marqo", "marqo (>=3.1.0,<3.2.0)"] +mongodb = ["pymongo (>=3.12.0,<3.13.0)"] +pinecone = ["pinecone-client (>=2.2.4,<2.3.0)"] +qdrant = ["fastembed", "fastembed (>=0.1.0,<0.2.0)", "qdrant-client", "qdrant-client (>=1.6.2,<1.7.0)"] +weaviate = ["weaviate-client (>=3.26.1,<3.27.0)"] + +[[package]] +name = "duckdb" +version = "0.9.2" +description = "DuckDB embedded database" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "duckdb-0.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:aadcea5160c586704c03a8a796c06a8afffbefefb1986601104a60cb0bfdb5ab"}, + {file = "duckdb-0.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:08215f17147ed83cbec972175d9882387366de2ed36c21cbe4add04b39a5bcb4"}, + {file = "duckdb-0.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ee6c2a8aba6850abef5e1be9dbc04b8e72a5b2c2b67f77892317a21fae868fe7"}, + {file = "duckdb-0.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ff49f3da9399900fd58b5acd0bb8bfad22c5147584ad2427a78d937e11ec9d0"}, + {file = "duckdb-0.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd5ac5baf8597efd2bfa75f984654afcabcd698342d59b0e265a0bc6f267b3f0"}, + {file = "duckdb-0.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:81c6df905589a1023a27e9712edb5b724566587ef280a0c66a7ec07c8083623b"}, + {file = "duckdb-0.9.2-cp310-cp310-win32.whl", hash = "sha256:a298cd1d821c81d0dec8a60878c4b38c1adea04a9675fb6306c8f9083bbf314d"}, + {file = "duckdb-0.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:492a69cd60b6cb4f671b51893884cdc5efc4c3b2eb76057a007d2a2295427173"}, + {file = "duckdb-0.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:061a9ea809811d6e3025c5de31bc40e0302cfb08c08feefa574a6491e882e7e8"}, + {file = "duckdb-0.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a43f93be768af39f604b7b9b48891f9177c9282a408051209101ff80f7450d8f"}, + {file = "duckdb-0.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ac29c8c8f56fff5a681f7bf61711ccb9325c5329e64f23cb7ff31781d7b50773"}, + {file = "duckdb-0.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b14d98d26bab139114f62ade81350a5342f60a168d94b27ed2c706838f949eda"}, + {file = "duckdb-0.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:796a995299878913e765b28cc2b14c8e44fae2f54ab41a9ee668c18449f5f833"}, + {file = "duckdb-0.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6cb64ccfb72c11ec9c41b3cb6181b6fd33deccceda530e94e1c362af5f810ba1"}, + {file = "duckdb-0.9.2-cp311-cp311-win32.whl", hash = "sha256:930740cb7b2cd9e79946e1d3a8f66e15dc5849d4eaeff75c8788d0983b9256a5"}, + {file = "duckdb-0.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:c28f13c45006fd525001b2011cdf91fa216530e9751779651e66edc0e446be50"}, + {file = "duckdb-0.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fbce7bbcb4ba7d99fcec84cec08db40bc0dd9342c6c11930ce708817741faeeb"}, + {file = "duckdb-0.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15a82109a9e69b1891f0999749f9e3265f550032470f51432f944a37cfdc908b"}, + {file = "duckdb-0.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9490fb9a35eb74af40db5569d90df8a04a6f09ed9a8c9caa024998c40e2506aa"}, + {file = "duckdb-0.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:696d5c6dee86c1a491ea15b74aafe34ad2b62dcd46ad7e03b1d00111ca1a8c68"}, + {file = "duckdb-0.9.2-cp37-cp37m-win32.whl", hash = "sha256:4f0935300bdf8b7631ddfc838f36a858c1323696d8c8a2cecbd416bddf6b0631"}, + {file = "duckdb-0.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:0aab900f7510e4d2613263865570203ddfa2631858c7eb8cbed091af6ceb597f"}, + {file = "duckdb-0.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:7d8130ed6a0c9421b135d0743705ea95b9a745852977717504e45722c112bf7a"}, + {file = "duckdb-0.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:974e5de0294f88a1a837378f1f83330395801e9246f4e88ed3bfc8ada65dcbee"}, + {file = "duckdb-0.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4fbc297b602ef17e579bb3190c94d19c5002422b55814421a0fc11299c0c1100"}, + {file = "duckdb-0.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1dd58a0d84a424924a35b3772419f8cd78a01c626be3147e4934d7a035a8ad68"}, + {file = "duckdb-0.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11a1194a582c80dfb57565daa06141727e415ff5d17e022dc5f31888a5423d33"}, + {file = "duckdb-0.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:be45d08541002a9338e568dca67ab4f20c0277f8f58a73dfc1435c5b4297c996"}, + {file = "duckdb-0.9.2-cp38-cp38-win32.whl", hash = "sha256:dd6f88aeb7fc0bfecaca633629ff5c986ac966fe3b7dcec0b2c48632fd550ba2"}, + {file = "duckdb-0.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:28100c4a6a04e69aa0f4a6670a6d3d67a65f0337246a0c1a429f3f28f3c40b9a"}, + {file = "duckdb-0.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7ae5bf0b6ad4278e46e933e51473b86b4b932dbc54ff097610e5b482dd125552"}, + {file = "duckdb-0.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e5d0bb845a80aa48ed1fd1d2d285dd352e96dc97f8efced2a7429437ccd1fe1f"}, + {file = "duckdb-0.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ce262d74a52500d10888110dfd6715989926ec936918c232dcbaddb78fc55b4"}, + {file = "duckdb-0.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6935240da090a7f7d2666f6d0a5e45ff85715244171ca4e6576060a7f4a1200e"}, + {file = "duckdb-0.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5cfb93e73911696a98b9479299d19cfbc21dd05bb7ab11a923a903f86b4d06e"}, + {file = "duckdb-0.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:64e3bc01751f31e7572d2716c3e8da8fe785f1cdc5be329100818d223002213f"}, + {file = "duckdb-0.9.2-cp39-cp39-win32.whl", hash = "sha256:6e5b80f46487636368e31b61461940e3999986359a78660a50dfdd17dd72017c"}, + {file = "duckdb-0.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:e6142a220180dbeea4f341708bd5f9501c5c962ce7ef47c1cadf5e8810b4cb13"}, + {file = "duckdb-0.9.2.tar.gz", hash = "sha256:3843afeab7c3fc4a4c0b53686a4cc1d9cdbdadcbb468d60fef910355ecafd447"}, +] + [[package]] name = "easygui" version = "0.98.3" @@ -1633,9 +1963,6 @@ files = [ {file = "fake_useragent-1.5.1-py3-none-any.whl", hash = "sha256:57415096557c8a4e23b62a375c21c55af5fd4ba30549227f562d2c4f5b60e3b3"}, ] -[package.dependencies] -importlib-resources = {version = ">=5.0", markers = "python_version < \"3.10\""} - [[package]] name = "fastapi" version = "0.109.2" @@ -1779,7 +2106,6 @@ files = [ [package.dependencies] blinker = ">=1.6.2" click = ">=8.1.3" -importlib-metadata = {version = ">=3.6.0", markers = "python_version < \"3.10\""} itsdangerous = ">=2.1.2" Jinja2 = ">=3.1.2" Werkzeug = ">=3.0.0" @@ -1934,15 +2260,19 @@ files = [ [[package]] name = "fsspec" -version = "2024.3.1" +version = "2023.10.0" description = "File-system specification" optional = false python-versions = ">=3.8" files = [ - {file = "fsspec-2024.3.1-py3-none-any.whl", hash = "sha256:918d18d41bf73f0e2b261824baeb1b124bcf771767e3a26425cd7dec3332f512"}, - {file = "fsspec-2024.3.1.tar.gz", hash = "sha256:f39780e282d7d117ffb42bb96992f8a90795e4d0fb0f661a70ca39fe9c43ded9"}, + {file = "fsspec-2023.10.0-py3-none-any.whl", hash = "sha256:346a8f024efeb749d2a5fca7ba8854474b1ff9af7c3faaf636a4548781136529"}, + {file = "fsspec-2023.10.0.tar.gz", hash = "sha256:330c66757591df346ad3091a53bd907e15348c2ba17d63fd54f5c39c4457d2a5"}, ] +[package.dependencies] +aiohttp = {version = "<4.0.0a0 || >4.0.0a0,<4.0.0a1 || >4.0.0a1", optional = true, markers = "extra == \"http\""} +requests = {version = "*", optional = true, markers = "extra == \"http\""} + [package.extras] abfs = ["adlfs"] adl = ["adlfs"] @@ -1958,7 +2288,7 @@ github = ["requests"] gs = ["gcsfs"] gui = ["panel"] hdfs = ["pyarrow (>=1)"] -http = ["aiohttp (!=4.0.0a0,!=4.0.0a1)"] +http = ["aiohttp (!=4.0.0a0,!=4.0.0a1)", "requests"] libarchive = ["libarchive-c"] oci = ["ocifs"] s3 = ["s3fs"] @@ -1978,6 +2308,21 @@ files = [ {file = "future-1.0.0.tar.gz", hash = "sha256:bd2968309307861edae1458a4f8a4f3598c03be43b97521076aebf5d94c07b05"}, ] +[[package]] +name = "geomet" +version = "0.2.1.post1" +description = "GeoJSON <-> WKT/WKB conversion utilities" +optional = false +python-versions = ">2.6, !=3.3.*, <4" +files = [ + {file = "geomet-0.2.1.post1-py3-none-any.whl", hash = "sha256:a41a1e336b381416d6cbed7f1745c848e91defaa4d4c1bdc1312732e46ffad2b"}, + {file = "geomet-0.2.1.post1.tar.gz", hash = "sha256:91d754f7c298cbfcabd3befdb69c641c27fe75e808b27aa55028605761d17e95"}, +] + +[package.dependencies] +click = "*" +six = "*" + [[package]] name = "gevent" version = "24.2.1" @@ -2216,13 +2561,13 @@ grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] [[package]] name = "google-api-python-client" -version = "2.124.0" +version = "2.125.0" description = "Google API Client Library for Python" optional = false python-versions = ">=3.7" files = [ - {file = "google-api-python-client-2.124.0.tar.gz", hash = "sha256:f6d3258420f7c76b0f5266b5e402e6f804e30351b018a10083f4a46c3ec33773"}, - {file = "google_api_python_client-2.124.0-py2.py3-none-any.whl", hash = "sha256:07dc674449ed353704b1169fdee792f74438d024261dad71b6ce7bb9c683d51f"}, + {file = "google-api-python-client-2.125.0.tar.gz", hash = "sha256:51a0385cff65ec135106e8be60ee7112557396dde5f44113ae23912baddda143"}, + {file = "google_api_python_client-2.125.0-py2.py3-none-any.whl", hash = "sha256:0a62b60fbd61b61a455f15d925264b3301099b67cafd2d33cf8bf151f1fca4f4"}, ] [package.dependencies] @@ -2270,257 +2615,28 @@ files = [ google-auth = "*" httplib2 = ">=0.19.0" -[[package]] -name = "google-cloud-aiplatform" -version = "1.45.0" -description = "Vertex AI API client library" -optional = false -python-versions = ">=3.8" -files = [ - {file = "google-cloud-aiplatform-1.45.0.tar.gz", hash = "sha256:8fdc5f79fe9211ccbb9191b92db883798dffdd63995c12cc734bc17fcdbb3846"}, - {file = "google_cloud_aiplatform-1.45.0-py2.py3-none-any.whl", hash = "sha256:40bf5e2baa9cdb453689c4276eee5e7fe12db2e7723c133f000d35bcca964fb2"}, -] - -[package.dependencies] -docstring-parser = "<1" -google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.8.dev0,<3.0.0dev", extras = ["grpc"]} -google-auth = ">=2.14.1,<3.0.0dev" -google-cloud-bigquery = ">=1.15.0,<3.20.0 || >3.20.0,<4.0.0dev" -google-cloud-resource-manager = ">=1.3.3,<3.0.0dev" -google-cloud-storage = ">=1.32.0,<3.0.0dev" -packaging = ">=14.3" -proto-plus = ">=1.22.0,<2.0.0dev" -protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0dev" -pydantic = "<3" -shapely = "<3.0.0dev" - -[package.extras] -autologging = ["mlflow (>=1.27.0,<=2.1.1)"] -cloud-profiler = ["tensorboard-plugin-profile (>=2.4.0,<3.0.0dev)", "tensorflow (>=2.4.0,<3.0.0dev)", "werkzeug (>=2.0.0,<2.1.0dev)"] -datasets = ["pyarrow (>=10.0.1)", "pyarrow (>=3.0.0,<8.0dev)"] -endpoint = ["requests (>=2.28.1)"] -full = ["cloudpickle (<3.0)", "docker (>=5.0.3)", "explainable-ai-sdk (>=1.0.0)", "fastapi (>=0.71.0,<0.103.1)", "google-cloud-bigquery", "google-cloud-bigquery-storage", "google-cloud-logging (<4.0)", "google-vizier (>=0.1.6)", "httpx (>=0.23.0,<0.25.0)", "immutabledict", "lit-nlp (==0.4.0)", "mlflow (>=1.27.0,<=2.1.1)", "numpy (>=1.15.0)", "pandas (>=1.0.0)", "pandas (>=1.0.0,<2.2.0)", "pyarrow (>=10.0.1)", "pyarrow (>=3.0.0,<8.0dev)", "pyarrow (>=6.0.1)", "pydantic (<2)", "pyyaml (==5.3.1)", "ray[default] (>=2.4,<2.5.dev0 || >2.9.0,!=2.9.1,!=2.9.2,<=2.9.3)", "ray[default] (>=2.5,<=2.9.3)", "requests (>=2.28.1)", "starlette (>=0.17.1)", "tensorflow (>=2.3.0,<2.15.0)", "tensorflow (>=2.3.0,<3.0.0dev)", "urllib3 (>=1.21.1,<1.27)", "uvicorn[standard] (>=0.16.0)"] -lit = ["explainable-ai-sdk (>=1.0.0)", "lit-nlp (==0.4.0)", "pandas (>=1.0.0)", "tensorflow (>=2.3.0,<3.0.0dev)"] -metadata = ["numpy (>=1.15.0)", "pandas (>=1.0.0)"] -pipelines = ["pyyaml (==5.3.1)"] -prediction = ["docker (>=5.0.3)", "fastapi (>=0.71.0,<0.103.1)", "httpx (>=0.23.0,<0.25.0)", "starlette (>=0.17.1)", "uvicorn[standard] (>=0.16.0)"] -preview = ["cloudpickle (<3.0)", "google-cloud-logging (<4.0)"] -private-endpoints = ["requests (>=2.28.1)", "urllib3 (>=1.21.1,<1.27)"] -ray = ["google-cloud-bigquery", "google-cloud-bigquery-storage", "immutabledict", "pandas (>=1.0.0,<2.2.0)", "pyarrow (>=6.0.1)", "pydantic (<2)", "ray[default] (>=2.4,<2.5.dev0 || >2.9.0,!=2.9.1,!=2.9.2,<=2.9.3)", "ray[default] (>=2.5,<=2.9.3)"] -ray-testing = ["google-cloud-bigquery", "google-cloud-bigquery-storage", "immutabledict", "pandas (>=1.0.0,<2.2.0)", "pyarrow (>=6.0.1)", "pydantic (<2)", "pytest-xdist", "ray[default] (>=2.4,<2.5.dev0 || >2.9.0,!=2.9.1,!=2.9.2,<=2.9.3)", "ray[default] (>=2.5,<=2.9.3)", "ray[train] (>=2.4,<2.5.dev0 || >2.9.0,!=2.9.1,!=2.9.2,<=2.9.3)", "scikit-learn", "tensorflow", "torch (>=2.0.0,<2.1.0)", "xgboost", "xgboost-ray"] -tensorboard = ["tensorflow (>=2.3.0,<2.15.0)"] -testing = ["bigframes", "cloudpickle (<3.0)", "docker (>=5.0.3)", "explainable-ai-sdk (>=1.0.0)", "fastapi (>=0.71.0,<0.103.1)", "google-api-core (>=2.11,<3.0.0)", "google-cloud-bigquery", "google-cloud-bigquery-storage", "google-cloud-logging (<4.0)", "google-vizier (>=0.1.6)", "grpcio-testing", "httpx (>=0.23.0,<0.25.0)", "immutabledict", "ipython", "kfp (>=2.6.0,<3.0.0)", "lit-nlp (==0.4.0)", "mlflow (>=1.27.0,<=2.1.1)", "numpy (>=1.15.0)", "pandas (>=1.0.0)", "pandas (>=1.0.0,<2.2.0)", "pyarrow (>=10.0.1)", "pyarrow (>=3.0.0,<8.0dev)", "pyarrow (>=6.0.1)", "pydantic (<2)", "pyfakefs", "pytest-asyncio", "pytest-xdist", "pyyaml (==5.3.1)", "ray[default] (>=2.4,<2.5.dev0 || >2.9.0,!=2.9.1,!=2.9.2,<=2.9.3)", "ray[default] (>=2.5,<=2.9.3)", "requests (>=2.28.1)", "requests-toolbelt (<1.0.0)", "scikit-learn", "starlette (>=0.17.1)", "tensorboard-plugin-profile (>=2.4.0,<3.0.0dev)", "tensorflow (==2.13.0)", "tensorflow (>=2.3.0,<2.15.0)", "tensorflow (>=2.3.0,<3.0.0dev)", "tensorflow (>=2.4.0,<3.0.0dev)", "torch (>=2.0.0,<2.1.0)", "urllib3 (>=1.21.1,<1.27)", "uvicorn[standard] (>=0.16.0)", "werkzeug (>=2.0.0,<2.1.0dev)", "xgboost", "xgboost-ray"] -vizier = ["google-vizier (>=0.1.6)"] -xai = ["tensorflow (>=2.3.0,<3.0.0dev)"] - -[[package]] -name = "google-cloud-bigquery" -version = "3.19.0" -description = "Google BigQuery API client library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "google-cloud-bigquery-3.19.0.tar.gz", hash = "sha256:8e311dae49768e1501fcdc5e916bff4b7e169471e5707919f4a6f78a02b3b5a6"}, - {file = "google_cloud_bigquery-3.19.0-py2.py3-none-any.whl", hash = "sha256:c6b8850247a4b132066e49f6e45f850c22824482838688d744a4398eea1120ed"}, -] - -[package.dependencies] -google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]} -google-auth = ">=2.14.1,<3.0.0dev" -google-cloud-core = ">=1.6.0,<3.0.0dev" -google-resumable-media = ">=0.6.0,<3.0dev" -packaging = ">=20.0.0" -python-dateutil = ">=2.7.2,<3.0dev" -requests = ">=2.21.0,<3.0.0dev" - -[package.extras] -all = ["Shapely (>=1.8.4,<3.0.0dev)", "db-dtypes (>=0.3.0,<2.0.0dev)", "geopandas (>=0.9.0,<1.0dev)", "google-cloud-bigquery-storage (>=2.6.0,<3.0.0dev)", "grpcio (>=1.47.0,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "importlib-metadata (>=1.0.0)", "ipykernel (>=6.0.0)", "ipython (>=7.23.1,!=8.1.0)", "ipywidgets (>=7.7.0)", "opentelemetry-api (>=1.1.0)", "opentelemetry-instrumentation (>=0.20b0)", "opentelemetry-sdk (>=1.1.0)", "pandas (>=1.1.0)", "proto-plus (>=1.15.0,<2.0.0dev)", "protobuf (>=3.19.5,!=3.20.0,!=3.20.1,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<5.0.0dev)", "pyarrow (>=3.0.0)", "tqdm (>=4.7.4,<5.0.0dev)"] -bigquery-v2 = ["proto-plus (>=1.15.0,<2.0.0dev)", "protobuf (>=3.19.5,!=3.20.0,!=3.20.1,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<5.0.0dev)"] -bqstorage = ["google-cloud-bigquery-storage (>=2.6.0,<3.0.0dev)", "grpcio (>=1.47.0,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "pyarrow (>=3.0.0)"] -geopandas = ["Shapely (>=1.8.4,<3.0.0dev)", "geopandas (>=0.9.0,<1.0dev)"] -ipython = ["ipykernel (>=6.0.0)", "ipython (>=7.23.1,!=8.1.0)"] -ipywidgets = ["ipykernel (>=6.0.0)", "ipywidgets (>=7.7.0)"] -opentelemetry = ["opentelemetry-api (>=1.1.0)", "opentelemetry-instrumentation (>=0.20b0)", "opentelemetry-sdk (>=1.1.0)"] -pandas = ["db-dtypes (>=0.3.0,<2.0.0dev)", "importlib-metadata (>=1.0.0)", "pandas (>=1.1.0)", "pyarrow (>=3.0.0)"] -tqdm = ["tqdm (>=4.7.4,<5.0.0dev)"] - -[[package]] -name = "google-cloud-core" -version = "2.4.1" -description = "Google Cloud API client core library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "google-cloud-core-2.4.1.tar.gz", hash = "sha256:9b7749272a812bde58fff28868d0c5e2f585b82f37e09a1f6ed2d4d10f134073"}, - {file = "google_cloud_core-2.4.1-py2.py3-none-any.whl", hash = "sha256:a9e6a4422b9ac5c29f79a0ede9485473338e2ce78d91f2370c01e730eab22e61"}, -] - -[package.dependencies] -google-api-core = ">=1.31.6,<2.0.dev0 || >2.3.0,<3.0.0dev" -google-auth = ">=1.25.0,<3.0dev" - -[package.extras] -grpc = ["grpcio (>=1.38.0,<2.0dev)", "grpcio-status (>=1.38.0,<2.0.dev0)"] - -[[package]] -name = "google-cloud-resource-manager" -version = "1.12.3" -description = "Google Cloud Resource Manager API client library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "google-cloud-resource-manager-1.12.3.tar.gz", hash = "sha256:809851824119834e4f2310b2c4f38621c1d16b2bb14d5b9f132e69c79d355e7f"}, - {file = "google_cloud_resource_manager-1.12.3-py2.py3-none-any.whl", hash = "sha256:92be7d6959927b76d90eafc4028985c37975a46ded5466a018f02e8649e113d4"}, -] - -[package.dependencies] -google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]} -google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0dev" -grpc-google-iam-v1 = ">=0.12.4,<1.0.0dev" -proto-plus = ">=1.22.3,<2.0.0dev" -protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0dev" - -[[package]] -name = "google-cloud-storage" -version = "2.16.0" -description = "Google Cloud Storage API client library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "google-cloud-storage-2.16.0.tar.gz", hash = "sha256:dda485fa503710a828d01246bd16ce9db0823dc51bbca742ce96a6817d58669f"}, - {file = "google_cloud_storage-2.16.0-py2.py3-none-any.whl", hash = "sha256:91a06b96fb79cf9cdfb4e759f178ce11ea885c79938f89590344d079305f5852"}, -] - -[package.dependencies] -google-api-core = ">=2.15.0,<3.0.0dev" -google-auth = ">=2.26.1,<3.0dev" -google-cloud-core = ">=2.3.0,<3.0dev" -google-crc32c = ">=1.0,<2.0dev" -google-resumable-media = ">=2.6.0" -requests = ">=2.18.0,<3.0.0dev" - -[package.extras] -protobuf = ["protobuf (<5.0.0dev)"] - -[[package]] -name = "google-crc32c" -version = "1.5.0" -description = "A python wrapper of the C library 'Google CRC32C'" -optional = false -python-versions = ">=3.7" -files = [ - {file = "google-crc32c-1.5.0.tar.gz", hash = "sha256:89284716bc6a5a415d4eaa11b1726d2d60a0cd12aadf5439828353662ede9dd7"}, - {file = "google_crc32c-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:596d1f98fc70232fcb6590c439f43b350cb762fb5d61ce7b0e9db4539654cc13"}, - {file = "google_crc32c-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:be82c3c8cfb15b30f36768797a640e800513793d6ae1724aaaafe5bf86f8f346"}, - {file = "google_crc32c-1.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:461665ff58895f508e2866824a47bdee72497b091c730071f2b7575d5762ab65"}, - {file = "google_crc32c-1.5.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2096eddb4e7c7bdae4bd69ad364e55e07b8316653234a56552d9c988bd2d61b"}, - {file = "google_crc32c-1.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:116a7c3c616dd14a3de8c64a965828b197e5f2d121fedd2f8c5585c547e87b02"}, - {file = "google_crc32c-1.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5829b792bf5822fd0a6f6eb34c5f81dd074f01d570ed7f36aa101d6fc7a0a6e4"}, - {file = "google_crc32c-1.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:64e52e2b3970bd891309c113b54cf0e4384762c934d5ae56e283f9a0afcd953e"}, - {file = "google_crc32c-1.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:02ebb8bf46c13e36998aeaad1de9b48f4caf545e91d14041270d9dca767b780c"}, - {file = "google_crc32c-1.5.0-cp310-cp310-win32.whl", hash = "sha256:2e920d506ec85eb4ba50cd4228c2bec05642894d4c73c59b3a2fe20346bd00ee"}, - {file = "google_crc32c-1.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:07eb3c611ce363c51a933bf6bd7f8e3878a51d124acfc89452a75120bc436289"}, - {file = "google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:cae0274952c079886567f3f4f685bcaf5708f0a23a5f5216fdab71f81a6c0273"}, - {file = "google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1034d91442ead5a95b5aaef90dbfaca8633b0247d1e41621d1e9f9db88c36298"}, - {file = "google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c42c70cd1d362284289c6273adda4c6af8039a8ae12dc451dcd61cdabb8ab57"}, - {file = "google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8485b340a6a9e76c62a7dce3c98e5f102c9219f4cfbf896a00cf48caf078d438"}, - {file = "google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906"}, - {file = "google_crc32c-1.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f583edb943cf2e09c60441b910d6a20b4d9d626c75a36c8fcac01a6c96c01183"}, - {file = "google_crc32c-1.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:a1fd716e7a01f8e717490fbe2e431d2905ab8aa598b9b12f8d10abebb36b04dd"}, - {file = "google_crc32c-1.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:72218785ce41b9cfd2fc1d6a017dc1ff7acfc4c17d01053265c41a2c0cc39b8c"}, - {file = "google_crc32c-1.5.0-cp311-cp311-win32.whl", hash = "sha256:66741ef4ee08ea0b2cc3c86916ab66b6aef03768525627fd6a1b34968b4e3709"}, - {file = "google_crc32c-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:ba1eb1843304b1e5537e1fca632fa894d6f6deca8d6389636ee5b4797affb968"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:98cb4d057f285bd80d8778ebc4fde6b4d509ac3f331758fb1528b733215443ae"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd8536e902db7e365f49e7d9029283403974ccf29b13fc7028b97e2295b33556"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19e0a019d2c4dcc5e598cd4a4bc7b008546b0358bd322537c74ad47a5386884f"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02c65b9817512edc6a4ae7c7e987fea799d2e0ee40c53ec573a692bee24de876"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6ac08d24c1f16bd2bf5eca8eaf8304812f44af5cfe5062006ec676e7e1d50afc"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3359fc442a743e870f4588fcf5dcbc1bf929df1fad8fb9905cd94e5edb02e84c"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e986b206dae4476f41bcec1faa057851f3889503a70e1bdb2378d406223994a"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:de06adc872bcd8c2a4e0dc51250e9e65ef2ca91be023b9d13ebd67c2ba552e1e"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-win32.whl", hash = "sha256:d3515f198eaa2f0ed49f8819d5732d70698c3fa37384146079b3799b97667a94"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:67b741654b851abafb7bc625b6d1cdd520a379074e64b6a128e3b688c3c04740"}, - {file = "google_crc32c-1.5.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c02ec1c5856179f171e032a31d6f8bf84e5a75c45c33b2e20a3de353b266ebd8"}, - {file = "google_crc32c-1.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:edfedb64740750e1a3b16152620220f51d58ff1b4abceb339ca92e934775c27a"}, - {file = "google_crc32c-1.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84e6e8cd997930fc66d5bb4fde61e2b62ba19d62b7abd7a69920406f9ecca946"}, - {file = "google_crc32c-1.5.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:024894d9d3cfbc5943f8f230e23950cd4906b2fe004c72e29b209420a1e6b05a"}, - {file = "google_crc32c-1.5.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:998679bf62b7fb599d2878aa3ed06b9ce688b8974893e7223c60db155f26bd8d"}, - {file = "google_crc32c-1.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:83c681c526a3439b5cf94f7420471705bbf96262f49a6fe546a6db5f687a3d4a"}, - {file = "google_crc32c-1.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4c6fdd4fccbec90cc8a01fc00773fcd5fa28db683c116ee3cb35cd5da9ef6c37"}, - {file = "google_crc32c-1.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5ae44e10a8e3407dbe138984f21e536583f2bba1be9491239f942c2464ac0894"}, - {file = "google_crc32c-1.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:37933ec6e693e51a5b07505bd05de57eee12f3e8c32b07da7e73669398e6630a"}, - {file = "google_crc32c-1.5.0-cp38-cp38-win32.whl", hash = "sha256:fe70e325aa68fa4b5edf7d1a4b6f691eb04bbccac0ace68e34820d283b5f80d4"}, - {file = "google_crc32c-1.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:74dea7751d98034887dbd821b7aae3e1d36eda111d6ca36c206c44478035709c"}, - {file = "google_crc32c-1.5.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c6c777a480337ac14f38564ac88ae82d4cd238bf293f0a22295b66eb89ffced7"}, - {file = "google_crc32c-1.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:759ce4851a4bb15ecabae28f4d2e18983c244eddd767f560165563bf9aefbc8d"}, - {file = "google_crc32c-1.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f13cae8cc389a440def0c8c52057f37359014ccbc9dc1f0827936bcd367c6100"}, - {file = "google_crc32c-1.5.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e560628513ed34759456a416bf86b54b2476c59144a9138165c9a1575801d0d9"}, - {file = "google_crc32c-1.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1674e4307fa3024fc897ca774e9c7562c957af85df55efe2988ed9056dc4e57"}, - {file = "google_crc32c-1.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:278d2ed7c16cfc075c91378c4f47924c0625f5fc84b2d50d921b18b7975bd210"}, - {file = "google_crc32c-1.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d5280312b9af0976231f9e317c20e4a61cd2f9629b7bfea6a693d1878a264ebd"}, - {file = "google_crc32c-1.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8b87e1a59c38f275c0e3676fc2ab6d59eccecfd460be267ac360cc31f7bcde96"}, - {file = "google_crc32c-1.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7c074fece789b5034b9b1404a1f8208fc2d4c6ce9decdd16e8220c5a793e6f61"}, - {file = "google_crc32c-1.5.0-cp39-cp39-win32.whl", hash = "sha256:7f57f14606cd1dd0f0de396e1e53824c371e9544a822648cd76c034d209b559c"}, - {file = "google_crc32c-1.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:a2355cba1f4ad8b6988a4ca3feed5bff33f6af2d7f134852cf279c2aebfde541"}, - {file = "google_crc32c-1.5.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f314013e7dcd5cf45ab1945d92e713eec788166262ae8deb2cfacd53def27325"}, - {file = "google_crc32c-1.5.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b747a674c20a67343cb61d43fdd9207ce5da6a99f629c6e2541aa0e89215bcd"}, - {file = "google_crc32c-1.5.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8f24ed114432de109aa9fd317278518a5af2d31ac2ea6b952b2f7782b43da091"}, - {file = "google_crc32c-1.5.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8667b48e7a7ef66afba2c81e1094ef526388d35b873966d8a9a447974ed9178"}, - {file = "google_crc32c-1.5.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:1c7abdac90433b09bad6c43a43af253e688c9cfc1c86d332aed13f9a7c7f65e2"}, - {file = "google_crc32c-1.5.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6f998db4e71b645350b9ac28a2167e6632c239963ca9da411523bb439c5c514d"}, - {file = "google_crc32c-1.5.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c99616c853bb585301df6de07ca2cadad344fd1ada6d62bb30aec05219c45d2"}, - {file = "google_crc32c-1.5.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2ad40e31093a4af319dadf503b2467ccdc8f67c72e4bcba97f8c10cb078207b5"}, - {file = "google_crc32c-1.5.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd67cf24a553339d5062eff51013780a00d6f97a39ca062781d06b3a73b15462"}, - {file = "google_crc32c-1.5.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:398af5e3ba9cf768787eef45c803ff9614cc3e22a5b2f7d7ae116df8b11e3314"}, - {file = "google_crc32c-1.5.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b1f8133c9a275df5613a451e73f36c2aea4fe13c5c8997e22cf355ebd7bd0728"}, - {file = "google_crc32c-1.5.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9ba053c5f50430a3fcfd36f75aff9caeba0440b2d076afdb79a318d6ca245f88"}, - {file = "google_crc32c-1.5.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:272d3892a1e1a2dbc39cc5cde96834c236d5327e2122d3aaa19f6614531bb6eb"}, - {file = "google_crc32c-1.5.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:635f5d4dd18758a1fbd1049a8e8d2fee4ffed124462d837d1a02a0e009c3ab31"}, - {file = "google_crc32c-1.5.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c672d99a345849301784604bfeaeba4db0c7aae50b95be04dd651fd2a7310b93"}, -] - -[package.extras] -testing = ["pytest"] - [[package]] name = "google-generativeai" -version = "0.3.2" +version = "0.4.1" description = "Google Generative AI High level API client library and tools." optional = false python-versions = ">=3.9" files = [ - {file = "google_generativeai-0.3.2-py3-none-any.whl", hash = "sha256:8761147e6e167141932dc14a7b7af08f2310dd56668a78d206c19bb8bd85bcd7"}, + {file = "google_generativeai-0.4.1-py3-none-any.whl", hash = "sha256:89be3c00c2e688108fccefc50f47f45fc9d37ecd53c1ade9d86b5d982919c24a"}, ] [package.dependencies] google-ai-generativelanguage = "0.4.0" google-api-core = "*" -google-auth = "*" +google-auth = ">=2.15.0" protobuf = "*" +pydantic = "*" tqdm = "*" typing-extensions = "*" [package.extras] dev = ["Pillow", "absl-py", "black", "ipython", "nose2", "pandas", "pytype", "pyyaml"] -[[package]] -name = "google-resumable-media" -version = "2.7.0" -description = "Utilities for Google Media Downloads and Resumable Uploads" -optional = false -python-versions = ">= 3.7" -files = [ - {file = "google-resumable-media-2.7.0.tar.gz", hash = "sha256:5f18f5fa9836f4b083162064a1c2c98c17239bfda9ca50ad970ccf905f3e625b"}, - {file = "google_resumable_media-2.7.0-py2.py3-none-any.whl", hash = "sha256:79543cfe433b63fd81c0844b7803aba1bb8950b47bedf7d980c38fa123937e08"}, -] - -[package.dependencies] -google-crc32c = ">=1.0,<2.0dev" - -[package.extras] -aiohttp = ["aiohttp (>=3.6.2,<4.0.0dev)", "google-auth (>=1.22.0,<2.0dev)"] -requests = ["requests (>=2.18.0,<3.0.0dev)"] - [[package]] name = "google-search-results" version = "2.4.2" @@ -2546,7 +2662,6 @@ files = [ ] [package.dependencies] -grpcio = {version = ">=1.44.0,<2.0.0.dev0", optional = true, markers = "extra == \"grpc\""} protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0.dev0" [package.extras] @@ -2638,22 +2753,6 @@ files = [ docs = ["Sphinx", "furo"] test = ["objgraph", "psutil"] -[[package]] -name = "grpc-google-iam-v1" -version = "0.13.0" -description = "IAM API client library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "grpc-google-iam-v1-0.13.0.tar.gz", hash = "sha256:fad318608b9e093258fbf12529180f400d1c44453698a33509cc6ecf005b294e"}, - {file = "grpc_google_iam_v1-0.13.0-py2.py3-none-any.whl", hash = "sha256:53902e2af7de8df8c1bd91373d9be55b0743ec267a7428ea638db3775becae89"}, -] - -[package.dependencies] -googleapis-common-protos = {version = ">=1.56.0,<2.0.0dev", extras = ["grpc"]} -grpcio = ">=1.44.0,<2.0.0dev" -protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0dev" - [[package]] name = "grpcio" version = "1.62.1" @@ -2876,6 +2975,16 @@ files = [ {file = "hpack-4.0.0.tar.gz", hash = "sha256:fc41de0c63e687ebffde81187a948221294896f6bdc0ae2312708df339430095"}, ] +[[package]] +name = "html2text" +version = "2024.2.26" +description = "Turn HTML into equivalent Markdown-structured text." +optional = false +python-versions = ">=3.8" +files = [ + {file = "html2text-2024.2.26.tar.gz", hash = "sha256:05f8e367d15aaabc96415376776cdd11afd5127a77fce6e36afc60c563ca2c32"}, +] + [[package]] name = "httpcore" version = "1.0.5" @@ -3068,15 +3177,113 @@ files = [ {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, ] +[[package]] +name = "ijson" +version = "3.2.3" +description = "Iterative JSON parser with standard Python iterator interfaces" +optional = false +python-versions = "*" +files = [ + {file = "ijson-3.2.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0a4ae076bf97b0430e4e16c9cb635a6b773904aec45ed8dcbc9b17211b8569ba"}, + {file = "ijson-3.2.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cfced0a6ec85916eb8c8e22415b7267ae118eaff2a860c42d2cc1261711d0d31"}, + {file = "ijson-3.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0b9d1141cfd1e6d6643aa0b4876730d0d28371815ce846d2e4e84a2d4f471cf3"}, + {file = "ijson-3.2.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e0a27db6454edd6013d40a956d008361aac5bff375a9c04ab11fc8c214250b5"}, + {file = "ijson-3.2.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c0d526ccb335c3c13063c273637d8611f32970603dfb182177b232d01f14c23"}, + {file = "ijson-3.2.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:545a30b3659df2a3481593d30d60491d1594bc8005f99600e1bba647bb44cbb5"}, + {file = "ijson-3.2.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9680e37a10fedb3eab24a4a7e749d8a73f26f1a4c901430e7aa81b5da15f7307"}, + {file = "ijson-3.2.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2a80c0bb1053055d1599e44dc1396f713e8b3407000e6390add72d49633ff3bb"}, + {file = "ijson-3.2.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f05ed49f434ce396ddcf99e9fd98245328e99f991283850c309f5e3182211a79"}, + {file = "ijson-3.2.3-cp310-cp310-win32.whl", hash = "sha256:b4eb2304573c9fdf448d3fa4a4fdcb727b93002b5c5c56c14a5ffbbc39f64ae4"}, + {file = "ijson-3.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:923131f5153c70936e8bd2dd9dcfcff43c67a3d1c789e9c96724747423c173eb"}, + {file = "ijson-3.2.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:904f77dd3d87736ff668884fe5197a184748eb0c3e302ded61706501d0327465"}, + {file = "ijson-3.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0974444c1f416e19de1e9f567a4560890095e71e81623c509feff642114c1e53"}, + {file = "ijson-3.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c1a4b8eb69b6d7b4e94170aa991efad75ba156b05f0de2a6cd84f991def12ff9"}, + {file = "ijson-3.2.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d052417fd7ce2221114f8d3b58f05a83c1a2b6b99cafe0b86ac9ed5e2fc889df"}, + {file = "ijson-3.2.3-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b8064a85ec1b0beda7dd028e887f7112670d574db606f68006c72dd0bb0e0e2"}, + {file = "ijson-3.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaac293853f1342a8d2a45ac1f723c860f700860e7743fb97f7b76356df883a8"}, + {file = "ijson-3.2.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6c32c18a934c1dc8917455b0ce478fd7a26c50c364bd52c5a4fb0fc6bb516af7"}, + {file = "ijson-3.2.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:713a919e0220ac44dab12b5fed74f9130f3480e55e90f9d80f58de129ea24f83"}, + {file = "ijson-3.2.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4a3a6a2fbbe7550ffe52d151cf76065e6b89cfb3e9d0463e49a7e322a25d0426"}, + {file = "ijson-3.2.3-cp311-cp311-win32.whl", hash = "sha256:6a4db2f7fb9acfb855c9ae1aae602e4648dd1f88804a0d5cfb78c3639bcf156c"}, + {file = "ijson-3.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:ccd6be56335cbb845f3d3021b1766299c056c70c4c9165fb2fbe2d62258bae3f"}, + {file = "ijson-3.2.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:055b71bbc37af5c3c5861afe789e15211d2d3d06ac51ee5a647adf4def19c0ea"}, + {file = "ijson-3.2.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c075a547de32f265a5dd139ab2035900fef6653951628862e5cdce0d101af557"}, + {file = "ijson-3.2.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:457f8a5fc559478ac6b06b6d37ebacb4811f8c5156e997f0d87d708b0d8ab2ae"}, + {file = "ijson-3.2.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9788f0c915351f41f0e69ec2618b81ebfcf9f13d9d67c6d404c7f5afda3e4afb"}, + {file = "ijson-3.2.3-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fa234ab7a6a33ed51494d9d2197fb96296f9217ecae57f5551a55589091e7853"}, + {file = "ijson-3.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdd0dc5da4f9dc6d12ab6e8e0c57d8b41d3c8f9ceed31a99dae7b2baf9ea769a"}, + {file = "ijson-3.2.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c6beb80df19713e39e68dc5c337b5c76d36ccf69c30b79034634e5e4c14d6904"}, + {file = "ijson-3.2.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:a2973ce57afb142d96f35a14e9cfec08308ef178a2c76b8b5e1e98f3960438bf"}, + {file = "ijson-3.2.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:105c314fd624e81ed20f925271ec506523b8dd236589ab6c0208b8707d652a0e"}, + {file = "ijson-3.2.3-cp312-cp312-win32.whl", hash = "sha256:ac44781de5e901ce8339352bb5594fcb3b94ced315a34dbe840b4cff3450e23b"}, + {file = "ijson-3.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:0567e8c833825b119e74e10a7c29761dc65fcd155f5d4cb10f9d3b8916ef9912"}, + {file = "ijson-3.2.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:eeb286639649fb6bed37997a5e30eefcacddac79476d24128348ec890b2a0ccb"}, + {file = "ijson-3.2.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:396338a655fb9af4ac59dd09c189885b51fa0eefc84d35408662031023c110d1"}, + {file = "ijson-3.2.3-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e0243d166d11a2a47c17c7e885debf3b19ed136be2af1f5d1c34212850236ac"}, + {file = "ijson-3.2.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85afdb3f3a5d0011584d4fa8e6dccc5936be51c27e84cd2882fe904ca3bd04c5"}, + {file = "ijson-3.2.3-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:4fc35d569eff3afa76bfecf533f818ecb9390105be257f3f83c03204661ace70"}, + {file = "ijson-3.2.3-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:455d7d3b7a6aacfb8ab1ebcaf697eedf5be66e044eac32508fccdc633d995f0e"}, + {file = "ijson-3.2.3-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:c63f3d57dbbac56cead05b12b81e8e1e259f14ce7f233a8cbe7fa0996733b628"}, + {file = "ijson-3.2.3-cp36-cp36m-win32.whl", hash = "sha256:a4d7fe3629de3ecb088bff6dfe25f77be3e8261ed53d5e244717e266f8544305"}, + {file = "ijson-3.2.3-cp36-cp36m-win_amd64.whl", hash = "sha256:96190d59f015b5a2af388a98446e411f58ecc6a93934e036daa75f75d02386a0"}, + {file = "ijson-3.2.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:35194e0b8a2bda12b4096e2e792efa5d4801a0abb950c48ade351d479cd22ba5"}, + {file = "ijson-3.2.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1053fb5f0b010ee76ca515e6af36b50d26c1728ad46be12f1f147a835341083"}, + {file = "ijson-3.2.3-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:211124cff9d9d139dd0dfced356f1472860352c055d2481459038b8205d7d742"}, + {file = "ijson-3.2.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:92dc4d48e9f6a271292d6079e9fcdce33c83d1acf11e6e12696fb05c5889fe74"}, + {file = "ijson-3.2.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3dcc33ee56f92a77f48776014ddb47af67c33dda361e84371153c4f1ed4434e1"}, + {file = "ijson-3.2.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:98c6799925a5d1988da4cd68879b8eeab52c6e029acc45e03abb7921a4715c4b"}, + {file = "ijson-3.2.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4252e48c95cd8ceefc2caade310559ab61c37d82dfa045928ed05328eb5b5f65"}, + {file = "ijson-3.2.3-cp37-cp37m-win32.whl", hash = "sha256:644f4f03349ff2731fd515afd1c91b9e439e90c9f8c28292251834154edbffca"}, + {file = "ijson-3.2.3-cp37-cp37m-win_amd64.whl", hash = "sha256:ba33c764afa9ecef62801ba7ac0319268a7526f50f7601370d9f8f04e77fc02b"}, + {file = "ijson-3.2.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:4b2ec8c2a3f1742cbd5f36b65e192028e541b5fd8c7fd97c1fc0ca6c427c704a"}, + {file = "ijson-3.2.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7dc357da4b4ebd8903e77dbcc3ce0555ee29ebe0747c3c7f56adda423df8ec89"}, + {file = "ijson-3.2.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bcc51c84bb220ac330122468fe526a7777faa6464e3b04c15b476761beea424f"}, + {file = "ijson-3.2.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8d54b624629f9903005c58d9321a036c72f5c212701bbb93d1a520ecd15e370"}, + {file = "ijson-3.2.3-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6ea7c7e3ec44742e867c72fd750c6a1e35b112f88a917615332c4476e718d40"}, + {file = "ijson-3.2.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:916acdc5e504f8b66c3e287ada5d4b39a3275fc1f2013c4b05d1ab9933671a6c"}, + {file = "ijson-3.2.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:81815b4184b85ce124bfc4c446d5f5e5e643fc119771c5916f035220ada29974"}, + {file = "ijson-3.2.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b49fd5fe1cd9c1c8caf6c59f82b08117dd6bea2ec45b641594e25948f48f4169"}, + {file = "ijson-3.2.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:86b3c91fdcb8ffb30556c9669930f02b7642de58ca2987845b04f0d7fe46d9a8"}, + {file = "ijson-3.2.3-cp38-cp38-win32.whl", hash = "sha256:a729b0c8fb935481afe3cf7e0dadd0da3a69cc7f145dbab8502e2f1e01d85a7c"}, + {file = "ijson-3.2.3-cp38-cp38-win_amd64.whl", hash = "sha256:d34e049992d8a46922f96483e96b32ac4c9cffd01a5c33a928e70a283710cd58"}, + {file = "ijson-3.2.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9c2a12dcdb6fa28f333bf10b3a0f80ec70bc45280d8435be7e19696fab2bc706"}, + {file = "ijson-3.2.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1844c5b57da21466f255a0aeddf89049e730d7f3dfc4d750f0e65c36e6a61a7c"}, + {file = "ijson-3.2.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2ec3e5ff2515f1c40ef6a94983158e172f004cd643b9e4b5302017139b6c96e4"}, + {file = "ijson-3.2.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46bafb1b9959872a1f946f8dd9c6f1a30a970fc05b7bfae8579da3f1f988e598"}, + {file = "ijson-3.2.3-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ab4db9fee0138b60e31b3c02fff8a4c28d7b152040553b6a91b60354aebd4b02"}, + {file = "ijson-3.2.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4bc87e69d1997c6a55fff5ee2af878720801ff6ab1fb3b7f94adda050651e37"}, + {file = "ijson-3.2.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e9fd906f0c38e9f0bfd5365e1bed98d649f506721f76bb1a9baa5d7374f26f19"}, + {file = "ijson-3.2.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e84d27d1acb60d9102728d06b9650e5b7e5cb0631bd6e3dfadba8fb6a80d6c2f"}, + {file = "ijson-3.2.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2cc04fc0a22bb945cd179f614845c8b5106c0b3939ee0d84ce67c7a61ac1a936"}, + {file = "ijson-3.2.3-cp39-cp39-win32.whl", hash = "sha256:e641814793a037175f7ec1b717ebb68f26d89d82cfd66f36e588f32d7e488d5f"}, + {file = "ijson-3.2.3-cp39-cp39-win_amd64.whl", hash = "sha256:6bd3e7e91d031f1e8cea7ce53f704ab74e61e505e8072467e092172422728b22"}, + {file = "ijson-3.2.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:06f9707da06a19b01013f8c65bf67db523662a9b4a4ff027e946e66c261f17f0"}, + {file = "ijson-3.2.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be8495f7c13fa1f622a2c6b64e79ac63965b89caf664cc4e701c335c652d15f2"}, + {file = "ijson-3.2.3-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7596b42f38c3dcf9d434dddd50f46aeb28e96f891444c2b4b1266304a19a2c09"}, + {file = "ijson-3.2.3-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fbac4e9609a1086bbad075beb2ceec486a3b138604e12d2059a33ce2cba93051"}, + {file = "ijson-3.2.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:db2d6341f9cb538253e7fe23311d59252f124f47165221d3c06a7ed667ecd595"}, + {file = "ijson-3.2.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fa8b98be298efbb2588f883f9953113d8a0023ab39abe77fe734b71b46b1220a"}, + {file = "ijson-3.2.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:674e585361c702fad050ab4c153fd168dc30f5980ef42b64400bc84d194e662d"}, + {file = "ijson-3.2.3-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd12e42b9cb9c0166559a3ffa276b4f9fc9d5b4c304e5a13668642d34b48b634"}, + {file = "ijson-3.2.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d31e0d771d82def80cd4663a66de277c3b44ba82cd48f630526b52f74663c639"}, + {file = "ijson-3.2.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:7ce4c70c23521179d6da842bb9bc2e36bb9fad1e0187e35423ff0f282890c9ca"}, + {file = "ijson-3.2.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:39f551a6fbeed4433c85269c7c8778e2aaea2501d7ebcb65b38f556030642c17"}, + {file = "ijson-3.2.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b14d322fec0de7af16f3ef920bf282f0dd747200b69e0b9628117f381b7775b"}, + {file = "ijson-3.2.3-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7851a341429b12d4527ca507097c959659baf5106c7074d15c17c387719ffbcd"}, + {file = "ijson-3.2.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db3bf1b42191b5cc9b6441552fdcb3b583594cb6b19e90d1578b7cbcf80d0fae"}, + {file = "ijson-3.2.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:6f662dc44362a53af3084d3765bb01cd7b4734d1f484a6095cad4cb0cbfe5374"}, + {file = "ijson-3.2.3.tar.gz", hash = "sha256:10294e9bf89cb713da05bc4790bdff616610432db561964827074898e174f917"}, +] + [[package]] name = "importlib-metadata" -version = "6.11.0" +version = "7.0.0" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_metadata-6.11.0-py3-none-any.whl", hash = "sha256:f0afba6205ad8f8947c7d338b5342d5db2afbfd82f9cbef7879a9539cc12eb9b"}, - {file = "importlib_metadata-6.11.0.tar.gz", hash = "sha256:1231cf92d825c9e03cfc4da076a16de6422c863558229ea0b22b675657463443"}, + {file = "importlib_metadata-7.0.0-py3-none-any.whl", hash = "sha256:d97503976bb81f40a193d41ee6570868479c69d5068651eb039c40d850c59d67"}, + {file = "importlib_metadata-7.0.0.tar.gz", hash = "sha256:7fc841f8b8332803464e5dc1c63a2e59121f46ca186c0e2e182e80bf8c1319f7"}, ] [package.dependencies] @@ -3098,9 +3305,6 @@ files = [ {file = "importlib_resources-6.4.0.tar.gz", hash = "sha256:cdb2b453b8046ca4e3798eb1d84f3cce1446a0e8e7b5ef4efb600f19fc398145"}, ] -[package.dependencies] -zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} - [package.extras] docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] testing = ["jaraco.test (>=5.4)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-ruff (>=0.2.1)", "zipp (>=3.17)"] @@ -3116,6 +3320,26 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] +[[package]] +name = "instructor" +version = "0.5.2" +description = "structured outputs for llm" +optional = false +python-versions = ">=3.10,<4.0" +files = [ + {file = "instructor-0.5.2-py3-none-any.whl", hash = "sha256:8c7c927f3cbf6cd863eeebceae3f021e27eaca2ceaf9e9f3c8204540a1126160"}, + {file = "instructor-0.5.2.tar.gz", hash = "sha256:d8d679eb4624254db615794aaab59840e506fa696bc0181d998ae4f9ded2706d"}, +] + +[package.dependencies] +aiohttp = ">=3.9.1,<4.0.0" +docstring-parser = ">=0.15,<0.16" +openai = ">=1.1.0,<2.0.0" +pydantic = ">=2.0.2,<3.0.0" +rich = ">=13.7.0,<14.0.0" +tenacity = ">=8.2.3,<9.0.0" +typer = ">=0.9.0,<0.10.0" + [[package]] name = "ipykernel" version = "6.29.4" @@ -3151,13 +3375,13 @@ test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio [[package]] name = "ipython" -version = "8.18.1" +version = "8.23.0" description = "IPython: Productive Interactive Computing" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" files = [ - {file = "ipython-8.18.1-py3-none-any.whl", hash = "sha256:e8267419d72d81955ec1177f8a29aaa90ac80ad647499201119e2f05e99aa397"}, - {file = "ipython-8.18.1.tar.gz", hash = "sha256:ca6f079bb33457c66e233e4580ebfc4128855b4cf6370dddd73842a9563e8a27"}, + {file = "ipython-8.23.0-py3-none-any.whl", hash = "sha256:07232af52a5ba146dc3372c7bf52a0f890a23edf38d77caef8d53f9cdc2584c1"}, + {file = "ipython-8.23.0.tar.gz", hash = "sha256:7468edaf4f6de3e1b912e57f66c241e6fd3c7099f2ec2136e239e142e800274d"}, ] [package.dependencies] @@ -3166,25 +3390,26 @@ decorator = "*" exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} jedi = ">=0.16" matplotlib-inline = "*" -pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} +pexpect = {version = ">4.3", markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\""} prompt-toolkit = ">=3.0.41,<3.1.0" pygments = ">=2.4.0" stack-data = "*" -traitlets = ">=5" -typing-extensions = {version = "*", markers = "python_version < \"3.10\""} +traitlets = ">=5.13.0" +typing-extensions = {version = "*", markers = "python_version < \"3.12\""} [package.extras] -all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"] +all = ["ipython[black,doc,kernel,matplotlib,nbconvert,nbformat,notebook,parallel,qtconsole]", "ipython[test,test-extra]"] black = ["black"] -doc = ["docrepr", "exceptiongroup", "ipykernel", "matplotlib", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"] +doc = ["docrepr", "exceptiongroup", "ipykernel", "ipython[test]", "matplotlib", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "sphinxcontrib-jquery", "stack-data", "typing-extensions"] kernel = ["ipykernel"] +matplotlib = ["matplotlib"] nbconvert = ["nbconvert"] nbformat = ["nbformat"] notebook = ["ipywidgets", "notebook"] parallel = ["ipyparallel"] qtconsole = ["qtconsole"] -test = ["pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath"] -test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath", "trio"] +test = ["pickleshare", "pytest (<8)", "pytest-asyncio (<0.22)", "testpath"] +test-extra = ["curio", "ipython[test]", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.23)", "pandas", "trio"] [[package]] name = "itsdangerous" @@ -3385,7 +3610,6 @@ files = [ ] [package.dependencies] -importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" python-dateutil = ">=2.8.2" pyzmq = ">=23.0" @@ -3429,7 +3653,6 @@ files = [ [package.dependencies] amqp = ">=5.1.1,<6.0.0" -typing-extensions = {version = "*", markers = "python_version < \"3.10\""} vine = "*" [package.extras] @@ -3477,13 +3700,13 @@ adal = ["adal (>=1.0.2)"] [[package]] name = "langchain" -version = "0.1.13" +version = "0.1.14" description = "Building applications with LLMs through composability" optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain-0.1.13-py3-none-any.whl", hash = "sha256:c87657021b777d6b07e55be379a28660a1cd148c31593569869dd6b0b4cab945"}, - {file = "langchain-0.1.13.tar.gz", hash = "sha256:db330aa79c33501cb1ed97ff465f7645813eaa6cfd742c61e19c2d48e4aaba18"}, + {file = "langchain-0.1.14-py3-none-any.whl", hash = "sha256:94f9b5df2421faaf762d4f43b9d65c270c2f701934580d281e4c6226deef7234"}, + {file = "langchain-0.1.14.tar.gz", hash = "sha256:124c6244cf3957616b98f2df07dc2992fc40dff6ed1a62d8ee8a40f1e0260a40"}, ] [package.dependencies] @@ -3491,8 +3714,8 @@ aiohttp = ">=3.8.3,<4.0.0" async-timeout = {version = ">=4.0.0,<5.0.0", markers = "python_version < \"3.11\""} dataclasses-json = ">=0.5.7,<0.7" jsonpatch = ">=1.33,<2.0" -langchain-community = ">=0.0.29,<0.1" -langchain-core = ">=0.1.33,<0.2.0" +langchain-community = ">=0.0.30,<0.1" +langchain-core = ">=0.1.37,<0.2.0" langchain-text-splitters = ">=0.0.1,<0.1" langsmith = ">=0.1.17,<0.2.0" numpy = ">=1,<2" @@ -3506,12 +3729,12 @@ tenacity = ">=8.1.0,<9.0.0" azure = ["azure-ai-formrecognizer (>=3.2.1,<4.0.0)", "azure-ai-textanalytics (>=5.3.0,<6.0.0)", "azure-cognitiveservices-speech (>=1.28.0,<2.0.0)", "azure-core (>=1.26.4,<2.0.0)", "azure-cosmos (>=4.4.0b1,<5.0.0)", "azure-identity (>=1.12.0,<2.0.0)", "azure-search-documents (==11.4.0b8)", "openai (<2)"] clarifai = ["clarifai (>=9.1.0)"] cli = ["typer (>=0.9.0,<0.10.0)"] -cohere = ["cohere (>=4,<5)"] +cohere = ["cohere (>=4,<6)"] docarray = ["docarray[hnswlib] (>=0.32.0,<0.33.0)"] embeddings = ["sentence-transformers (>=2,<3)"] -extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cohere (>=4,<5)", "couchbase (>=4.1.9,<5.0.0)", "dashvector (>=1.0.1,<2.0.0)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "langchain-openai (>=0.0.2,<0.1)", "lxml (>=4.9.2,<5.0.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "upstash-redis (>=0.15.0,<0.16.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"] +extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cohere (>=4,<6)", "couchbase (>=4.1.9,<5.0.0)", "dashvector (>=1.0.1,<2.0.0)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "langchain-openai (>=0.0.2,<0.1)", "lxml (>=4.9.3,<6.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "upstash-redis (>=0.15.0,<0.16.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"] javascript = ["esprima (>=4.0.1,<5.0.0)"] -llms = ["clarifai (>=9.1.0)", "cohere (>=4,<5)", "huggingface_hub (>=0,<1)", "manifest-ml (>=0.0.1,<0.0.2)", "nlpcloud (>=1,<2)", "openai (<2)", "openlm (>=0.0.5,<0.0.6)", "torch (>=1,<3)", "transformers (>=4,<5)"] +llms = ["clarifai (>=9.1.0)", "cohere (>=4,<6)", "huggingface_hub (>=0,<1)", "manifest-ml (>=0.0.1,<0.0.2)", "nlpcloud (>=1,<2)", "openai (<2)", "openlm (>=0.0.5,<0.0.6)", "torch (>=1,<3)", "transformers (>=4,<5)"] openai = ["openai (<2)", "tiktoken (>=0.3.2,<0.6.0)"] qdrant = ["qdrant-client (>=1.3.1,<2.0.0)"] text-helpers = ["chardet (>=5.1.0,<6.0.0)"] @@ -3532,21 +3755,52 @@ anthropic = ">=0.17.0,<1" defusedxml = ">=0.7.1,<0.8.0" langchain-core = ">=0.1,<0.2" +[[package]] +name = "langchain-astradb" +version = "0.1.0" +description = "An integration package connecting Astra DB and LangChain" +optional = false +python-versions = ">=3.8.1,<4.0" +files = [ + {file = "langchain_astradb-0.1.0-py3-none-any.whl", hash = "sha256:c6686089da343fce8c31e36c9162323e88888300b09d56b72347a19449d7361f"}, + {file = "langchain_astradb-0.1.0.tar.gz", hash = "sha256:c8a3426c9daa2beeec2dc7a718186b0b9c388082e9543e0bc07363712cc3b947"}, +] + +[package.dependencies] +astrapy = ">=0.7.7,<0.8.0" +langchain-core = ">=0.1.31,<0.2.0" +numpy = ">=1,<2" + +[[package]] +name = "langchain-cohere" +version = "0.1.0" +description = "An integration package connecting Cohere and LangChain" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "langchain_cohere-0.1.0-py3-none-any.whl", hash = "sha256:f60e9eb41f7d4ead9659bddb3fae7aa18ddc3fdf2b2867be4bd8a565229f488d"}, + {file = "langchain_cohere-0.1.0.tar.gz", hash = "sha256:960551293ea58d170fad37d44657d3ae4587f6b2e8f3f58922c53c59b9e9d85c"}, +] + +[package.dependencies] +cohere = ">=5.1.4,<6.0.0" +langchain-core = ">=0.1.32,<0.2.0" + [[package]] name = "langchain-community" -version = "0.0.29" +version = "0.0.31" description = "Community contributed LangChain integrations." optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain_community-0.0.29-py3-none-any.whl", hash = "sha256:1652dddf257089b7b5066974b636262b4a5b680339f4539be133b14ae351e67d"}, - {file = "langchain_community-0.0.29.tar.gz", hash = "sha256:d88107fafa9fe2c5733da9630c68d9ee51cd33b1c88a4950e7a2d9a38f7e7aa3"}, + {file = "langchain_community-0.0.31-py3-none-any.whl", hash = "sha256:905c01b978a1cef7fdcddd2d9241dedc9987db6f23ba1b58d974e38b1cdf2775"}, + {file = "langchain_community-0.0.31.tar.gz", hash = "sha256:9a970bc2bb59bb4c204b696d8c62c2534f6ddb31005005cc1b7d7f934e58a5fc"}, ] [package.dependencies] aiohttp = ">=3.8.3,<4.0.0" dataclasses-json = ">=0.5.7,<0.7" -langchain-core = ">=0.1.33,<0.2.0" +langchain-core = ">=0.1.37,<0.2.0" langsmith = ">=0.1.0,<0.2.0" numpy = ">=1,<2" PyYAML = ">=5.3" @@ -3556,17 +3810,17 @@ tenacity = ">=8.1.0,<9.0.0" [package.extras] cli = ["typer (>=0.9.0,<0.10.0)"] -extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "azure-ai-documentintelligence (>=1.0.0b1,<2.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cloudpickle (>=2.0.0)", "cohere (>=4,<5)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "elasticsearch (>=8.12.0,<9.0.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "friendli-client (>=1.2.4,<2.0.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "gradientai (>=1.4.0,<2.0.0)", "hdbcli (>=2.19.21,<3.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "httpx (>=0.24.1,<0.25.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "lxml (>=4.9.2,<5.0.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "nvidia-riva-client (>=2.14.0,<3.0.0)", "oci (>=2.119.1,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "oracle-ads (>=2.9.1,<3.0.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "tidb-vector (>=0.0.3,<1.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "tree-sitter (>=0.20.2,<0.21.0)", "tree-sitter-languages (>=1.8.0,<2.0.0)", "upstash-redis (>=0.15.0,<0.16.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)", "zhipuai (>=1.0.7,<2.0.0)"] +extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "azure-ai-documentintelligence (>=1.0.0b1,<2.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cloudpickle (>=2.0.0)", "cohere (>=4,<5)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "elasticsearch (>=8.12.0,<9.0.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "friendli-client (>=1.2.4,<2.0.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "gradientai (>=1.4.0,<2.0.0)", "hdbcli (>=2.19.21,<3.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "httpx (>=0.24.1,<0.25.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "lxml (>=4.9.3,<6.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "nvidia-riva-client (>=2.14.0,<3.0.0)", "oci (>=2.119.1,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "oracle-ads (>=2.9.1,<3.0.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "premai (>=0.3.25,<0.4.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "tidb-vector (>=0.0.3,<1.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "tree-sitter (>=0.20.2,<0.21.0)", "tree-sitter-languages (>=1.8.0,<2.0.0)", "upstash-redis (>=0.15.0,<0.16.0)", "vdms (>=0.0.20,<0.0.21)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)", "zhipuai (>=1.0.7,<2.0.0)"] [[package]] name = "langchain-core" -version = "0.1.36" +version = "0.1.40" description = "Building applications with LLMs through composability" optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain_core-0.1.36-py3-none-any.whl", hash = "sha256:564beeb18ab13deca8daf6e6e74acab52e0b8f6202110262a4c914e4450febd2"}, - {file = "langchain_core-0.1.36.tar.gz", hash = "sha256:aa2432370ca3d2a5d6dd14a810aa6488bf2f622ff7a0a3dc30f6e0ed9d7f5fa8"}, + {file = "langchain_core-0.1.40-py3-none-any.whl", hash = "sha256:618dbb7ab44d8b263b91e384db1ff07d0db256ae5bdafa0123a115b6a75a13f1"}, + {file = "langchain_core-0.1.40.tar.gz", hash = "sha256:34c06fc0e6d3534b738c63f85403446b4be71161665b7e091f9bb19c914ec100"}, ] [package.dependencies] @@ -3575,7 +3829,6 @@ langsmith = ">=0.1.0,<0.2.0" packaging = ">=23.2,<24.0" pydantic = ">=1,<3" PyYAML = ">=5.3" -requests = ">=2,<3" tenacity = ">=8.1.0,<9.0.0" [package.extras] @@ -3583,35 +3836,35 @@ extended-testing = ["jinja2 (>=3,<4)"] [[package]] name = "langchain-experimental" -version = "0.0.55" +version = "0.0.56" description = "Building applications with LLMs through composability" optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain_experimental-0.0.55-py3-none-any.whl", hash = "sha256:1b6b47689a4d21f81fac5ce3e968914bf7cafb70a14695404a0a67585114e09f"}, - {file = "langchain_experimental-0.0.55.tar.gz", hash = "sha256:8338a5e31b3dce8b072ddbdc1dda7765d864505478923e98681a93ae2555c237"}, + {file = "langchain_experimental-0.0.56-py3-none-any.whl", hash = "sha256:91fd7a723b0ef3193a63726745523efdd5dd7134116d838c312cfdbf4b354298"}, + {file = "langchain_experimental-0.0.56.tar.gz", hash = "sha256:ebb1c34815739d3af50c9b709c57b91d0357d567ad2042acb724853c6ba1d735"}, ] [package.dependencies] -langchain = ">=0.1.13,<0.2.0" -langchain-core = ">=0.1.33,<0.2.0" +langchain = ">=0.1.14,<0.2.0" +langchain-core = ">=0.1.37,<0.2.0" [package.extras] extended-testing = ["faker (>=19.3.1,<20.0.0)", "jinja2 (>=3,<4)", "pandas (>=2.0.1,<3.0.0)", "presidio-analyzer (>=2.2.352,<3.0.0)", "presidio-anonymizer (>=2.2.352,<3.0.0)", "sentence-transformers (>=2,<3)", "tabulate (>=0.9.0,<0.10.0)", "vowpal-wabbit-next (==0.6.0)"] [[package]] name = "langchain-google-genai" -version = "0.0.6" +version = "1.0.1" description = "An integration package connecting Google's genai package and LangChain" optional = false -python-versions = ">=3.9,<4.0" +python-versions = "<4.0,>=3.9" files = [ - {file = "langchain_google_genai-0.0.6-py3-none-any.whl", hash = "sha256:2e347ad4d18f8f761ed8d3997f9ea52b41f97b7fd81f698612ad718da5d9c13b"}, - {file = "langchain_google_genai-0.0.6.tar.gz", hash = "sha256:93156a523306031d4bbfa7c759778a1123779902512f8ef329516da558069d70"}, + {file = "langchain_google_genai-1.0.1-py3-none-any.whl", hash = "sha256:c59e7f49b3afb3d6d25366f83d47319e6825c8f0a9b95f4a591687dcb18862c0"}, + {file = "langchain_google_genai-1.0.1.tar.gz", hash = "sha256:43b80ed2fbae3495381a4ed9d3978067c467fd5e5cf123aeaed79a9998b6e54a"}, ] [package.dependencies] -google-generativeai = ">=0.3.1,<0.4.0" +google-generativeai = ">=0.4.1,<0.5.0" langchain-core = ">=0.1,<0.2" [package.extras] @@ -3619,20 +3872,20 @@ images = ["pillow (>=10.1.0,<11.0.0)"] [[package]] name = "langchain-openai" -version = "0.0.6" +version = "0.0.5" description = "An integration package connecting OpenAI and LangChain" optional = false python-versions = ">=3.8.1,<4.0" files = [ - {file = "langchain_openai-0.0.6-py3-none-any.whl", hash = "sha256:2ef040e4447a26a9d3bd45dfac9cefa00797ea58555a3d91ab4f88699eb3a005"}, - {file = "langchain_openai-0.0.6.tar.gz", hash = "sha256:f5c4ebe46f2c8635c8f0c26cc8df27700aacafea025410e418d5a080039974dd"}, + {file = "langchain_openai-0.0.5-py3-none-any.whl", hash = "sha256:93b37dfac274adad65e46d5d6e71411e00c6984bcc5e10f1d6bb58e7944dc01b"}, + {file = "langchain_openai-0.0.5.tar.gz", hash = "sha256:f317fee5b652949ad96ad7edf8ef7a044a6a3f0cc71d1e12f9d5261789fd68c4"}, ] [package.dependencies] langchain-core = ">=0.1.16,<0.2" numpy = ">=1,<2" openai = ">=1.10.0,<2.0.0" -tiktoken = ">=0.5.2,<1" +tiktoken = ">=0.5.2,<0.6.0" [[package]] name = "langchain-text-splitters" @@ -3665,15 +3918,68 @@ files = [ [package.dependencies] six = "*" +[[package]] +name = "langflow-base" +version = "0.0.17" +description = "A Python package with a built-in web application" +optional = false +python-versions = ">=3.10,<3.12" +files = [] +develop = true + +[package.dependencies] +alembic = "^1.13.0" +bcrypt = "4.0.1" +cachetools = "^5.3.1" +chromadb = "^0.4.24" +docstring-parser = "^0.15" +duckdb = "^0.9.2" +fastapi = "^0.109.0" +gunicorn = "^21.2.0" +httpx = "*" +jq = {version = "^1.7.0", markers = "sys_platform != \"win32\""} +langchain = "~0.1.0" +langchain-anthropic = "^0.1.4" +langchain-astradb = "^0.1.0" +langchain-experimental = "*" +loguru = "^0.7.1" +multiprocess = "^0.70.14" +orjson = "3.9.15" +pandas = "2.2.0" +passlib = "^1.7.4" +pillow = "^10.2.0" +platformdirs = "^4.2.0" +pydantic = "^2.5.0" +pydantic-settings = "^2.1.0" +pypdf = "^4.1.0" +python-docx = "^1.1.0" +python-jose = "^3.3.0" +python-multipart = "^0.0.7" +python-socketio = "^5.11.0" +rich = "^13.7.0" +sqlmodel = "^0.0.14" +typer = "^0.9.0" +uvicorn = "^0.27.0" +websockets = "*" + +[package.extras] +all = [] +deploy = [] +local = [] + +[package.source] +type = "directory" +url = "src/backend/base" + [[package]] name = "langfuse" -version = "2.21.1" +version = "2.21.2" description = "A client library for accessing langfuse" optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langfuse-2.21.1-py3-none-any.whl", hash = "sha256:5ef286823a4c9903e2120ad2bf0169a929d41789702535abc713e66a0d270f05"}, - {file = "langfuse-2.21.1.tar.gz", hash = "sha256:36494ea016784ac339a1a5375b88c33484e81668433956ead442d7a93c217078"}, + {file = "langfuse-2.21.2-py3-none-any.whl", hash = "sha256:bd65858e6326776f65c9b2e414e64fdea0f14402f5c784952af93346dfd489bb"}, + {file = "langfuse-2.21.2.tar.gz", hash = "sha256:eb7911aa640f020f097cb56eaa7d67f01d39f9e2bdd6226e0c5d642a87f3663c"}, ] [package.dependencies] @@ -3686,18 +3992,18 @@ wrapt = ">=1.14,<2.0" [package.extras] langchain = ["langchain (>=0.0.309)"] -llama-index = ["llama-index (>=0.10.12,<0.11.0)"] +llama-index = ["llama-index (>=0.10.12,<2.0.0)"] openai = ["openai (>=0.27.8)"] [[package]] name = "langsmith" -version = "0.1.37" +version = "0.1.39" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." optional = false python-versions = "<4.0,>=3.8.1" files = [ - {file = "langsmith-0.1.37-py3-none-any.whl", hash = "sha256:2ea0375eb76d95b1cd32f57fc27a5c9c529443fbe816c0c0671d7e25e432ea37"}, - {file = "langsmith-0.1.37.tar.gz", hash = "sha256:d410491b6ff6e1f07aeb1d33fb19784f544eed5fb549b514c793ab19d8fb4b60"}, + {file = "langsmith-0.1.39-py3-none-any.whl", hash = "sha256:85c19177162585728001cb7ae91ab48ca4abe39b7bc1ff783212ac426ded222b"}, + {file = "langsmith-0.1.39.tar.gz", hash = "sha256:2aec9d2f9cc664042d2121b13da569b0902aff842c86b17b440245d57da84ec5"}, ] [package.dependencies] @@ -3722,14 +4028,40 @@ interegular = ["interegular (>=0.3.1,<0.4.0)"] nearley = ["js2py"] regex = ["regex"] +[[package]] +name = "litellm" +version = "1.34.22" +description = "Library to easily interface with LLM API providers" +optional = false +python-versions = "!=2.7.*,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,!=3.7.*,>=3.8" +files = [ + {file = "litellm-1.34.22-py3-none-any.whl", hash = "sha256:0e573d56d762f4060c53493da4a08c48034b5bb5ba22e34517065739adfd9154"}, + {file = "litellm-1.34.22.tar.gz", hash = "sha256:ca50ede3ca8d3f9dc2765ca13cf2ff5c4e4b9afb4db222f9d7cb9ee838b6180f"}, +] + +[package.dependencies] +aiohttp = "*" +click = "*" +importlib-metadata = ">=6.8.0" +jinja2 = ">=3.1.2,<4.0.0" +openai = ">=1.0.0" +python-dotenv = ">=0.2.0" +requests = ">=2.31.0,<3.0.0" +tiktoken = ">=0.4.0" +tokenizers = "*" + +[package.extras] +extra-proxy = ["azure-identity (>=1.15.0,<2.0.0)", "azure-keyvault-secrets (>=4.8.0,<5.0.0)", "google-cloud-kms (>=2.21.3,<3.0.0)", "prisma (==0.11.0)", "resend (>=0.8.0,<0.9.0)"] +proxy = ["PyJWT (>=2.8.0,<3.0.0)", "apscheduler (>=3.10.4,<4.0.0)", "backoff", "cryptography (>=42.0.5,<43.0.0)", "fastapi (>=0.109.1,<0.110.0)", "fastapi-sso (>=0.10.0,<0.11.0)", "gunicorn (>=21.2.0,<22.0.0)", "orjson (>=3.9.7,<4.0.0)", "python-multipart (>=0.0.9,<0.0.10)", "pyyaml (>=6.0.1,<7.0.0)", "rq", "uvicorn (>=0.22.0,<0.23.0)"] + [[package]] name = "llama-cpp-python" -version = "0.2.57" +version = "0.2.59" description = "Python bindings for the llama.cpp library" optional = true python-versions = ">=3.8" files = [ - {file = "llama_cpp_python-0.2.57.tar.gz", hash = "sha256:bd81dbc4bc03b7deca3be0496330705d4c53bba726f7c3a47d556c7ec2452304"}, + {file = "llama_cpp_python-0.2.59.tar.gz", hash = "sha256:4b19283226ab91c74c6d811d88724a6f32d9dd7d07caf9d8b897dd3372d5d4d2"}, ] [package.dependencies] @@ -3746,13 +4078,143 @@ test = ["httpx (>=0.24.1)", "pytest (>=7.4.0)", "scipy (>=1.10)"] [[package]] name = "llama-index" +version = "0.10.26" +description = "Interface between LLMs and your data" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "llama_index-0.10.26-py3-none-any.whl", hash = "sha256:25a3f8c9f63fbdaaf3d760ce59c5dad8afc5cf40431e9e6a28e02b92a820d450"}, + {file = "llama_index-0.10.26.tar.gz", hash = "sha256:5a6036bcb2449277ede3244cfa1b49d9fab5dba30ad8b212c2df92449cfa7d48"}, +] + +[package.dependencies] +llama-index-agent-openai = ">=0.1.4,<0.3.0" +llama-index-cli = ">=0.1.2,<0.2.0" +llama-index-core = ">=0.10.26,<0.11.0" +llama-index-embeddings-openai = ">=0.1.5,<0.2.0" +llama-index-indices-managed-llama-cloud = ">=0.1.2,<0.2.0" +llama-index-legacy = ">=0.9.48,<0.10.0" +llama-index-llms-openai = ">=0.1.13,<0.2.0" +llama-index-multi-modal-llms-openai = ">=0.1.3,<0.2.0" +llama-index-program-openai = ">=0.1.3,<0.2.0" +llama-index-question-gen-openai = ">=0.1.2,<0.2.0" +llama-index-readers-file = ">=0.1.4,<0.2.0" +llama-index-readers-llama-parse = ">=0.1.2,<0.2.0" + +[[package]] +name = "llama-index-agent-openai" +version = "0.2.2" +description = "llama-index agent openai integration" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "llama_index_agent_openai-0.2.2-py3-none-any.whl", hash = "sha256:fa8cbc2c7be5a465848f8d5b432db01c55f07dfa06357edb7fb77fb17d534d1e"}, + {file = "llama_index_agent_openai-0.2.2.tar.gz", hash = "sha256:12063dd932c74015796f973986cc52d783f51fda38e4ead72a56d0fd195925ee"}, +] + +[package.dependencies] +llama-index-core = ">=0.10.1,<0.11.0" +llama-index-llms-openai = ">=0.1.5,<0.2.0" +openai = ">=1.14.0" + +[[package]] +name = "llama-index-cli" +version = "0.1.11" +description = "llama-index cli" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "llama_index_cli-0.1.11-py3-none-any.whl", hash = "sha256:44bc32af6d9bc0b523ad284f24fa1ec17288491243fe6d7c7b4770b3245dbb84"}, + {file = "llama_index_cli-0.1.11.tar.gz", hash = "sha256:5de707e125aa877d70c61da70cc44fea72a9f7adb77f413b51f73b1deffdd750"}, +] + +[package.dependencies] +llama-index-core = ">=0.10.11.post1,<0.11.0" +llama-index-embeddings-openai = ">=0.1.1,<0.2.0" +llama-index-llms-openai = ">=0.1.1,<0.2.0" + +[[package]] +name = "llama-index-core" +version = "0.10.26" +description = "Interface between LLMs and your data" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "llama_index_core-0.10.26-py3-none-any.whl", hash = "sha256:e08886b9d353fb45f63d0011e78326627f1ee5c7761585fdd85a9a0dfdbf0365"}, + {file = "llama_index_core-0.10.26.tar.gz", hash = "sha256:8ea27093a053aed79b7b5d80694152066ddaa5b70116308d48db382c76367a87"}, +] + +[package.dependencies] +aiohttp = ">=3.8.6,<4.0.0" +dataclasses-json = "*" +deprecated = ">=1.2.9.3" +dirtyjson = ">=1.0.8,<2.0.0" +fsspec = ">=2023.5.0" +httpx = "*" +llamaindex-py-client = ">=0.1.15,<0.2.0" +nest-asyncio = ">=1.5.8,<2.0.0" +networkx = ">=3.0" +nltk = ">=3.8.1,<4.0.0" +numpy = "*" +openai = ">=1.1.0" +pandas = "*" +pillow = ">=9.0.0" +PyYAML = ">=6.0.1" +requests = ">=2.31.0" +SQLAlchemy = {version = ">=1.4.49", extras = ["asyncio"]} +tenacity = ">=8.2.0,<9.0.0" +tiktoken = ">=0.3.3" +tqdm = ">=4.66.1,<5.0.0" +typing-extensions = ">=4.5.0" +typing-inspect = ">=0.8.0" +wrapt = "*" + +[package.extras] +gradientai = ["gradientai (>=1.4.0)"] +html = ["beautifulsoup4 (>=4.12.2,<5.0.0)"] +langchain = ["langchain (>=0.0.303)"] +local-models = ["optimum[onnxruntime] (>=1.13.2,<2.0.0)", "sentencepiece (>=0.1.99,<0.2.0)", "transformers[torch] (>=4.33.1,<5.0.0)"] +postgres = ["asyncpg (>=0.29.0,<0.30.0)", "pgvector (>=0.2.4,<0.3.0)", "psycopg2-binary (>=2.9.9,<3.0.0)"] +query-tools = ["guidance (>=0.0.64,<0.0.65)", "jsonpath-ng (>=1.6.0,<2.0.0)", "lm-format-enforcer (>=0.4.3,<0.5.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "scikit-learn", "spacy (>=3.7.1,<4.0.0)"] + +[[package]] +name = "llama-index-embeddings-openai" +version = "0.1.7" +description = "llama-index embeddings openai integration" +optional = false +python-versions = ">=3.8.1,<4.0" +files = [ + {file = "llama_index_embeddings_openai-0.1.7-py3-none-any.whl", hash = "sha256:6023925ed1487b0688323d21711efbf8880e82ed3b87ef413255c3dc63a2f2fe"}, + {file = "llama_index_embeddings_openai-0.1.7.tar.gz", hash = "sha256:c71cc9820680c4cedfc9845dc87b94f6851d1ccce1e486fc91298f8fa8d9f27d"}, +] + +[package.dependencies] +llama-index-core = ">=0.10.1,<0.11.0" + +[[package]] +name = "llama-index-indices-managed-llama-cloud" +version = "0.1.5" +description = "llama-index indices llama-cloud integration" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "llama_index_indices_managed_llama_cloud-0.1.5-py3-none-any.whl", hash = "sha256:79f636cb6f4fabb12fec153564110f7f4dfda3cacb087793a5fec988484d7d2c"}, + {file = "llama_index_indices_managed_llama_cloud-0.1.5.tar.gz", hash = "sha256:47cdde9f06bbddd508f0efcf41de425e85171ac2c8fda8a5fb2a89673e1c8c71"}, +] + +[package.dependencies] +llama-index-core = ">=0.10.0,<0.11.0" +llamaindex-py-client = ">=0.1.13,<0.2.0" + +[[package]] +name = "llama-index-legacy" version = "0.9.48" description = "Interface between LLMs and your data" optional = false python-versions = ">=3.8.1,<4.0" files = [ - {file = "llama_index-0.9.48-py3-none-any.whl", hash = "sha256:56aa406d39e7ca53a5d990b55d69901fbb9eddc9af6a40950367dc5d734f6283"}, - {file = "llama_index-0.9.48.tar.gz", hash = "sha256:c50d02ac8c7e4ff9fb41f0860391fe0020ad8a3d7c30048db52d17d8be654bf3"}, + {file = "llama_index_legacy-0.9.48-py3-none-any.whl", hash = "sha256:714ada95beac179b4acefa4d2deff74bb7b2f22b0f699ac247d4cb67738d16d4"}, + {file = "llama_index_legacy-0.9.48.tar.gz", hash = "sha256:82ddc4691edbf49533d65582c249ba22c03fe96fbd3e92f7758dccef28e43834"}, ] [package.dependencies] @@ -3783,6 +4245,129 @@ local-models = ["optimum[onnxruntime] (>=1.13.2,<2.0.0)", "sentencepiece (>=0.1. postgres = ["asyncpg (>=0.28.0,<0.29.0)", "pgvector (>=0.1.0,<0.2.0)", "psycopg2-binary (>=2.9.9,<3.0.0)"] query-tools = ["guidance (>=0.0.64,<0.0.65)", "jsonpath-ng (>=1.6.0,<2.0.0)", "lm-format-enforcer (>=0.4.3,<0.5.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "scikit-learn", "spacy (>=3.7.1,<4.0.0)"] +[[package]] +name = "llama-index-llms-openai" +version = "0.1.14" +description = "llama-index llms openai integration" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "llama_index_llms_openai-0.1.14-py3-none-any.whl", hash = "sha256:13cec467962a6ccb9e63451c7febe8e9c2ed536bd6b1058239c2b4fd86776060"}, + {file = "llama_index_llms_openai-0.1.14.tar.gz", hash = "sha256:7eba66882ae84fa42b188941234b84267c48e449ef214f511756dcad3f9f0b62"}, +] + +[package.dependencies] +llama-index-core = ">=0.10.24,<0.11.0" + +[[package]] +name = "llama-index-multi-modal-llms-openai" +version = "0.1.4" +description = "llama-index multi-modal-llms openai integration" +optional = false +python-versions = ">=3.8.1,<4.0" +files = [ + {file = "llama_index_multi_modal_llms_openai-0.1.4-py3-none-any.whl", hash = "sha256:03b887d110551d5d5b99b9fd110824e6311f2e31f4d5e67dafd2ee66da32818d"}, + {file = "llama_index_multi_modal_llms_openai-0.1.4.tar.gz", hash = "sha256:6a5d6584c33a9d1b06cf5c874c63af2603fc93b660bde481a8c547e876c6e2c3"}, +] + +[package.dependencies] +llama-index-core = ">=0.10.1,<0.11.0" +llama-index-llms-openai = ">=0.1.1,<0.2.0" + +[[package]] +name = "llama-index-program-openai" +version = "0.1.5" +description = "llama-index program openai integration" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "llama_index_program_openai-0.1.5-py3-none-any.whl", hash = "sha256:20b6efa706ac73e4dc5086900fea1ffcb1eb0787c8a6f081669d37da7235aee0"}, + {file = "llama_index_program_openai-0.1.5.tar.gz", hash = "sha256:c33aa2d2876ad0ff1f9a2a755d4e7d4917240847d0174e7b2d0b8474499bb700"}, +] + +[package.dependencies] +llama-index-agent-openai = ">=0.1.1,<0.3.0" +llama-index-core = ">=0.10.1,<0.11.0" +llama-index-llms-openai = ">=0.1.1,<0.2.0" + +[[package]] +name = "llama-index-question-gen-openai" +version = "0.1.3" +description = "llama-index question_gen openai integration" +optional = false +python-versions = ">=3.8.1,<4.0" +files = [ + {file = "llama_index_question_gen_openai-0.1.3-py3-none-any.whl", hash = "sha256:1f83b49e8b2e665030d1ec8c54687d6985d9fa8426147b64e46628a9e489b302"}, + {file = "llama_index_question_gen_openai-0.1.3.tar.gz", hash = "sha256:4486198117a45457d2e036ae60b93af58052893cc7d78fa9b6f47dd47b81e2e1"}, +] + +[package.dependencies] +llama-index-core = ">=0.10.1,<0.11.0" +llama-index-llms-openai = ">=0.1.1,<0.2.0" +llama-index-program-openai = ">=0.1.1,<0.2.0" + +[[package]] +name = "llama-index-readers-file" +version = "0.1.13" +description = "llama-index readers file integration" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "llama_index_readers_file-0.1.13-py3-none-any.whl", hash = "sha256:692988b8c3ca2807d21a171351078b634ada2ff1682ebe4a484f82da384dfc55"}, + {file = "llama_index_readers_file-0.1.13.tar.gz", hash = "sha256:830f06ec7b34437fc3bb5f268d235c5c7640296adb148d8f92277dceb7f0846d"}, +] + +[package.dependencies] +beautifulsoup4 = ">=4.12.3,<5.0.0" +llama-index-core = ">=0.10.1,<0.11.0" +pymupdf = ">=1.23.21,<2.0.0" +pypdf = ">=4.0.1,<5.0.0" +striprtf = ">=0.0.26,<0.0.27" + +[[package]] +name = "llama-index-readers-llama-parse" +version = "0.1.4" +description = "llama-index readers llama-parse integration" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "llama_index_readers_llama_parse-0.1.4-py3-none-any.whl", hash = "sha256:c4914b37d12cceee56fbd185cca80f87d60acbf8ea7a73f9719610180be1fcdd"}, + {file = "llama_index_readers_llama_parse-0.1.4.tar.gz", hash = "sha256:78608b193c818894aefeee0aa303f02b7f80f2e4caf13866c2fd3b0b1023e2c0"}, +] + +[package.dependencies] +llama-index-core = ">=0.10.7,<0.11.0" +llama-parse = ">=0.4.0,<0.5.0" + +[[package]] +name = "llama-parse" +version = "0.4.0" +description = "Parse files into RAG-Optimized formats." +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "llama_parse-0.4.0-py3-none-any.whl", hash = "sha256:52b450c9bb94746c5f86867f54fd2e74670d89b385dcb879eb93490a42fda628"}, + {file = "llama_parse-0.4.0.tar.gz", hash = "sha256:ee521e9422db48dbdf00303cb6e90f1066131960b5ca4e14f5b5a6db6b7917e2"}, +] + +[package.dependencies] +llama-index-core = ">=0.10.7" + +[[package]] +name = "llamaindex-py-client" +version = "0.1.16" +description = "" +optional = false +python-versions = "<4.0,>=3.8" +files = [ + {file = "llamaindex_py_client-0.1.16-py3-none-any.whl", hash = "sha256:b34e0a14984468f46ff5eebfe4b2b88598a24ff9459338a5621eee78e58bf0db"}, + {file = "llamaindex_py_client-0.1.16.tar.gz", hash = "sha256:e99bbc0855e6caaa75eba219cdb3cf6c943ae94fa15ccbb68a3a08d452fd6380"}, +] + +[package.dependencies] +httpx = ">=0.20.0" +pydantic = ">=1.10" + [[package]] name = "locust" version = "2.24.1" @@ -3830,111 +4415,173 @@ dev = ["Sphinx (==7.2.5)", "colorama (==0.4.5)", "colorama (==0.4.6)", "exceptio [[package]] name = "lxml" -version = "4.9.4" +version = "5.2.1" description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*" +python-versions = ">=3.6" files = [ - {file = "lxml-4.9.4-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e214025e23db238805a600f1f37bf9f9a15413c7bf5f9d6ae194f84980c78722"}, - {file = "lxml-4.9.4-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:ec53a09aee61d45e7dbe7e91252ff0491b6b5fee3d85b2d45b173d8ab453efc1"}, - {file = "lxml-4.9.4-cp27-cp27m-win32.whl", hash = "sha256:7d1d6c9e74c70ddf524e3c09d9dc0522aba9370708c2cb58680ea40174800013"}, - {file = "lxml-4.9.4-cp27-cp27m-win_amd64.whl", hash = "sha256:cb53669442895763e61df5c995f0e8361b61662f26c1b04ee82899c2789c8f69"}, - {file = "lxml-4.9.4-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:647bfe88b1997d7ae8d45dabc7c868d8cb0c8412a6e730a7651050b8c7289cf2"}, - {file = "lxml-4.9.4-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:4d973729ce04784906a19108054e1fd476bc85279a403ea1a72fdb051c76fa48"}, - {file = "lxml-4.9.4-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:056a17eaaf3da87a05523472ae84246f87ac2f29a53306466c22e60282e54ff8"}, - {file = "lxml-4.9.4-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:aaa5c173a26960fe67daa69aa93d6d6a1cd714a6eb13802d4e4bd1d24a530644"}, - {file = "lxml-4.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:647459b23594f370c1c01768edaa0ba0959afc39caeeb793b43158bb9bb6a663"}, - {file = "lxml-4.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:bdd9abccd0927673cffe601d2c6cdad1c9321bf3437a2f507d6b037ef91ea307"}, - {file = "lxml-4.9.4-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:00e91573183ad273e242db5585b52670eddf92bacad095ce25c1e682da14ed91"}, - {file = "lxml-4.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a602ed9bd2c7d85bd58592c28e101bd9ff9c718fbde06545a70945ffd5d11868"}, - {file = "lxml-4.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:de362ac8bc962408ad8fae28f3967ce1a262b5d63ab8cefb42662566737f1dc7"}, - {file = "lxml-4.9.4-cp310-cp310-win32.whl", hash = "sha256:33714fcf5af4ff7e70a49731a7cc8fd9ce910b9ac194f66eaa18c3cc0a4c02be"}, - {file = "lxml-4.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:d3caa09e613ece43ac292fbed513a4bce170681a447d25ffcbc1b647d45a39c5"}, - {file = "lxml-4.9.4-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:359a8b09d712df27849e0bcb62c6a3404e780b274b0b7e4c39a88826d1926c28"}, - {file = "lxml-4.9.4-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:43498ea734ccdfb92e1886dfedaebeb81178a241d39a79d5351ba2b671bff2b2"}, - {file = "lxml-4.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:4855161013dfb2b762e02b3f4d4a21cc7c6aec13c69e3bffbf5022b3e708dd97"}, - {file = "lxml-4.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:c71b5b860c5215fdbaa56f715bc218e45a98477f816b46cfde4a84d25b13274e"}, - {file = "lxml-4.9.4-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:9a2b5915c333e4364367140443b59f09feae42184459b913f0f41b9fed55794a"}, - {file = "lxml-4.9.4-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:d82411dbf4d3127b6cde7da0f9373e37ad3a43e89ef374965465928f01c2b979"}, - {file = "lxml-4.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:273473d34462ae6e97c0f4e517bd1bf9588aa67a1d47d93f760a1282640e24ac"}, - {file = "lxml-4.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:389d2b2e543b27962990ab529ac6720c3dded588cc6d0f6557eec153305a3622"}, - {file = "lxml-4.9.4-cp311-cp311-win32.whl", hash = "sha256:8aecb5a7f6f7f8fe9cac0bcadd39efaca8bbf8d1bf242e9f175cbe4c925116c3"}, - {file = "lxml-4.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:c7721a3ef41591341388bb2265395ce522aba52f969d33dacd822da8f018aff8"}, - {file = "lxml-4.9.4-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:dbcb2dc07308453db428a95a4d03259bd8caea97d7f0776842299f2d00c72fc8"}, - {file = "lxml-4.9.4-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:01bf1df1db327e748dcb152d17389cf6d0a8c5d533ef9bab781e9d5037619229"}, - {file = "lxml-4.9.4-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:e8f9f93a23634cfafbad6e46ad7d09e0f4a25a2400e4a64b1b7b7c0fbaa06d9d"}, - {file = "lxml-4.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3f3f00a9061605725df1816f5713d10cd94636347ed651abdbc75828df302b20"}, - {file = "lxml-4.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:953dd5481bd6252bd480d6ec431f61d7d87fdcbbb71b0d2bdcfc6ae00bb6fb10"}, - {file = "lxml-4.9.4-cp312-cp312-win32.whl", hash = "sha256:266f655d1baff9c47b52f529b5f6bec33f66042f65f7c56adde3fcf2ed62ae8b"}, - {file = "lxml-4.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:f1faee2a831fe249e1bae9cbc68d3cd8a30f7e37851deee4d7962b17c410dd56"}, - {file = "lxml-4.9.4-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:23d891e5bdc12e2e506e7d225d6aa929e0a0368c9916c1fddefab88166e98b20"}, - {file = "lxml-4.9.4-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e96a1788f24d03e8d61679f9881a883ecdf9c445a38f9ae3f3f193ab6c591c66"}, - {file = "lxml-4.9.4-cp36-cp36m-macosx_11_0_x86_64.whl", hash = "sha256:5557461f83bb7cc718bc9ee1f7156d50e31747e5b38d79cf40f79ab1447afd2d"}, - {file = "lxml-4.9.4-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:fdb325b7fba1e2c40b9b1db407f85642e32404131c08480dd652110fc908561b"}, - {file = "lxml-4.9.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d74d4a3c4b8f7a1f676cedf8e84bcc57705a6d7925e6daef7a1e54ae543a197"}, - {file = "lxml-4.9.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:ac7674d1638df129d9cb4503d20ffc3922bd463c865ef3cb412f2c926108e9a4"}, - {file = "lxml-4.9.4-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:ddd92e18b783aeb86ad2132d84a4b795fc5ec612e3545c1b687e7747e66e2b53"}, - {file = "lxml-4.9.4-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2bd9ac6e44f2db368ef8986f3989a4cad3de4cd55dbdda536e253000c801bcc7"}, - {file = "lxml-4.9.4-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:bc354b1393dce46026ab13075f77b30e40b61b1a53e852e99d3cc5dd1af4bc85"}, - {file = "lxml-4.9.4-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:f836f39678cb47c9541f04d8ed4545719dc31ad850bf1832d6b4171e30d65d23"}, - {file = "lxml-4.9.4-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:9c131447768ed7bc05a02553d939e7f0e807e533441901dd504e217b76307745"}, - {file = "lxml-4.9.4-cp36-cp36m-win32.whl", hash = "sha256:bafa65e3acae612a7799ada439bd202403414ebe23f52e5b17f6ffc2eb98c2be"}, - {file = "lxml-4.9.4-cp36-cp36m-win_amd64.whl", hash = "sha256:6197c3f3c0b960ad033b9b7d611db11285bb461fc6b802c1dd50d04ad715c225"}, - {file = "lxml-4.9.4-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:7b378847a09d6bd46047f5f3599cdc64fcb4cc5a5a2dd0a2af610361fbe77b16"}, - {file = "lxml-4.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:1343df4e2e6e51182aad12162b23b0a4b3fd77f17527a78c53f0f23573663545"}, - {file = "lxml-4.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:6dbdacf5752fbd78ccdb434698230c4f0f95df7dd956d5f205b5ed6911a1367c"}, - {file = "lxml-4.9.4-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:506becdf2ecaebaf7f7995f776394fcc8bd8a78022772de66677c84fb02dd33d"}, - {file = "lxml-4.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ca8e44b5ba3edb682ea4e6185b49661fc22b230cf811b9c13963c9f982d1d964"}, - {file = "lxml-4.9.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:9d9d5726474cbbef279fd709008f91a49c4f758bec9c062dfbba88eab00e3ff9"}, - {file = "lxml-4.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:bbdd69e20fe2943b51e2841fc1e6a3c1de460d630f65bde12452d8c97209464d"}, - {file = "lxml-4.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8671622256a0859f5089cbe0ce4693c2af407bc053dcc99aadff7f5310b4aa02"}, - {file = "lxml-4.9.4-cp37-cp37m-win32.whl", hash = "sha256:dd4fda67f5faaef4f9ee5383435048ee3e11ad996901225ad7615bc92245bc8e"}, - {file = "lxml-4.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6bee9c2e501d835f91460b2c904bc359f8433e96799f5c2ff20feebd9bb1e590"}, - {file = "lxml-4.9.4-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:1f10f250430a4caf84115b1e0f23f3615566ca2369d1962f82bef40dd99cd81a"}, - {file = "lxml-4.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:3b505f2bbff50d261176e67be24e8909e54b5d9d08b12d4946344066d66b3e43"}, - {file = "lxml-4.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:1449f9451cd53e0fd0a7ec2ff5ede4686add13ac7a7bfa6988ff6d75cff3ebe2"}, - {file = "lxml-4.9.4-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:4ece9cca4cd1c8ba889bfa67eae7f21d0d1a2e715b4d5045395113361e8c533d"}, - {file = "lxml-4.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:59bb5979f9941c61e907ee571732219fa4774d5a18f3fa5ff2df963f5dfaa6bc"}, - {file = "lxml-4.9.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b1980dbcaad634fe78e710c8587383e6e3f61dbe146bcbfd13a9c8ab2d7b1192"}, - {file = "lxml-4.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9ae6c3363261021144121427b1552b29e7b59de9d6a75bf51e03bc072efb3c37"}, - {file = "lxml-4.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bcee502c649fa6351b44bb014b98c09cb00982a475a1912a9881ca28ab4f9cd9"}, - {file = "lxml-4.9.4-cp38-cp38-win32.whl", hash = "sha256:a8edae5253efa75c2fc79a90068fe540b197d1c7ab5803b800fccfe240eed33c"}, - {file = "lxml-4.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:701847a7aaefef121c5c0d855b2affa5f9bd45196ef00266724a80e439220e46"}, - {file = "lxml-4.9.4-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:f610d980e3fccf4394ab3806de6065682982f3d27c12d4ce3ee46a8183d64a6a"}, - {file = "lxml-4.9.4-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:aa9b5abd07f71b081a33115d9758ef6077924082055005808f68feccb27616bd"}, - {file = "lxml-4.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:365005e8b0718ea6d64b374423e870648ab47c3a905356ab6e5a5ff03962b9a9"}, - {file = "lxml-4.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:16b9ec51cc2feab009e800f2c6327338d6ee4e752c76e95a35c4465e80390ccd"}, - {file = "lxml-4.9.4-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:a905affe76f1802edcac554e3ccf68188bea16546071d7583fb1b693f9cf756b"}, - {file = "lxml-4.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fd814847901df6e8de13ce69b84c31fc9b3fb591224d6762d0b256d510cbf382"}, - {file = "lxml-4.9.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:91bbf398ac8bb7d65a5a52127407c05f75a18d7015a270fdd94bbcb04e65d573"}, - {file = "lxml-4.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f99768232f036b4776ce419d3244a04fe83784bce871b16d2c2e984c7fcea847"}, - {file = "lxml-4.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bb5bd6212eb0edfd1e8f254585290ea1dadc3687dd8fd5e2fd9a87c31915cdab"}, - {file = "lxml-4.9.4-cp39-cp39-win32.whl", hash = "sha256:88f7c383071981c74ec1998ba9b437659e4fd02a3c4a4d3efc16774eb108d0ec"}, - {file = "lxml-4.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:936e8880cc00f839aa4173f94466a8406a96ddce814651075f95837316369899"}, - {file = "lxml-4.9.4-pp310-pypy310_pp73-macosx_11_0_x86_64.whl", hash = "sha256:f6c35b2f87c004270fa2e703b872fcc984d714d430b305145c39d53074e1ffe0"}, - {file = "lxml-4.9.4-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:606d445feeb0856c2b424405236a01c71af7c97e5fe42fbc778634faef2b47e4"}, - {file = "lxml-4.9.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a1bdcbebd4e13446a14de4dd1825f1e778e099f17f79718b4aeaf2403624b0f7"}, - {file = "lxml-4.9.4-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:0a08c89b23117049ba171bf51d2f9c5f3abf507d65d016d6e0fa2f37e18c0fc5"}, - {file = "lxml-4.9.4-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:232fd30903d3123be4c435fb5159938c6225ee8607b635a4d3fca847003134ba"}, - {file = "lxml-4.9.4-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:231142459d32779b209aa4b4d460b175cadd604fed856f25c1571a9d78114771"}, - {file = "lxml-4.9.4-pp38-pypy38_pp73-macosx_11_0_x86_64.whl", hash = "sha256:520486f27f1d4ce9654154b4494cf9307b495527f3a2908ad4cb48e4f7ed7ef7"}, - {file = "lxml-4.9.4-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:562778586949be7e0d7435fcb24aca4810913771f845d99145a6cee64d5b67ca"}, - {file = "lxml-4.9.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a9e7c6d89c77bb2770c9491d988f26a4b161d05c8ca58f63fb1f1b6b9a74be45"}, - {file = "lxml-4.9.4-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:786d6b57026e7e04d184313c1359ac3d68002c33e4b1042ca58c362f1d09ff58"}, - {file = "lxml-4.9.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:95ae6c5a196e2f239150aa4a479967351df7f44800c93e5a975ec726fef005e2"}, - {file = "lxml-4.9.4-pp39-pypy39_pp73-macosx_11_0_x86_64.whl", hash = "sha256:9b556596c49fa1232b0fff4b0e69b9d4083a502e60e404b44341e2f8fb7187f5"}, - {file = "lxml-4.9.4-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:cc02c06e9e320869d7d1bd323df6dd4281e78ac2e7f8526835d3d48c69060683"}, - {file = "lxml-4.9.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:857d6565f9aa3464764c2cb6a2e3c2e75e1970e877c188f4aeae45954a314e0c"}, - {file = "lxml-4.9.4-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c42ae7e010d7d6bc51875d768110c10e8a59494855c3d4c348b068f5fb81fdcd"}, - {file = "lxml-4.9.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f10250bb190fb0742e3e1958dd5c100524c2cc5096c67c8da51233f7448dc137"}, - {file = "lxml-4.9.4.tar.gz", hash = "sha256:b1541e50b78e15fa06a2670157a1962ef06591d4c998b998047fff5e3236880e"}, + {file = "lxml-5.2.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1f7785f4f789fdb522729ae465adcaa099e2a3441519df750ebdccc481d961a1"}, + {file = "lxml-5.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6cc6ee342fb7fa2471bd9b6d6fdfc78925a697bf5c2bcd0a302e98b0d35bfad3"}, + {file = "lxml-5.2.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:794f04eec78f1d0e35d9e0c36cbbb22e42d370dda1609fb03bcd7aeb458c6377"}, + {file = "lxml-5.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c817d420c60a5183953c783b0547d9eb43b7b344a2c46f69513d5952a78cddf3"}, + {file = "lxml-5.2.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2213afee476546a7f37c7a9b4ad4d74b1e112a6fafffc9185d6d21f043128c81"}, + {file = "lxml-5.2.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b070bbe8d3f0f6147689bed981d19bbb33070225373338df755a46893528104a"}, + {file = "lxml-5.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e02c5175f63effbd7c5e590399c118d5db6183bbfe8e0d118bdb5c2d1b48d937"}, + {file = "lxml-5.2.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:3dc773b2861b37b41a6136e0b72a1a44689a9c4c101e0cddb6b854016acc0aa8"}, + {file = "lxml-5.2.1-cp310-cp310-manylinux_2_28_ppc64le.whl", hash = "sha256:d7520db34088c96cc0e0a3ad51a4fd5b401f279ee112aa2b7f8f976d8582606d"}, + {file = "lxml-5.2.1-cp310-cp310-manylinux_2_28_s390x.whl", hash = "sha256:bcbf4af004f98793a95355980764b3d80d47117678118a44a80b721c9913436a"}, + {file = "lxml-5.2.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a2b44bec7adf3e9305ce6cbfa47a4395667e744097faed97abb4728748ba7d47"}, + {file = "lxml-5.2.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:1c5bb205e9212d0ebddf946bc07e73fa245c864a5f90f341d11ce7b0b854475d"}, + {file = "lxml-5.2.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2c9d147f754b1b0e723e6afb7ba1566ecb162fe4ea657f53d2139bbf894d050a"}, + {file = "lxml-5.2.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:3545039fa4779be2df51d6395e91a810f57122290864918b172d5dc7ca5bb433"}, + {file = "lxml-5.2.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a91481dbcddf1736c98a80b122afa0f7296eeb80b72344d7f45dc9f781551f56"}, + {file = "lxml-5.2.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2ddfe41ddc81f29a4c44c8ce239eda5ade4e7fc305fb7311759dd6229a080052"}, + {file = "lxml-5.2.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a7baf9ffc238e4bf401299f50e971a45bfcc10a785522541a6e3179c83eabf0a"}, + {file = "lxml-5.2.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:31e9a882013c2f6bd2f2c974241bf4ba68c85eba943648ce88936d23209a2e01"}, + {file = "lxml-5.2.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0a15438253b34e6362b2dc41475e7f80de76320f335e70c5528b7148cac253a1"}, + {file = "lxml-5.2.1-cp310-cp310-win32.whl", hash = "sha256:6992030d43b916407c9aa52e9673612ff39a575523c5f4cf72cdef75365709a5"}, + {file = "lxml-5.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:da052e7962ea2d5e5ef5bc0355d55007407087392cf465b7ad84ce5f3e25fe0f"}, + {file = "lxml-5.2.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:70ac664a48aa64e5e635ae5566f5227f2ab7f66a3990d67566d9907edcbbf867"}, + {file = "lxml-5.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1ae67b4e737cddc96c99461d2f75d218bdf7a0c3d3ad5604d1f5e7464a2f9ffe"}, + {file = "lxml-5.2.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f18a5a84e16886898e51ab4b1d43acb3083c39b14c8caeb3589aabff0ee0b270"}, + {file = "lxml-5.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6f2c8372b98208ce609c9e1d707f6918cc118fea4e2c754c9f0812c04ca116d"}, + {file = "lxml-5.2.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:394ed3924d7a01b5bd9a0d9d946136e1c2f7b3dc337196d99e61740ed4bc6fe1"}, + {file = "lxml-5.2.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d077bc40a1fe984e1a9931e801e42959a1e6598edc8a3223b061d30fbd26bbc"}, + {file = "lxml-5.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:764b521b75701f60683500d8621841bec41a65eb739b8466000c6fdbc256c240"}, + {file = "lxml-5.2.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:3a6b45da02336895da82b9d472cd274b22dc27a5cea1d4b793874eead23dd14f"}, + {file = "lxml-5.2.1-cp311-cp311-manylinux_2_28_ppc64le.whl", hash = "sha256:5ea7b6766ac2dfe4bcac8b8595107665a18ef01f8c8343f00710b85096d1b53a"}, + {file = "lxml-5.2.1-cp311-cp311-manylinux_2_28_s390x.whl", hash = "sha256:e196a4ff48310ba62e53a8e0f97ca2bca83cdd2fe2934d8b5cb0df0a841b193a"}, + {file = "lxml-5.2.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:200e63525948e325d6a13a76ba2911f927ad399ef64f57898cf7c74e69b71095"}, + {file = "lxml-5.2.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:dae0ed02f6b075426accbf6b2863c3d0a7eacc1b41fb40f2251d931e50188dad"}, + {file = "lxml-5.2.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:ab31a88a651039a07a3ae327d68ebdd8bc589b16938c09ef3f32a4b809dc96ef"}, + {file = "lxml-5.2.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:df2e6f546c4df14bc81f9498bbc007fbb87669f1bb707c6138878c46b06f6510"}, + {file = "lxml-5.2.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5dd1537e7cc06efd81371f5d1a992bd5ab156b2b4f88834ca852de4a8ea523fa"}, + {file = "lxml-5.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9b9ec9c9978b708d488bec36b9e4c94d88fd12ccac3e62134a9d17ddba910ea9"}, + {file = "lxml-5.2.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:8e77c69d5892cb5ba71703c4057091e31ccf534bd7f129307a4d084d90d014b8"}, + {file = "lxml-5.2.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:a8d5c70e04aac1eda5c829a26d1f75c6e5286c74743133d9f742cda8e53b9c2f"}, + {file = "lxml-5.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c94e75445b00319c1fad60f3c98b09cd63fe1134a8a953dcd48989ef42318534"}, + {file = "lxml-5.2.1-cp311-cp311-win32.whl", hash = "sha256:4951e4f7a5680a2db62f7f4ab2f84617674d36d2d76a729b9a8be4b59b3659be"}, + {file = "lxml-5.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:5c670c0406bdc845b474b680b9a5456c561c65cf366f8db5a60154088c92d102"}, + {file = "lxml-5.2.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:abc25c3cab9ec7fcd299b9bcb3b8d4a1231877e425c650fa1c7576c5107ab851"}, + {file = "lxml-5.2.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6935bbf153f9a965f1e07c2649c0849d29832487c52bb4a5c5066031d8b44fd5"}, + {file = "lxml-5.2.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d793bebb202a6000390a5390078e945bbb49855c29c7e4d56a85901326c3b5d9"}, + {file = "lxml-5.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afd5562927cdef7c4f5550374acbc117fd4ecc05b5007bdfa57cc5355864e0a4"}, + {file = "lxml-5.2.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0e7259016bc4345a31af861fdce942b77c99049d6c2107ca07dc2bba2435c1d9"}, + {file = "lxml-5.2.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:530e7c04f72002d2f334d5257c8a51bf409db0316feee7c87e4385043be136af"}, + {file = "lxml-5.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59689a75ba8d7ffca577aefd017d08d659d86ad4585ccc73e43edbfc7476781a"}, + {file = "lxml-5.2.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:f9737bf36262046213a28e789cc82d82c6ef19c85a0cf05e75c670a33342ac2c"}, + {file = "lxml-5.2.1-cp312-cp312-manylinux_2_28_ppc64le.whl", hash = "sha256:3a74c4f27167cb95c1d4af1c0b59e88b7f3e0182138db2501c353555f7ec57f4"}, + {file = "lxml-5.2.1-cp312-cp312-manylinux_2_28_s390x.whl", hash = "sha256:68a2610dbe138fa8c5826b3f6d98a7cfc29707b850ddcc3e21910a6fe51f6ca0"}, + {file = "lxml-5.2.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:f0a1bc63a465b6d72569a9bba9f2ef0334c4e03958e043da1920299100bc7c08"}, + {file = "lxml-5.2.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c2d35a1d047efd68027817b32ab1586c1169e60ca02c65d428ae815b593e65d4"}, + {file = "lxml-5.2.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:79bd05260359170f78b181b59ce871673ed01ba048deef4bf49a36ab3e72e80b"}, + {file = "lxml-5.2.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:865bad62df277c04beed9478fe665b9ef63eb28fe026d5dedcb89b537d2e2ea6"}, + {file = "lxml-5.2.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:44f6c7caff88d988db017b9b0e4ab04934f11e3e72d478031efc7edcac6c622f"}, + {file = "lxml-5.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:71e97313406ccf55d32cc98a533ee05c61e15d11b99215b237346171c179c0b0"}, + {file = "lxml-5.2.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:057cdc6b86ab732cf361f8b4d8af87cf195a1f6dc5b0ff3de2dced242c2015e0"}, + {file = "lxml-5.2.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:f3bbbc998d42f8e561f347e798b85513ba4da324c2b3f9b7969e9c45b10f6169"}, + {file = "lxml-5.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:491755202eb21a5e350dae00c6d9a17247769c64dcf62d8c788b5c135e179dc4"}, + {file = "lxml-5.2.1-cp312-cp312-win32.whl", hash = "sha256:8de8f9d6caa7f25b204fc861718815d41cbcf27ee8f028c89c882a0cf4ae4134"}, + {file = "lxml-5.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:f2a9efc53d5b714b8df2b4b3e992accf8ce5bbdfe544d74d5c6766c9e1146a3a"}, + {file = "lxml-5.2.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:70a9768e1b9d79edca17890175ba915654ee1725975d69ab64813dd785a2bd5c"}, + {file = "lxml-5.2.1-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c38d7b9a690b090de999835f0443d8aa93ce5f2064035dfc48f27f02b4afc3d0"}, + {file = "lxml-5.2.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5670fb70a828663cc37552a2a85bf2ac38475572b0e9b91283dc09efb52c41d1"}, + {file = "lxml-5.2.1-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:958244ad566c3ffc385f47dddde4145088a0ab893504b54b52c041987a8c1863"}, + {file = "lxml-5.2.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:2a66bf12fbd4666dd023b6f51223aed3d9f3b40fef06ce404cb75bafd3d89536"}, + {file = "lxml-5.2.1-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:9123716666e25b7b71c4e1789ec829ed18663152008b58544d95b008ed9e21e9"}, + {file = "lxml-5.2.1-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:0c3f67e2aeda739d1cc0b1102c9a9129f7dc83901226cc24dd72ba275ced4218"}, + {file = "lxml-5.2.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:5d5792e9b3fb8d16a19f46aa8208987cfeafe082363ee2745ea8b643d9cc5b45"}, + {file = "lxml-5.2.1-cp36-cp36m-musllinux_1_2_aarch64.whl", hash = "sha256:88e22fc0a6684337d25c994381ed8a1580a6f5ebebd5ad41f89f663ff4ec2885"}, + {file = "lxml-5.2.1-cp36-cp36m-musllinux_1_2_ppc64le.whl", hash = "sha256:21c2e6b09565ba5b45ae161b438e033a86ad1736b8c838c766146eff8ceffff9"}, + {file = "lxml-5.2.1-cp36-cp36m-musllinux_1_2_s390x.whl", hash = "sha256:afbbdb120d1e78d2ba8064a68058001b871154cc57787031b645c9142b937a62"}, + {file = "lxml-5.2.1-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:627402ad8dea044dde2eccde4370560a2b750ef894c9578e1d4f8ffd54000461"}, + {file = "lxml-5.2.1-cp36-cp36m-win32.whl", hash = "sha256:e89580a581bf478d8dcb97d9cd011d567768e8bc4095f8557b21c4d4c5fea7d0"}, + {file = "lxml-5.2.1-cp36-cp36m-win_amd64.whl", hash = "sha256:59565f10607c244bc4c05c0c5fa0c190c990996e0c719d05deec7030c2aa8289"}, + {file = "lxml-5.2.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:857500f88b17a6479202ff5fe5f580fc3404922cd02ab3716197adf1ef628029"}, + {file = "lxml-5.2.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:56c22432809085b3f3ae04e6e7bdd36883d7258fcd90e53ba7b2e463efc7a6af"}, + {file = "lxml-5.2.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a55ee573116ba208932e2d1a037cc4b10d2c1cb264ced2184d00b18ce585b2c0"}, + {file = "lxml-5.2.1-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:6cf58416653c5901e12624e4013708b6e11142956e7f35e7a83f1ab02f3fe456"}, + {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:64c2baa7774bc22dd4474248ba16fe1a7f611c13ac6123408694d4cc93d66dbd"}, + {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:74b28c6334cca4dd704e8004cba1955af0b778cf449142e581e404bd211fb619"}, + {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:7221d49259aa1e5a8f00d3d28b1e0b76031655ca74bb287123ef56c3db92f213"}, + {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3dbe858ee582cbb2c6294dc85f55b5f19c918c2597855e950f34b660f1a5ede6"}, + {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:04ab5415bf6c86e0518d57240a96c4d1fcfc3cb370bb2ac2a732b67f579e5a04"}, + {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:6ab833e4735a7e5533711a6ea2df26459b96f9eec36d23f74cafe03631647c41"}, + {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f443cdef978430887ed55112b491f670bba6462cea7a7742ff8f14b7abb98d75"}, + {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:9e2addd2d1866fe112bc6f80117bcc6bc25191c5ed1bfbcf9f1386a884252ae8"}, + {file = "lxml-5.2.1-cp37-cp37m-win32.whl", hash = "sha256:f51969bac61441fd31f028d7b3b45962f3ecebf691a510495e5d2cd8c8092dbd"}, + {file = "lxml-5.2.1-cp37-cp37m-win_amd64.whl", hash = "sha256:b0b58fbfa1bf7367dde8a557994e3b1637294be6cf2169810375caf8571a085c"}, + {file = "lxml-5.2.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3e183c6e3298a2ed5af9d7a356ea823bccaab4ec2349dc9ed83999fd289d14d5"}, + {file = "lxml-5.2.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:804f74efe22b6a227306dd890eecc4f8c59ff25ca35f1f14e7482bbce96ef10b"}, + {file = "lxml-5.2.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:08802f0c56ed150cc6885ae0788a321b73505d2263ee56dad84d200cab11c07a"}, + {file = "lxml-5.2.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f8c09ed18ecb4ebf23e02b8e7a22a05d6411911e6fabef3a36e4f371f4f2585"}, + {file = "lxml-5.2.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3d30321949861404323c50aebeb1943461a67cd51d4200ab02babc58bd06a86"}, + {file = "lxml-5.2.1-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:b560e3aa4b1d49e0e6c847d72665384db35b2f5d45f8e6a5c0072e0283430533"}, + {file = "lxml-5.2.1-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:058a1308914f20784c9f4674036527e7c04f7be6fb60f5d61353545aa7fcb739"}, + {file = "lxml-5.2.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:adfb84ca6b87e06bc6b146dc7da7623395db1e31621c4785ad0658c5028b37d7"}, + {file = "lxml-5.2.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:417d14450f06d51f363e41cace6488519038f940676ce9664b34ebf5653433a5"}, + {file = "lxml-5.2.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a2dfe7e2473f9b59496247aad6e23b405ddf2e12ef0765677b0081c02d6c2c0b"}, + {file = "lxml-5.2.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bf2e2458345d9bffb0d9ec16557d8858c9c88d2d11fed53998512504cd9df49b"}, + {file = "lxml-5.2.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:58278b29cb89f3e43ff3e0c756abbd1518f3ee6adad9e35b51fb101c1c1daaec"}, + {file = "lxml-5.2.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:64641a6068a16201366476731301441ce93457eb8452056f570133a6ceb15fca"}, + {file = "lxml-5.2.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:78bfa756eab503673991bdcf464917ef7845a964903d3302c5f68417ecdc948c"}, + {file = "lxml-5.2.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:11a04306fcba10cd9637e669fd73aa274c1c09ca64af79c041aa820ea992b637"}, + {file = "lxml-5.2.1-cp38-cp38-win32.whl", hash = "sha256:66bc5eb8a323ed9894f8fa0ee6cb3e3fb2403d99aee635078fd19a8bc7a5a5da"}, + {file = "lxml-5.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:9676bfc686fa6a3fa10cd4ae6b76cae8be26eb5ec6811d2a325636c460da1806"}, + {file = "lxml-5.2.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:cf22b41fdae514ee2f1691b6c3cdeae666d8b7fa9434de445f12bbeee0cf48dd"}, + {file = "lxml-5.2.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ec42088248c596dbd61d4ae8a5b004f97a4d91a9fd286f632e42e60b706718d7"}, + {file = "lxml-5.2.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd53553ddad4a9c2f1f022756ae64abe16da1feb497edf4d9f87f99ec7cf86bd"}, + {file = "lxml-5.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feaa45c0eae424d3e90d78823f3828e7dc42a42f21ed420db98da2c4ecf0a2cb"}, + {file = "lxml-5.2.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddc678fb4c7e30cf830a2b5a8d869538bc55b28d6c68544d09c7d0d8f17694dc"}, + {file = "lxml-5.2.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:853e074d4931dbcba7480d4dcab23d5c56bd9607f92825ab80ee2bd916edea53"}, + {file = "lxml-5.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc4691d60512798304acb9207987e7b2b7c44627ea88b9d77489bbe3e6cc3bd4"}, + {file = "lxml-5.2.1-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:beb72935a941965c52990f3a32d7f07ce869fe21c6af8b34bf6a277b33a345d3"}, + {file = "lxml-5.2.1-cp39-cp39-manylinux_2_28_ppc64le.whl", hash = "sha256:6588c459c5627fefa30139be4d2e28a2c2a1d0d1c265aad2ba1935a7863a4913"}, + {file = "lxml-5.2.1-cp39-cp39-manylinux_2_28_s390x.whl", hash = "sha256:588008b8497667f1ddca7c99f2f85ce8511f8f7871b4a06ceede68ab62dff64b"}, + {file = "lxml-5.2.1-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b6787b643356111dfd4032b5bffe26d2f8331556ecb79e15dacb9275da02866e"}, + {file = "lxml-5.2.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7c17b64b0a6ef4e5affae6a3724010a7a66bda48a62cfe0674dabd46642e8b54"}, + {file = "lxml-5.2.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:27aa20d45c2e0b8cd05da6d4759649170e8dfc4f4e5ef33a34d06f2d79075d57"}, + {file = "lxml-5.2.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:d4f2cc7060dc3646632d7f15fe68e2fa98f58e35dd5666cd525f3b35d3fed7f8"}, + {file = "lxml-5.2.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff46d772d5f6f73564979cd77a4fffe55c916a05f3cb70e7c9c0590059fb29ef"}, + {file = "lxml-5.2.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:96323338e6c14e958d775700ec8a88346014a85e5de73ac7967db0367582049b"}, + {file = "lxml-5.2.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:52421b41ac99e9d91934e4d0d0fe7da9f02bfa7536bb4431b4c05c906c8c6919"}, + {file = "lxml-5.2.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:7a7efd5b6d3e30d81ec68ab8a88252d7c7c6f13aaa875009fe3097eb4e30b84c"}, + {file = "lxml-5.2.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0ed777c1e8c99b63037b91f9d73a6aad20fd035d77ac84afcc205225f8f41188"}, + {file = "lxml-5.2.1-cp39-cp39-win32.whl", hash = "sha256:644df54d729ef810dcd0f7732e50e5ad1bd0a135278ed8d6bcb06f33b6b6f708"}, + {file = "lxml-5.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:9ca66b8e90daca431b7ca1408cae085d025326570e57749695d6a01454790e95"}, + {file = "lxml-5.2.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9b0ff53900566bc6325ecde9181d89afadc59c5ffa39bddf084aaedfe3b06a11"}, + {file = "lxml-5.2.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd6037392f2d57793ab98d9e26798f44b8b4da2f2464388588f48ac52c489ea1"}, + {file = "lxml-5.2.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b9c07e7a45bb64e21df4b6aa623cb8ba214dfb47d2027d90eac197329bb5e94"}, + {file = "lxml-5.2.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:3249cc2989d9090eeac5467e50e9ec2d40704fea9ab72f36b034ea34ee65ca98"}, + {file = "lxml-5.2.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f42038016852ae51b4088b2862126535cc4fc85802bfe30dea3500fdfaf1864e"}, + {file = "lxml-5.2.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:533658f8fbf056b70e434dff7e7aa611bcacb33e01f75de7f821810e48d1bb66"}, + {file = "lxml-5.2.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:622020d4521e22fb371e15f580d153134bfb68d6a429d1342a25f051ec72df1c"}, + {file = "lxml-5.2.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efa7b51824aa0ee957ccd5a741c73e6851de55f40d807f08069eb4c5a26b2baa"}, + {file = "lxml-5.2.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c6ad0fbf105f6bcc9300c00010a2ffa44ea6f555df1a2ad95c88f5656104817"}, + {file = "lxml-5.2.1-pp37-pypy37_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:e233db59c8f76630c512ab4a4daf5a5986da5c3d5b44b8e9fc742f2a24dbd460"}, + {file = "lxml-5.2.1-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:6a014510830df1475176466b6087fc0c08b47a36714823e58d8b8d7709132a96"}, + {file = "lxml-5.2.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:d38c8f50ecf57f0463399569aa388b232cf1a2ffb8f0a9a5412d0db57e054860"}, + {file = "lxml-5.2.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5aea8212fb823e006b995c4dda533edcf98a893d941f173f6c9506126188860d"}, + {file = "lxml-5.2.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff097ae562e637409b429a7ac958a20aab237a0378c42dabaa1e3abf2f896e5f"}, + {file = "lxml-5.2.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f5d65c39f16717a47c36c756af0fb36144069c4718824b7533f803ecdf91138"}, + {file = "lxml-5.2.1-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:3d0c3dd24bb4605439bf91068598d00c6370684f8de4a67c2992683f6c309d6b"}, + {file = "lxml-5.2.1-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e32be23d538753a8adb6c85bd539f5fd3b15cb987404327c569dfc5fd8366e85"}, + {file = "lxml-5.2.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:cc518cea79fd1e2f6c90baafa28906d4309d24f3a63e801d855e7424c5b34144"}, + {file = "lxml-5.2.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a0af35bd8ebf84888373630f73f24e86bf016642fb8576fba49d3d6b560b7cbc"}, + {file = "lxml-5.2.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8aca2e3a72f37bfc7b14ba96d4056244001ddcc18382bd0daa087fd2e68a354"}, + {file = "lxml-5.2.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ca1e8188b26a819387b29c3895c47a5e618708fe6f787f3b1a471de2c4a94d9"}, + {file = "lxml-5.2.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c8ba129e6d3b0136a0f50345b2cb3db53f6bda5dd8c7f5d83fbccba97fb5dcb5"}, + {file = "lxml-5.2.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e998e304036198b4f6914e6a1e2b6f925208a20e2042563d9734881150c6c246"}, + {file = "lxml-5.2.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d3be9b2076112e51b323bdf6d5a7f8a798de55fb8d95fcb64bd179460cdc0704"}, + {file = "lxml-5.2.1.tar.gz", hash = "sha256:3f7765e69bbce0906a7c74d5fe46d2c7a7596147318dbc08e4a2431f3060e306"}, ] [package.extras] cssselect = ["cssselect (>=0.7)"] +html-clean = ["lxml-html-clean"] html5 = ["html5lib"] htmlsoup = ["BeautifulSoup4"] -source = ["Cython (==0.29.37)"] +source = ["Cython (>=3.0.10)"] [[package]] name = "mako" @@ -3955,6 +4602,21 @@ babel = ["Babel"] lingua = ["lingua"] testing = ["pytest"] +[[package]] +name = "markdown" +version = "3.6" +description = "Python implementation of John Gruber's Markdown." +optional = false +python-versions = ">=3.8" +files = [ + {file = "Markdown-3.6-py3-none-any.whl", hash = "sha256:48f276f4d8cfb8ce6527c8f79e2ee29708508bf4d40aa410fbc3b4ee832c850f"}, + {file = "Markdown-3.6.tar.gz", hash = "sha256:ed4f41f6daecbeeb96e576ce414c41d2d876daa9a16cb35fa8ed8c2ddfad0224"}, +] + +[package.extras] +docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"] +testing = ["coverage", "pyyaml"] + [[package]] name = "markdown-it-py" version = "3.0.0" @@ -4303,7 +4965,6 @@ files = [ {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fbb160554e319f7b22ecf530a80a3ff496d38e8e07ae763b9e82fadfe96f273"}, {file = "msgpack-1.0.8-cp39-cp39-win32.whl", hash = "sha256:f9af38a89b6a5c04b7d18c492c8ccf2aee7048aff1ce8437c4683bb5a1df893d"}, {file = "msgpack-1.0.8-cp39-cp39-win_amd64.whl", hash = "sha256:ed59dd52075f8fc91da6053b12e8c89e37aa043f8986efd89e61fae69dc1b011"}, - {file = "msgpack-1.0.8-py3-none-any.whl", hash = "sha256:24f727df1e20b9876fa6e95f840a2a2651e34c0ad147676356f4bf5fbb0206ca"}, {file = "msgpack-1.0.8.tar.gz", hash = "sha256:95c02b0e27e706e48d0e5426d1710ca78e0f0628d6e89d5b5a5b91a5f12274f3"}, ] @@ -4423,27 +5084,31 @@ files = [ [[package]] name = "multiprocess" -version = "0.70.16" +version = "0.70.15" description = "better multiprocessing and multithreading in Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.7" files = [ - {file = "multiprocess-0.70.16-pp310-pypy310_pp73-macosx_10_13_x86_64.whl", hash = "sha256:476887be10e2f59ff183c006af746cb6f1fd0eadcfd4ef49e605cbe2659920ee"}, - {file = "multiprocess-0.70.16-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d951bed82c8f73929ac82c61f01a7b5ce8f3e5ef40f5b52553b4f547ce2b08ec"}, - {file = "multiprocess-0.70.16-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:37b55f71c07e2d741374998c043b9520b626a8dddc8b3129222ca4f1a06ef67a"}, - {file = "multiprocess-0.70.16-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:ba8c31889abf4511c7308a8c52bb4a30b9d590e7f58523302ba00237702ca054"}, - {file = "multiprocess-0.70.16-pp39-pypy39_pp73-macosx_10_13_x86_64.whl", hash = "sha256:0dfd078c306e08d46d7a8d06fb120313d87aa43af60d66da43ffff40b44d2f41"}, - {file = "multiprocess-0.70.16-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e7b9d0f307cd9bd50851afaac0dba2cb6c44449efff697df7c7645f7d3f2be3a"}, - {file = "multiprocess-0.70.16-py310-none-any.whl", hash = "sha256:c4a9944c67bd49f823687463660a2d6daae94c289adff97e0f9d696ba6371d02"}, - {file = "multiprocess-0.70.16-py311-none-any.whl", hash = "sha256:af4cabb0dac72abfb1e794fa7855c325fd2b55a10a44628a3c1ad3311c04127a"}, - {file = "multiprocess-0.70.16-py312-none-any.whl", hash = "sha256:fc0544c531920dde3b00c29863377f87e1632601092ea2daca74e4beb40faa2e"}, - {file = "multiprocess-0.70.16-py38-none-any.whl", hash = "sha256:a71d82033454891091a226dfc319d0cfa8019a4e888ef9ca910372a446de4435"}, - {file = "multiprocess-0.70.16-py39-none-any.whl", hash = "sha256:a0bafd3ae1b732eac64be2e72038231c1ba97724b60b09400d68f229fcc2fbf3"}, - {file = "multiprocess-0.70.16.tar.gz", hash = "sha256:161af703d4652a0e1410be6abccecde4a7ddffd19341be0a7011b94aeb171ac1"}, + {file = "multiprocess-0.70.15-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:aa36c7ed16f508091438687fe9baa393a7a8e206731d321e443745e743a0d4e5"}, + {file = "multiprocess-0.70.15-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:20e024018c46d0d1602024c613007ac948f9754659e3853b0aa705e83f6931d8"}, + {file = "multiprocess-0.70.15-pp37-pypy37_pp73-manylinux_2_24_i686.whl", hash = "sha256:e576062981c91f0fe8a463c3d52506e598dfc51320a8dd8d78b987dfca91c5db"}, + {file = "multiprocess-0.70.15-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:e73f497e6696a0f5433ada2b3d599ae733b87a6e8b008e387c62ac9127add177"}, + {file = "multiprocess-0.70.15-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:73db2e7b32dcc7f9b0f075c2ffa45c90b6729d3f1805f27e88534c8d321a1be5"}, + {file = "multiprocess-0.70.15-pp38-pypy38_pp73-manylinux_2_24_i686.whl", hash = "sha256:4271647bd8a49c28ecd6eb56a7fdbd3c212c45529ad5303b40b3c65fc6928e5f"}, + {file = "multiprocess-0.70.15-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:cf981fb998d6ec3208cb14f0cf2e9e80216e834f5d51fd09ebc937c32b960902"}, + {file = "multiprocess-0.70.15-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:18f9f2c7063346d1617bd1684fdcae8d33380ae96b99427260f562e1a1228b67"}, + {file = "multiprocess-0.70.15-pp39-pypy39_pp73-manylinux_2_24_i686.whl", hash = "sha256:0eac53214d664c49a34695e5824872db4006b1a465edd7459a251809c3773370"}, + {file = "multiprocess-0.70.15-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:1a51dd34096db47fb21fa2b839e615b051d51b97af9a67afbcdaa67186b44883"}, + {file = "multiprocess-0.70.15-py310-none-any.whl", hash = "sha256:7dd58e33235e83cf09d625e55cffd7b0f0eede7ee9223cdd666a87624f60c21a"}, + {file = "multiprocess-0.70.15-py311-none-any.whl", hash = "sha256:134f89053d82c9ed3b73edd3a2531eb791e602d4f4156fc92a79259590bd9670"}, + {file = "multiprocess-0.70.15-py37-none-any.whl", hash = "sha256:f7d4a1629bccb433114c3b4885f69eccc200994323c80f6feee73b0edc9199c5"}, + {file = "multiprocess-0.70.15-py38-none-any.whl", hash = "sha256:bee9afba476c91f9ebee7beeee0601face9eff67d822e893f9a893725fbd6316"}, + {file = "multiprocess-0.70.15-py39-none-any.whl", hash = "sha256:3e0953f5d52b4c76f1c973eaf8214554d146f2be5decb48e928e55c7a2d19338"}, + {file = "multiprocess-0.70.15.tar.gz", hash = "sha256:f20eed3036c0ef477b07a4177cf7c1ba520d9a2677870a4f47fe026f0cd6787e"}, ] [package.dependencies] -dill = ">=0.3.8" +dill = ">=0.3.7" [[package]] name = "mypy" @@ -4559,44 +5224,44 @@ twitter = ["twython"] [[package]] name = "numexpr" -version = "2.9.0" +version = "2.10.0" description = "Fast numerical expression evaluator for NumPy" optional = false python-versions = ">=3.9" files = [ - {file = "numexpr-2.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c52b4ac54514f5d4d8ead66768810cd5f77aa198e6064213d9b5c7b2e1c97c35"}, - {file = "numexpr-2.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:50f57bc333f285e8c46b1ce61c6e94ec9bb74e4ea0d674d1c6c6f4a286f64fe4"}, - {file = "numexpr-2.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:943ba141f3884ffafa3fa1a3ebf3cdda9e9688a67a3c91986e6eae13dc073d43"}, - {file = "numexpr-2.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee48acd6339748a65c0e32403b802ebfadd9cb0e3b602ba5889896238eafdd61"}, - {file = "numexpr-2.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:972e29b5cecc21466c5b177e38568372ab66aab1f053ae04690a49cea09e747d"}, - {file = "numexpr-2.9.0-cp310-cp310-win32.whl", hash = "sha256:520e55d75bd99c76e376b6326e35ecf44c5ce2635a5caed72799a3885fc49173"}, - {file = "numexpr-2.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:5615497c3f34b637fda9b571f7774b6a82f2367cc1364b7a4573068dd1aabcaa"}, - {file = "numexpr-2.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bffcbc55dea5a5f5255e2586da08f00929998820e6592ee717273a08ad021eb3"}, - {file = "numexpr-2.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:374dc6ca54b2af813cb15c2b34e85092dfeac1f73d51ec358dd81876bd9adcec"}, - {file = "numexpr-2.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:549afc1622296cca3478a132c6e0fb5e55a19e08d32bc0d5a415434824a9c157"}, - {file = "numexpr-2.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c618a5895e34db0a364dcdb9960084c080f93f9d377c45b1ca9c394c24b4e77"}, - {file = "numexpr-2.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:37a7dd36fd79a2b69c3fd2bc2b51ac8270bebc69cc96e6d78f1148e147fcbfa8"}, - {file = "numexpr-2.9.0-cp311-cp311-win32.whl", hash = "sha256:00dab81d49239ea5423861ad627097b44d10d802df5f883d1b00f742139c3349"}, - {file = "numexpr-2.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:0e2574cafb18373774f351cac45ed23b5b360d9ecd1dbf3c12dac6d6eefefc87"}, - {file = "numexpr-2.9.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9761195526a228e05eba400b8c484c94bbabfea853b9ea35ab8fa1bf415331b1"}, - {file = "numexpr-2.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0f619e91034b346ea85a4e1856ff06011dcb7dce10a60eda75e74db90120f880"}, - {file = "numexpr-2.9.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2749bce1c48706d58894992634a43b8458c4ba9411191471c4565fa41e9979ec"}, - {file = "numexpr-2.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1c31f621a625c7be602f92b027d90f2d3d60dcbc19b106e77fb04a4362152af"}, - {file = "numexpr-2.9.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1a78b937861d13de67d440d54c85a835faed7572be5a6fd10d4f3bd4e66e157f"}, - {file = "numexpr-2.9.0-cp312-cp312-win32.whl", hash = "sha256:aa6298fb46bd7ec69911b5b80927a00663d066e719b29f48eb952d559bdd8371"}, - {file = "numexpr-2.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:8efd879839572bde5a38a1aa3ac23fd4dd9b956fb969bc5e43d1c403419e1e8c"}, - {file = "numexpr-2.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b04f12a6130094a251e3a8fff40130589c1c83be6d4eb223873bea14d8c8b630"}, - {file = "numexpr-2.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:977537f2a1cc843f888fb5f0507626f956ada674e4b3847168214a3f3c7446fa"}, - {file = "numexpr-2.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6eae6c0c2d5682c02e8ac9c4287c2232c2443c9148b239df22500eaa3c5d73b7"}, - {file = "numexpr-2.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1fae6828042b70c2f52a132bfcb9139da704274ed11b982fbf537f91c075d2ef"}, - {file = "numexpr-2.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7c77392aea53f0700d60eb270ad63174b4ff10b04f8de92861101ca2129fee51"}, - {file = "numexpr-2.9.0-cp39-cp39-win32.whl", hash = "sha256:3b03a6cf37a72f5b52f2b962d7ac7f565bea8eaba83c3c4e5fcf8fbb6a938153"}, - {file = "numexpr-2.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:d655b6eacc4e81006b662cba014e4615a9ddd96881b8b4db4ad0d7f6d38069af"}, - {file = "numexpr-2.9.0.tar.gz", hash = "sha256:f21d12f6c432ce349089eb95342babf6629aebb3fddf187a4492d3aadaadaaf0"}, + {file = "numexpr-2.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1af6dc6b3bd2e11a802337b352bf58f30df0b70be16c4f863b70a3af3a8ef95e"}, + {file = "numexpr-2.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3c66dc0188358cdcc9465b6ee54fd5eef2e83ac64b1d4ba9117c41df59bf6fca"}, + {file = "numexpr-2.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83f1e7a7f7ee741b8dcd20c56c3f862a3a3ec26fa8b9fcadb7dcd819876d2f35"}, + {file = "numexpr-2.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f0b045e1831953a47cc9fabae76a6794c69cbb60921751a5cf2d555034c55bf"}, + {file = "numexpr-2.10.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1d8eb88b0ae3d3c609d732a17e71096779b2bf47b3a084320ffa93d9f9132786"}, + {file = "numexpr-2.10.0-cp310-cp310-win32.whl", hash = "sha256:629b66cc1b750671e7fb396506b3f9410612e5bd8bc1dd55b5a0a0041d839f95"}, + {file = "numexpr-2.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:78e0a8bc4417c3dedcbae3c473505b69080535246edc977c7dccf3ec8454a685"}, + {file = "numexpr-2.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a602692cd52ce923ce8a0a90fb1d6cf186ebe8706eed83eee0de685e634b9aa9"}, + {file = "numexpr-2.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:745b46a1fb76920a3eebfaf26e50bc94a9c13b5aee34b256ab4b2d792dbaa9ca"}, + {file = "numexpr-2.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10789450032357afaeda4ac4d06da9542d1535c13151e8d32b49ae1a488d1358"}, + {file = "numexpr-2.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4feafc65ea3044b8bf8f305b757a928e59167a310630c22b97a57dff07a56490"}, + {file = "numexpr-2.10.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:937d36c6d3cf15601f26f84f0f706649f976491e9e0892d16cd7c876d77fa7dc"}, + {file = "numexpr-2.10.0-cp311-cp311-win32.whl", hash = "sha256:03d0ba492e484a5a1aeb24b300c4213ed168f2c246177be5733abb4e18cbb043"}, + {file = "numexpr-2.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:6b5f8242c075477156d26b3a6b8e0cd0a06d4c8eb68d907bde56dd3c9c683e92"}, + {file = "numexpr-2.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b276e2ba3e87ace9a30fd49078ad5dcdc6a1674d030b1ec132599c55465c0346"}, + {file = "numexpr-2.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb5e12787101f1216f2cdabedc3417748f2e1f472442e16bbfabf0bab2336300"}, + {file = "numexpr-2.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05278bad96b5846d712eba58b44e5cec743bdb3e19ca624916c921d049fdbcf6"}, + {file = "numexpr-2.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6cdf9e64c5b3dbb61729edb505ea75ee212fa02b85c5b1d851331381ae3b0e1"}, + {file = "numexpr-2.10.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e3a973265591b0a875fd1151c4549e468959c7192821aac0bb86937694a08efa"}, + {file = "numexpr-2.10.0-cp312-cp312-win32.whl", hash = "sha256:416e0e9f0fc4cced67767585e44cb6b301728bdb9edbb7c534a853222ec62cac"}, + {file = "numexpr-2.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:748e8d4cde22d9a5603165293fb293a4de1a4623513299416c64fdab557118c2"}, + {file = "numexpr-2.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dc3506c30c03b082da2cadef43747d474e5170c1f58a6dcdf882b3dc88b1e849"}, + {file = "numexpr-2.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:efa63ecdc9fcaf582045639ddcf56e9bdc1f4d9a01729be528f62df4db86c9d6"}, + {file = "numexpr-2.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96a64d0dd8f8e694da3f8582d73d7da8446ff375f6dd239b546010efea371ac3"}, + {file = "numexpr-2.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d47bb567e330ebe86781864219a36cbccb3a47aec893bd509f0139c6b23e8104"}, + {file = "numexpr-2.10.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c7517b774d309b1f0896c89bdd1ddd33c4418a92ecfbe5e1df3ac698698f6fcf"}, + {file = "numexpr-2.10.0-cp39-cp39-win32.whl", hash = "sha256:04e8620e7e676504201d4082e7b3ee2d9b561d1cb9470b47a6104e10c1e2870e"}, + {file = "numexpr-2.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:56d0d96b130f7cd4d78d0017030d6a0e9d9fc2a717ac51d4cf4860b39637e86a"}, + {file = "numexpr-2.10.0.tar.gz", hash = "sha256:c89e930752639df040539160326d8f99a84159bbea41943ab8e960591edaaef0"}, ] [package.dependencies] -numpy = ">=1.13.3" +numpy = ">=1.19.3" [[package]] name = "numpy" @@ -4769,6 +5434,7 @@ description = "Nvidia JIT LTO Library" optional = true python-versions = ">=3" files = [ + {file = "nvidia_nvjitlink_cu12-12.4.99-py3-none-manylinux2014_aarch64.whl", hash = "sha256:75d6498c96d9adb9435f2bbdbddb479805ddfb97b5c1b32395c694185c20ca57"}, {file = "nvidia_nvjitlink_cu12-12.4.99-py3-none-manylinux2014_x86_64.whl", hash = "sha256:c6428836d20fe7e327191c175791d38570e10762edc588fb46749217cd444c74"}, {file = "nvidia_nvjitlink_cu12-12.4.99-py3-none-win_amd64.whl", hash = "sha256:991905ffa2144cb603d8ca7962d75c35334ae82bf92820b6ba78157277da1ad2"}, ] @@ -4880,13 +5546,13 @@ sympy = "*" [[package]] name = "openai" -version = "1.14.3" +version = "1.16.1" description = "The official Python library for the openai API" optional = false python-versions = ">=3.7.1" files = [ - {file = "openai-1.14.3-py3-none-any.whl", hash = "sha256:7a465994a7ccf677a110c6cc2ef9d86229bad42c060b585b67049aa749f3b774"}, - {file = "openai-1.14.3.tar.gz", hash = "sha256:37b514e9c0ff45383ec9b242abd0f7859b1080d4b54b61393ed341ecad1b8eb9"}, + {file = "openai-1.16.1-py3-none-any.whl", hash = "sha256:77ef3db6110071f7154859e234250fb945a36554207a30a4491092eadb73fcb5"}, + {file = "openai-1.16.1.tar.gz", hash = "sha256:58922c785d167458b46e3c76e7b1bc2306f313ee9b71791e84cbf590abe160f2"}, ] [package.dependencies] @@ -4953,6 +5619,26 @@ opentelemetry-sdk = ">=1.24.0,<1.25.0" [package.extras] test = ["pytest-grpc"] +[[package]] +name = "opentelemetry-exporter-otlp-proto-http" +version = "1.24.0" +description = "OpenTelemetry Collector Protobuf over HTTP Exporter" +optional = false +python-versions = ">=3.8" +files = [ + {file = "opentelemetry_exporter_otlp_proto_http-1.24.0-py3-none-any.whl", hash = "sha256:25af10e46fdf4cd3833175e42f4879a1255fc01655fe14c876183a2903949836"}, + {file = "opentelemetry_exporter_otlp_proto_http-1.24.0.tar.gz", hash = "sha256:704c066cc96f5131881b75c0eac286cd73fc735c490b054838b4513254bd7850"}, +] + +[package.dependencies] +deprecated = ">=1.2.6" +googleapis-common-protos = ">=1.52,<2.0" +opentelemetry-api = ">=1.15,<2.0" +opentelemetry-exporter-otlp-proto-common = "1.24.0" +opentelemetry-proto = "1.24.0" +opentelemetry-sdk = ">=1.24.0,<1.25.0" +requests = ">=2.7,<3.0" + [[package]] name = "opentelemetry-instrumentation" version = "0.45b0" @@ -5063,6 +5749,33 @@ files = [ {file = "opentelemetry_util_http-0.45b0.tar.gz", hash = "sha256:4ce08b6a7d52dd7c96b7705b5b4f06fdb6aa3eac1233b3b0bfef8a0cab9a92cd"}, ] +[[package]] +name = "optuna" +version = "3.6.1" +description = "A hyperparameter optimization framework" +optional = false +python-versions = ">=3.7" +files = [ + {file = "optuna-3.6.1-py3-none-any.whl", hash = "sha256:b32e0490bd6552790b70ec94de77dd2855057c9e229cd9f4da48fe8a31c7f1cc"}, + {file = "optuna-3.6.1.tar.gz", hash = "sha256:146e530b57b4b9afd7526b3e642fbe65491f7e292b405913355f8e438e361ecf"}, +] + +[package.dependencies] +alembic = ">=1.5.0" +colorlog = "*" +numpy = "*" +packaging = ">=20.0" +PyYAML = "*" +sqlalchemy = ">=1.3.0" +tqdm = "*" + +[package.extras] +benchmark = ["asv (>=0.5.0)", "botorch", "cma", "virtualenv"] +checking = ["black", "blackdoc", "flake8", "isort", "mypy", "mypy-boto3-s3", "types-PyYAML", "types-redis", "types-setuptools", "types-tqdm", "typing-extensions (>=3.10.0.0)"] +document = ["ase", "cmaes (>=0.10.0)", "fvcore", "lightgbm", "matplotlib (!=3.6.0)", "pandas", "pillow", "plotly (>=4.9.0)", "scikit-learn", "sphinx", "sphinx-copybutton", "sphinx-gallery", "sphinx-plotly-directive", "sphinx-rtd-theme (>=1.2.0)", "torch", "torchvision"] +optional = ["boto3", "cmaes (>=0.10.0)", "google-cloud-storage", "matplotlib (!=3.6.0)", "pandas", "plotly (>=4.9.0)", "redis", "scikit-learn (>=0.24.2)", "scipy", "torch"] +test = ["coverage", "fakeredis[lua]", "kaleido", "moto", "pytest", "scipy (>=1.9.2)", "torch"] + [[package]] name = "ordered-set" version = "4.1.0" @@ -5320,79 +6033,80 @@ numpy = "*" [[package]] name = "pillow" -version = "10.2.0" +version = "10.3.0" description = "Python Imaging Library (Fork)" optional = false python-versions = ">=3.8" files = [ - {file = "pillow-10.2.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:7823bdd049099efa16e4246bdf15e5a13dbb18a51b68fa06d6c1d4d8b99a796e"}, - {file = "pillow-10.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:83b2021f2ade7d1ed556bc50a399127d7fb245e725aa0113ebd05cfe88aaf588"}, - {file = "pillow-10.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fad5ff2f13d69b7e74ce5b4ecd12cc0ec530fcee76356cac6742785ff71c452"}, - {file = "pillow-10.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da2b52b37dad6d9ec64e653637a096905b258d2fc2b984c41ae7d08b938a67e4"}, - {file = "pillow-10.2.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:47c0995fc4e7f79b5cfcab1fc437ff2890b770440f7696a3ba065ee0fd496563"}, - {file = "pillow-10.2.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:322bdf3c9b556e9ffb18f93462e5f749d3444ce081290352c6070d014c93feb2"}, - {file = "pillow-10.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:51f1a1bffc50e2e9492e87d8e09a17c5eea8409cda8d3f277eb6edc82813c17c"}, - {file = "pillow-10.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:69ffdd6120a4737710a9eee73e1d2e37db89b620f702754b8f6e62594471dee0"}, - {file = "pillow-10.2.0-cp310-cp310-win32.whl", hash = "sha256:c6dafac9e0f2b3c78df97e79af707cdc5ef8e88208d686a4847bab8266870023"}, - {file = "pillow-10.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:aebb6044806f2e16ecc07b2a2637ee1ef67a11840a66752751714a0d924adf72"}, - {file = "pillow-10.2.0-cp310-cp310-win_arm64.whl", hash = "sha256:7049e301399273a0136ff39b84c3678e314f2158f50f517bc50285fb5ec847ad"}, - {file = "pillow-10.2.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:35bb52c37f256f662abdfa49d2dfa6ce5d93281d323a9af377a120e89a9eafb5"}, - {file = "pillow-10.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9c23f307202661071d94b5e384e1e1dc7dfb972a28a2310e4ee16103e66ddb67"}, - {file = "pillow-10.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:773efe0603db30c281521a7c0214cad7836c03b8ccff897beae9b47c0b657d61"}, - {file = "pillow-10.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11fa2e5984b949b0dd6d7a94d967743d87c577ff0b83392f17cb3990d0d2fd6e"}, - {file = "pillow-10.2.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:716d30ed977be8b37d3ef185fecb9e5a1d62d110dfbdcd1e2a122ab46fddb03f"}, - {file = "pillow-10.2.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a086c2af425c5f62a65e12fbf385f7c9fcb8f107d0849dba5839461a129cf311"}, - {file = "pillow-10.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c8de2789052ed501dd829e9cae8d3dcce7acb4777ea4a479c14521c942d395b1"}, - {file = "pillow-10.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:609448742444d9290fd687940ac0b57fb35e6fd92bdb65386e08e99af60bf757"}, - {file = "pillow-10.2.0-cp311-cp311-win32.whl", hash = "sha256:823ef7a27cf86df6597fa0671066c1b596f69eba53efa3d1e1cb8b30f3533068"}, - {file = "pillow-10.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:1da3b2703afd040cf65ec97efea81cfba59cdbed9c11d8efc5ab09df9509fc56"}, - {file = "pillow-10.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:edca80cbfb2b68d7b56930b84a0e45ae1694aeba0541f798e908a49d66b837f1"}, - {file = "pillow-10.2.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:1b5e1b74d1bd1b78bc3477528919414874748dd363e6272efd5abf7654e68bef"}, - {file = "pillow-10.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0eae2073305f451d8ecacb5474997c08569fb4eb4ac231ffa4ad7d342fdc25ac"}, - {file = "pillow-10.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7c2286c23cd350b80d2fc9d424fc797575fb16f854b831d16fd47ceec078f2c"}, - {file = "pillow-10.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e23412b5c41e58cec602f1135c57dfcf15482013ce6e5f093a86db69646a5aa"}, - {file = "pillow-10.2.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:52a50aa3fb3acb9cf7213573ef55d31d6eca37f5709c69e6858fe3bc04a5c2a2"}, - {file = "pillow-10.2.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:127cee571038f252a552760076407f9cff79761c3d436a12af6000cd182a9d04"}, - {file = "pillow-10.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:8d12251f02d69d8310b046e82572ed486685c38f02176bd08baf216746eb947f"}, - {file = "pillow-10.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:54f1852cd531aa981bc0965b7d609f5f6cc8ce8c41b1139f6ed6b3c54ab82bfb"}, - {file = "pillow-10.2.0-cp312-cp312-win32.whl", hash = "sha256:257d8788df5ca62c980314053197f4d46eefedf4e6175bc9412f14412ec4ea2f"}, - {file = "pillow-10.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:154e939c5f0053a383de4fd3d3da48d9427a7e985f58af8e94d0b3c9fcfcf4f9"}, - {file = "pillow-10.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:f379abd2f1e3dddb2b61bc67977a6b5a0a3f7485538bcc6f39ec76163891ee48"}, - {file = "pillow-10.2.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:8373c6c251f7ef8bda6675dd6d2b3a0fcc31edf1201266b5cf608b62a37407f9"}, - {file = "pillow-10.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:870ea1ada0899fd0b79643990809323b389d4d1d46c192f97342eeb6ee0b8483"}, - {file = "pillow-10.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4b6b1e20608493548b1f32bce8cca185bf0480983890403d3b8753e44077129"}, - {file = "pillow-10.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3031709084b6e7852d00479fd1d310b07d0ba82765f973b543c8af5061cf990e"}, - {file = "pillow-10.2.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:3ff074fc97dd4e80543a3e91f69d58889baf2002b6be64347ea8cf5533188213"}, - {file = "pillow-10.2.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:cb4c38abeef13c61d6916f264d4845fab99d7b711be96c326b84df9e3e0ff62d"}, - {file = "pillow-10.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b1b3020d90c2d8e1dae29cf3ce54f8094f7938460fb5ce8bc5c01450b01fbaf6"}, - {file = "pillow-10.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:170aeb00224ab3dc54230c797f8404507240dd868cf52066f66a41b33169bdbe"}, - {file = "pillow-10.2.0-cp38-cp38-win32.whl", hash = "sha256:c4225f5220f46b2fde568c74fca27ae9771536c2e29d7c04f4fb62c83275ac4e"}, - {file = "pillow-10.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:0689b5a8c5288bc0504d9fcee48f61a6a586b9b98514d7d29b840143d6734f39"}, - {file = "pillow-10.2.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:b792a349405fbc0163190fde0dc7b3fef3c9268292586cf5645598b48e63dc67"}, - {file = "pillow-10.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c570f24be1e468e3f0ce7ef56a89a60f0e05b30a3669a459e419c6eac2c35364"}, - {file = "pillow-10.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8ecd059fdaf60c1963c58ceb8997b32e9dc1b911f5da5307aab614f1ce5c2fb"}, - {file = "pillow-10.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c365fd1703040de1ec284b176d6af5abe21b427cb3a5ff68e0759e1e313a5e7e"}, - {file = "pillow-10.2.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:70c61d4c475835a19b3a5aa42492409878bbca7438554a1f89d20d58a7c75c01"}, - {file = "pillow-10.2.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b6f491cdf80ae540738859d9766783e3b3c8e5bd37f5dfa0b76abdecc5081f13"}, - {file = "pillow-10.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d189550615b4948f45252d7f005e53c2040cea1af5b60d6f79491a6e147eef7"}, - {file = "pillow-10.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:49d9ba1ed0ef3e061088cd1e7538a0759aab559e2e0a80a36f9fd9d8c0c21591"}, - {file = "pillow-10.2.0-cp39-cp39-win32.whl", hash = "sha256:babf5acfede515f176833ed6028754cbcd0d206f7f614ea3447d67c33be12516"}, - {file = "pillow-10.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:0304004f8067386b477d20a518b50f3fa658a28d44e4116970abfcd94fac34a8"}, - {file = "pillow-10.2.0-cp39-cp39-win_arm64.whl", hash = "sha256:0fb3e7fc88a14eacd303e90481ad983fd5b69c761e9e6ef94c983f91025da869"}, - {file = "pillow-10.2.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:322209c642aabdd6207517e9739c704dc9f9db943015535783239022002f054a"}, - {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3eedd52442c0a5ff4f887fab0c1c0bb164d8635b32c894bc1faf4c618dd89df2"}, - {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb28c753fd5eb3dd859b4ee95de66cc62af91bcff5db5f2571d32a520baf1f04"}, - {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:33870dc4653c5017bf4c8873e5488d8f8d5f8935e2f1fb9a2208c47cdd66efd2"}, - {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3c31822339516fb3c82d03f30e22b1d038da87ef27b6a78c9549888f8ceda39a"}, - {file = "pillow-10.2.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a2b56ba36e05f973d450582fb015594aaa78834fefe8dfb8fcd79b93e64ba4c6"}, - {file = "pillow-10.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d8e6aeb9201e655354b3ad049cb77d19813ad4ece0df1249d3c793de3774f8c7"}, - {file = "pillow-10.2.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:2247178effb34a77c11c0e8ac355c7a741ceca0a732b27bf11e747bbc950722f"}, - {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15587643b9e5eb26c48e49a7b33659790d28f190fc514a322d55da2fb5c2950e"}, - {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753cd8f2086b2b80180d9b3010dd4ed147efc167c90d3bf593fe2af21265e5a5"}, - {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:7c8f97e8e7a9009bcacbe3766a36175056c12f9a44e6e6f2d5caad06dcfbf03b"}, - {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d1b35bcd6c5543b9cb547dee3150c93008f8dd0f1fef78fc0cd2b141c5baf58a"}, - {file = "pillow-10.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fe4c15f6c9285dc54ce6553a3ce908ed37c8f3825b5a51a15c91442bb955b868"}, - {file = "pillow-10.2.0.tar.gz", hash = "sha256:e87f0b2c78157e12d7686b27d63c070fd65d994e8ddae6f328e0dcf4a0cd007e"}, + {file = "pillow-10.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:90b9e29824800e90c84e4022dd5cc16eb2d9605ee13f05d47641eb183cd73d45"}, + {file = "pillow-10.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a2c405445c79c3f5a124573a051062300936b0281fee57637e706453e452746c"}, + {file = "pillow-10.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78618cdbccaa74d3f88d0ad6cb8ac3007f1a6fa5c6f19af64b55ca170bfa1edf"}, + {file = "pillow-10.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:261ddb7ca91fcf71757979534fb4c128448b5b4c55cb6152d280312062f69599"}, + {file = "pillow-10.3.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:ce49c67f4ea0609933d01c0731b34b8695a7a748d6c8d186f95e7d085d2fe475"}, + {file = "pillow-10.3.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:b14f16f94cbc61215115b9b1236f9c18403c15dd3c52cf629072afa9d54c1cbf"}, + {file = "pillow-10.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d33891be6df59d93df4d846640f0e46f1a807339f09e79a8040bc887bdcd7ed3"}, + {file = "pillow-10.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b50811d664d392f02f7761621303eba9d1b056fb1868c8cdf4231279645c25f5"}, + {file = "pillow-10.3.0-cp310-cp310-win32.whl", hash = "sha256:ca2870d5d10d8726a27396d3ca4cf7976cec0f3cb706debe88e3a5bd4610f7d2"}, + {file = "pillow-10.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:f0d0591a0aeaefdaf9a5e545e7485f89910c977087e7de2b6c388aec32011e9f"}, + {file = "pillow-10.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:ccce24b7ad89adb5a1e34a6ba96ac2530046763912806ad4c247356a8f33a67b"}, + {file = "pillow-10.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:5f77cf66e96ae734717d341c145c5949c63180842a545c47a0ce7ae52ca83795"}, + {file = "pillow-10.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e4b878386c4bf293578b48fc570b84ecfe477d3b77ba39a6e87150af77f40c57"}, + {file = "pillow-10.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdcbb4068117dfd9ce0138d068ac512843c52295ed996ae6dd1faf537b6dbc27"}, + {file = "pillow-10.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9797a6c8fe16f25749b371c02e2ade0efb51155e767a971c61734b1bf6293994"}, + {file = "pillow-10.3.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:9e91179a242bbc99be65e139e30690e081fe6cb91a8e77faf4c409653de39451"}, + {file = "pillow-10.3.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:1b87bd9d81d179bd8ab871603bd80d8645729939f90b71e62914e816a76fc6bd"}, + {file = "pillow-10.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:81d09caa7b27ef4e61cb7d8fbf1714f5aec1c6b6c5270ee53504981e6e9121ad"}, + {file = "pillow-10.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:048ad577748b9fa4a99a0548c64f2cb8d672d5bf2e643a739ac8faff1164238c"}, + {file = "pillow-10.3.0-cp311-cp311-win32.whl", hash = "sha256:7161ec49ef0800947dc5570f86568a7bb36fa97dd09e9827dc02b718c5643f09"}, + {file = "pillow-10.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:8eb0908e954d093b02a543dc963984d6e99ad2b5e36503d8a0aaf040505f747d"}, + {file = "pillow-10.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:4e6f7d1c414191c1199f8996d3f2282b9ebea0945693fb67392c75a3a320941f"}, + {file = "pillow-10.3.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:e46f38133e5a060d46bd630faa4d9fa0202377495df1f068a8299fd78c84de84"}, + {file = "pillow-10.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:50b8eae8f7334ec826d6eeffaeeb00e36b5e24aa0b9df322c247539714c6df19"}, + {file = "pillow-10.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d3bea1c75f8c53ee4d505c3e67d8c158ad4df0d83170605b50b64025917f338"}, + {file = "pillow-10.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19aeb96d43902f0a783946a0a87dbdad5c84c936025b8419da0a0cd7724356b1"}, + {file = "pillow-10.3.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:74d28c17412d9caa1066f7a31df8403ec23d5268ba46cd0ad2c50fb82ae40462"}, + {file = "pillow-10.3.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:ff61bfd9253c3915e6d41c651d5f962da23eda633cf02262990094a18a55371a"}, + {file = "pillow-10.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d886f5d353333b4771d21267c7ecc75b710f1a73d72d03ca06df49b09015a9ef"}, + {file = "pillow-10.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b5ec25d8b17217d635f8935dbc1b9aa5907962fae29dff220f2659487891cd3"}, + {file = "pillow-10.3.0-cp312-cp312-win32.whl", hash = "sha256:51243f1ed5161b9945011a7360e997729776f6e5d7005ba0c6879267d4c5139d"}, + {file = "pillow-10.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:412444afb8c4c7a6cc11a47dade32982439925537e483be7c0ae0cf96c4f6a0b"}, + {file = "pillow-10.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:798232c92e7665fe82ac085f9d8e8ca98826f8e27859d9a96b41d519ecd2e49a"}, + {file = "pillow-10.3.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:4eaa22f0d22b1a7e93ff0a596d57fdede2e550aecffb5a1ef1106aaece48e96b"}, + {file = "pillow-10.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cd5e14fbf22a87321b24c88669aad3a51ec052eb145315b3da3b7e3cc105b9a2"}, + {file = "pillow-10.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1530e8f3a4b965eb6a7785cf17a426c779333eb62c9a7d1bbcf3ffd5bf77a4aa"}, + {file = "pillow-10.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d512aafa1d32efa014fa041d38868fda85028e3f930a96f85d49c7d8ddc0383"}, + {file = "pillow-10.3.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:339894035d0ede518b16073bdc2feef4c991ee991a29774b33e515f1d308e08d"}, + {file = "pillow-10.3.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:aa7e402ce11f0885305bfb6afb3434b3cd8f53b563ac065452d9d5654c7b86fd"}, + {file = "pillow-10.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0ea2a783a2bdf2a561808fe4a7a12e9aa3799b701ba305de596bc48b8bdfce9d"}, + {file = "pillow-10.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c78e1b00a87ce43bb37642c0812315b411e856a905d58d597750eb79802aaaa3"}, + {file = "pillow-10.3.0-cp38-cp38-win32.whl", hash = "sha256:72d622d262e463dfb7595202d229f5f3ab4b852289a1cd09650362db23b9eb0b"}, + {file = "pillow-10.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:2034f6759a722da3a3dbd91a81148cf884e91d1b747992ca288ab88c1de15999"}, + {file = "pillow-10.3.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:2ed854e716a89b1afcedea551cd85f2eb2a807613752ab997b9974aaa0d56936"}, + {file = "pillow-10.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:dc1a390a82755a8c26c9964d457d4c9cbec5405896cba94cf51f36ea0d855002"}, + {file = "pillow-10.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4203efca580f0dd6f882ca211f923168548f7ba334c189e9eab1178ab840bf60"}, + {file = "pillow-10.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3102045a10945173d38336f6e71a8dc71bcaeed55c3123ad4af82c52807b9375"}, + {file = "pillow-10.3.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:6fb1b30043271ec92dc65f6d9f0b7a830c210b8a96423074b15c7bc999975f57"}, + {file = "pillow-10.3.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:1dfc94946bc60ea375cc39cff0b8da6c7e5f8fcdc1d946beb8da5c216156ddd8"}, + {file = "pillow-10.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b09b86b27a064c9624d0a6c54da01c1beaf5b6cadfa609cf63789b1d08a797b9"}, + {file = "pillow-10.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d3b2348a78bc939b4fed6552abfd2e7988e0f81443ef3911a4b8498ca084f6eb"}, + {file = "pillow-10.3.0-cp39-cp39-win32.whl", hash = "sha256:45ebc7b45406febf07fef35d856f0293a92e7417ae7933207e90bf9090b70572"}, + {file = "pillow-10.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:0ba26351b137ca4e0db0342d5d00d2e355eb29372c05afd544ebf47c0956ffeb"}, + {file = "pillow-10.3.0-cp39-cp39-win_arm64.whl", hash = "sha256:50fd3f6b26e3441ae07b7c979309638b72abc1a25da31a81a7fbd9495713ef4f"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:6b02471b72526ab8a18c39cb7967b72d194ec53c1fd0a70b050565a0f366d355"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8ab74c06ffdab957d7670c2a5a6e1a70181cd10b727cd788c4dd9005b6a8acd9"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:048eeade4c33fdf7e08da40ef402e748df113fd0b4584e32c4af74fe78baaeb2"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e2ec1e921fd07c7cda7962bad283acc2f2a9ccc1b971ee4b216b75fad6f0463"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:4c8e73e99da7db1b4cad7f8d682cf6abad7844da39834c288fbfa394a47bbced"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:16563993329b79513f59142a6b02055e10514c1a8e86dca8b48a893e33cf91e3"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:dd78700f5788ae180b5ee8902c6aea5a5726bac7c364b202b4b3e3ba2d293170"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:aff76a55a8aa8364d25400a210a65ff59d0168e0b4285ba6bf2bd83cf675ba32"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:b7bc2176354defba3edc2b9a777744462da2f8e921fbaf61e52acb95bafa9828"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:793b4e24db2e8742ca6423d3fde8396db336698c55cd34b660663ee9e45ed37f"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d93480005693d247f8346bc8ee28c72a2191bdf1f6b5db469c096c0c867ac015"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c83341b89884e2b2e55886e8fbbf37c3fa5efd6c8907124aeb72f285ae5696e5"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1a1d1915db1a4fdb2754b9de292642a39a7fb28f1736699527bb649484fb966a"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a0eaa93d054751ee9964afa21c06247779b90440ca41d184aeb5d410f20ff591"}, + {file = "pillow-10.3.0.tar.gz", hash = "sha256:9d2455fbf44c914840c793e89aa82d0e1763a14253a000743719ae5946814b2d"}, ] [package.extras] @@ -5405,13 +6119,13 @@ xmp = ["defusedxml"] [[package]] name = "pinecone-client" -version = "3.2.1" +version = "3.2.2" description = "Pinecone client and SDK" optional = false python-versions = "<4.0,>=3.8" files = [ - {file = "pinecone_client-3.2.1-py3-none-any.whl", hash = "sha256:e3e7983762509235250b9bcd543ec6283b7dffaed2e899f1631327f2b77859e3"}, - {file = "pinecone_client-3.2.1.tar.gz", hash = "sha256:8560ffafb13b9c45a92eb9eb77a2db32d5a1fa7903a1db17f7af58ee1058bb60"}, + {file = "pinecone_client-3.2.2-py3-none-any.whl", hash = "sha256:7e492fdda23c73726bc0cb94c689bb950d06fb94e82b701a0c610c2e830db327"}, + {file = "pinecone_client-3.2.2.tar.gz", hash = "sha256:887a12405f90ac11c396490f605fc479f31cf282361034d1ae0fccc02ac75bee"}, ] [package.dependencies] @@ -5914,6 +6628,17 @@ files = [ [package.dependencies] numpy = ">=1.16.6" +[[package]] +name = "pyarrow-hotfix" +version = "0.6" +description = "" +optional = false +python-versions = ">=3.5" +files = [ + {file = "pyarrow_hotfix-0.6-py3-none-any.whl", hash = "sha256:dcc9ae2d220dff0083be6a9aa8e0cdee5182ad358d4931fce825c545e5c89178"}, + {file = "pyarrow_hotfix-0.6.tar.gz", hash = "sha256:79d3e030f7ff890d408a100ac16d6f00b14d44a502d7897cd9fc3e3a534e9945"}, +] + [[package]] name = "pyasn1" version = "0.6.0" @@ -5978,13 +6703,13 @@ websurfer = ["beautifulsoup4", "markdownify", "pathvalidate", "pdfminer.six"] [[package]] name = "pycparser" -version = "2.21" +version = "2.22" description = "C parser in Python" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.8" files = [ - {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, - {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, + {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, + {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, ] [[package]] @@ -6030,18 +6755,18 @@ files = [ [[package]] name = "pydantic" -version = "2.6.4" +version = "2.5.0" description = "Data validation using Python type hints" optional = false -python-versions = ">=3.8" +python-versions = ">=3.7" files = [ - {file = "pydantic-2.6.4-py3-none-any.whl", hash = "sha256:cc46fce86607580867bdc3361ad462bab9c222ef042d3da86f2fb333e1d916c5"}, - {file = "pydantic-2.6.4.tar.gz", hash = "sha256:b1704e0847db01817624a6b86766967f552dd9dbf3afba4004409f908dcc84e6"}, + {file = "pydantic-2.5.0-py3-none-any.whl", hash = "sha256:7ce6e766c456ad026fe5712f7bcf036efc34bd5d107b3e669ef7ea01b3a9050c"}, + {file = "pydantic-2.5.0.tar.gz", hash = "sha256:69bd6fb62d2d04b7055f59a396993486a2ee586c43a0b89231ce0000de07627c"}, ] [package.dependencies] annotated-types = ">=0.4.0" -pydantic-core = "2.16.3" +pydantic-core = "2.14.1" typing-extensions = ">=4.6.1" [package.extras] @@ -6049,90 +6774,112 @@ email = ["email-validator (>=2.0.0)"] [[package]] name = "pydantic-core" -version = "2.16.3" +version = "2.14.1" description = "" optional = false -python-versions = ">=3.8" +python-versions = ">=3.7" files = [ - {file = "pydantic_core-2.16.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:75b81e678d1c1ede0785c7f46690621e4c6e63ccd9192af1f0bd9d504bbb6bf4"}, - {file = "pydantic_core-2.16.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9c865a7ee6f93783bd5d781af5a4c43dadc37053a5b42f7d18dc019f8c9d2bd1"}, - {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:162e498303d2b1c036b957a1278fa0899d02b2842f1ff901b6395104c5554a45"}, - {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f583bd01bbfbff4eaee0868e6fc607efdfcc2b03c1c766b06a707abbc856187"}, - {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b926dd38db1519ed3043a4de50214e0d600d404099c3392f098a7f9d75029ff8"}, - {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:716b542728d4c742353448765aa7cdaa519a7b82f9564130e2b3f6766018c9ec"}, - {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc4ad7f7ee1a13d9cb49d8198cd7d7e3aa93e425f371a68235f784e99741561f"}, - {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd87f48924f360e5d1c5f770d6155ce0e7d83f7b4e10c2f9ec001c73cf475c99"}, - {file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0df446663464884297c793874573549229f9eca73b59360878f382a0fc085979"}, - {file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4df8a199d9f6afc5ae9a65f8f95ee52cae389a8c6b20163762bde0426275b7db"}, - {file = "pydantic_core-2.16.3-cp310-none-win32.whl", hash = "sha256:456855f57b413f077dff513a5a28ed838dbbb15082ba00f80750377eed23d132"}, - {file = "pydantic_core-2.16.3-cp310-none-win_amd64.whl", hash = "sha256:732da3243e1b8d3eab8c6ae23ae6a58548849d2e4a4e03a1924c8ddf71a387cb"}, - {file = "pydantic_core-2.16.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:519ae0312616026bf4cedc0fe459e982734f3ca82ee8c7246c19b650b60a5ee4"}, - {file = "pydantic_core-2.16.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b3992a322a5617ded0a9f23fd06dbc1e4bd7cf39bc4ccf344b10f80af58beacd"}, - {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d62da299c6ecb04df729e4b5c52dc0d53f4f8430b4492b93aa8de1f541c4aac"}, - {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2acca2be4bb2f2147ada8cac612f8a98fc09f41c89f87add7256ad27332c2fda"}, - {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b662180108c55dfbf1280d865b2d116633d436cfc0bba82323554873967b340"}, - {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e7c6ed0dc9d8e65f24f5824291550139fe6f37fac03788d4580da0d33bc00c97"}, - {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1bb0827f56654b4437955555dc3aeeebeddc47c2d7ed575477f082622c49e"}, - {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e56f8186d6210ac7ece503193ec84104da7ceb98f68ce18c07282fcc2452e76f"}, - {file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:936e5db01dd49476fa8f4383c259b8b1303d5dd5fb34c97de194560698cc2c5e"}, - {file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:33809aebac276089b78db106ee692bdc9044710e26f24a9a2eaa35a0f9fa70ba"}, - {file = "pydantic_core-2.16.3-cp311-none-win32.whl", hash = "sha256:ded1c35f15c9dea16ead9bffcde9bb5c7c031bff076355dc58dcb1cb436c4721"}, - {file = "pydantic_core-2.16.3-cp311-none-win_amd64.whl", hash = "sha256:d89ca19cdd0dd5f31606a9329e309d4fcbb3df860960acec32630297d61820df"}, - {file = "pydantic_core-2.16.3-cp311-none-win_arm64.whl", hash = "sha256:6162f8d2dc27ba21027f261e4fa26f8bcb3cf9784b7f9499466a311ac284b5b9"}, - {file = "pydantic_core-2.16.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0f56ae86b60ea987ae8bcd6654a887238fd53d1384f9b222ac457070b7ac4cff"}, - {file = "pydantic_core-2.16.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9bd22a2a639e26171068f8ebb5400ce2c1bc7d17959f60a3b753ae13c632975"}, - {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4204e773b4b408062960e65468d5346bdfe139247ee5f1ca2a378983e11388a2"}, - {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f651dd19363c632f4abe3480a7c87a9773be27cfe1341aef06e8759599454120"}, - {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aaf09e615a0bf98d406657e0008e4a8701b11481840be7d31755dc9f97c44053"}, - {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8e47755d8152c1ab5b55928ab422a76e2e7b22b5ed8e90a7d584268dd49e9c6b"}, - {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:500960cb3a0543a724a81ba859da816e8cf01b0e6aaeedf2c3775d12ee49cade"}, - {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cf6204fe865da605285c34cf1172879d0314ff267b1c35ff59de7154f35fdc2e"}, - {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d33dd21f572545649f90c38c227cc8631268ba25c460b5569abebdd0ec5974ca"}, - {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:49d5d58abd4b83fb8ce763be7794d09b2f50f10aa65c0f0c1696c677edeb7cbf"}, - {file = "pydantic_core-2.16.3-cp312-none-win32.whl", hash = "sha256:f53aace168a2a10582e570b7736cc5bef12cae9cf21775e3eafac597e8551fbe"}, - {file = "pydantic_core-2.16.3-cp312-none-win_amd64.whl", hash = "sha256:0d32576b1de5a30d9a97f300cc6a3f4694c428d956adbc7e6e2f9cad279e45ed"}, - {file = "pydantic_core-2.16.3-cp312-none-win_arm64.whl", hash = "sha256:ec08be75bb268473677edb83ba71e7e74b43c008e4a7b1907c6d57e940bf34b6"}, - {file = "pydantic_core-2.16.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b1f6f5938d63c6139860f044e2538baeee6f0b251a1816e7adb6cbce106a1f01"}, - {file = "pydantic_core-2.16.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2a1ef6a36fdbf71538142ed604ad19b82f67b05749512e47f247a6ddd06afdc7"}, - {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:704d35ecc7e9c31d48926150afada60401c55efa3b46cd1ded5a01bdffaf1d48"}, - {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d937653a696465677ed583124b94a4b2d79f5e30b2c46115a68e482c6a591c8a"}, - {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9803edf8e29bd825f43481f19c37f50d2b01899448273b3a7758441b512acf8"}, - {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:72282ad4892a9fb2da25defeac8c2e84352c108705c972db82ab121d15f14e6d"}, - {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f752826b5b8361193df55afcdf8ca6a57d0232653494ba473630a83ba50d8c9"}, - {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4384a8f68ddb31a0b0c3deae88765f5868a1b9148939c3f4121233314ad5532c"}, - {file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a4b2bf78342c40b3dc830880106f54328928ff03e357935ad26c7128bbd66ce8"}, - {file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:13dcc4802961b5f843a9385fc821a0b0135e8c07fc3d9949fd49627c1a5e6ae5"}, - {file = "pydantic_core-2.16.3-cp38-none-win32.whl", hash = "sha256:e3e70c94a0c3841e6aa831edab1619ad5c511199be94d0c11ba75fe06efe107a"}, - {file = "pydantic_core-2.16.3-cp38-none-win_amd64.whl", hash = "sha256:ecdf6bf5f578615f2e985a5e1f6572e23aa632c4bd1dc67f8f406d445ac115ed"}, - {file = "pydantic_core-2.16.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:bda1ee3e08252b8d41fa5537413ffdddd58fa73107171a126d3b9ff001b9b820"}, - {file = "pydantic_core-2.16.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:21b888c973e4f26b7a96491c0965a8a312e13be108022ee510248fe379a5fa23"}, - {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be0ec334369316fa73448cc8c982c01e5d2a81c95969d58b8f6e272884df0074"}, - {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5b6079cc452a7c53dd378c6f881ac528246b3ac9aae0f8eef98498a75657805"}, - {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ee8d5f878dccb6d499ba4d30d757111847b6849ae07acdd1205fffa1fc1253c"}, - {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7233d65d9d651242a68801159763d09e9ec96e8a158dbf118dc090cd77a104c9"}, - {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6119dc90483a5cb50a1306adb8d52c66e447da88ea44f323e0ae1a5fcb14256"}, - {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:578114bc803a4c1ff9946d977c221e4376620a46cf78da267d946397dc9514a8"}, - {file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d8f99b147ff3fcf6b3cc60cb0c39ea443884d5559a30b1481e92495f2310ff2b"}, - {file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4ac6b4ce1e7283d715c4b729d8f9dab9627586dafce81d9eaa009dd7f25dd972"}, - {file = "pydantic_core-2.16.3-cp39-none-win32.whl", hash = "sha256:e7774b570e61cb998490c5235740d475413a1f6de823169b4cf94e2fe9e9f6b2"}, - {file = "pydantic_core-2.16.3-cp39-none-win_amd64.whl", hash = "sha256:9091632a25b8b87b9a605ec0e61f241c456e9248bfdcf7abdf344fdb169c81cf"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:36fa178aacbc277bc6b62a2c3da95226520da4f4e9e206fdf076484363895d2c"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:dcca5d2bf65c6fb591fff92da03f94cd4f315972f97c21975398bd4bd046854a"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a72fb9963cba4cd5793854fd12f4cfee731e86df140f59ff52a49b3552db241"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b60cc1a081f80a2105a59385b92d82278b15d80ebb3adb200542ae165cd7d183"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cbcc558401de90a746d02ef330c528f2e668c83350f045833543cd57ecead1ad"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:fee427241c2d9fb7192b658190f9f5fd6dfe41e02f3c1489d2ec1e6a5ab1e04a"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f4cb85f693044e0f71f394ff76c98ddc1bc0953e48c061725e540396d5c8a2e1"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b29eeb887aa931c2fcef5aa515d9d176d25006794610c264ddc114c053bf96fe"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a425479ee40ff021f8216c9d07a6a3b54b31c8267c6e17aa88b70d7ebd0e5e5b"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5c5cbc703168d1b7a838668998308018a2718c2130595e8e190220238addc96f"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99b6add4c0b39a513d323d3b93bc173dac663c27b99860dd5bf491b240d26137"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f76ee558751746d6a38f89d60b6228fa174e5172d143886af0f85aa306fd89"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:00ee1c97b5364b84cb0bd82e9bbf645d5e2871fb8c58059d158412fee2d33d8a"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:287073c66748f624be4cef893ef9174e3eb88fe0b8a78dc22e88eca4bc357ca6"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ed25e1835c00a332cb10c683cd39da96a719ab1dfc08427d476bce41b92531fc"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:86b3d0033580bd6bbe07590152007275bd7af95f98eaa5bd36f3da219dcd93da"}, - {file = "pydantic_core-2.16.3.tar.gz", hash = "sha256:1cac689f80a3abab2d3c0048b29eea5751114054f032a941a32de4c852c59cad"}, + {file = "pydantic_core-2.14.1-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:812beca1dcb2b722cccc7e9c620bd972cbc323321194ec2725eab3222e6ac573"}, + {file = "pydantic_core-2.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a2ccdc53cb88e51c7d47d74c59630d7be844428f6b8d463055ffad6f0392d8da"}, + {file = "pydantic_core-2.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd937733bf2fe7d6a8bf208c12741f1f730b7bf5636033877767a75093c29b8a"}, + {file = "pydantic_core-2.14.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:581bb606a31749a00796f5257947a0968182d7fe91e1dada41f06aeb6bfbc91a"}, + {file = "pydantic_core-2.14.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aadf74a40a7ae49c3c1aa7d32334fe94f4f968e21dd948e301bb4ed431fb2412"}, + {file = "pydantic_core-2.14.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b89821a2c77cc1b8f2c1fc3aacd6a3ecc5df8f7e518dc3f18aef8c4dcf66003d"}, + {file = "pydantic_core-2.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49ee28d65f506b2858a60745cc974ed005298ebab12693646b97641dd7c99c35"}, + {file = "pydantic_core-2.14.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:97246f896b4df7fd84caa8a75a67abb95f94bc0b547665bf0889e3262b060399"}, + {file = "pydantic_core-2.14.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:1185548665bc61bbab0dc78f10c8eafa0db0aa1e920fe9a451b77782b10a65cc"}, + {file = "pydantic_core-2.14.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2a7d08b39fac97540fba785fce3b21ee01a81f081a07a4d031efd791da6666f9"}, + {file = "pydantic_core-2.14.1-cp310-none-win32.whl", hash = "sha256:0a8c8daf4e3aa3aeb98e3638fc3d58a359738f3d12590b2474c6bb64031a0764"}, + {file = "pydantic_core-2.14.1-cp310-none-win_amd64.whl", hash = "sha256:4f0788699a92d604f348e9c1ac5e97e304e97127ba8325c7d0af88dcc7d35bd3"}, + {file = "pydantic_core-2.14.1-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:2be018a84995b6be1bbd40d6064395dbf71592a981169cf154c0885637f5f54a"}, + {file = "pydantic_core-2.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fc3227408808ba7df8e95eb1d8389f4ba2203bed8240b308de1d7ae66d828f24"}, + {file = "pydantic_core-2.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42d5d0e9bbb50481a049bd0203224b339d4db04006b78564df2b782e2fd16ebc"}, + {file = "pydantic_core-2.14.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bc6a4ea9f88a810cb65ccae14404da846e2a02dd5c0ad21dee712ff69d142638"}, + {file = "pydantic_core-2.14.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d312ad20e3c6d179cb97c42232b53111bcd8dcdd5c1136083db9d6bdd489bc73"}, + {file = "pydantic_core-2.14.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:679cc4e184f213c8227862e57340d12fd4d4d19dc0e3ddb0f653f86f01e90f94"}, + {file = "pydantic_core-2.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101df420e954966868b8bc992aefed5fa71dd1f2755104da62ee247abab28e2f"}, + {file = "pydantic_core-2.14.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c964c0cc443d6c08a2347c0e5c1fc2d85a272dc66c1a6f3cde4fc4843882ada4"}, + {file = "pydantic_core-2.14.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8276bbab68a9dbe721da92d19cbc061f76655248fe24fb63969d0c3e0e5755e7"}, + {file = "pydantic_core-2.14.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:12163197fec7c95751a3c71b36dcc1909eed9959f011ffc79cc8170a6a74c826"}, + {file = "pydantic_core-2.14.1-cp311-none-win32.whl", hash = "sha256:b8ff0302518dcd001bd722bbe342919c29e5066c7eda86828fe08cdc112668b8"}, + {file = "pydantic_core-2.14.1-cp311-none-win_amd64.whl", hash = "sha256:59fa83873223f856d898452c6162a390af4297756f6ba38493a67533387d85d9"}, + {file = "pydantic_core-2.14.1-cp311-none-win_arm64.whl", hash = "sha256:798590d38c9381f07c48d13af1f1ef337cebf76ee452fcec5deb04aceced51c7"}, + {file = "pydantic_core-2.14.1-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:587d75aec9ae50d0d63788cec38bf13c5128b3fc1411aa4b9398ebac884ab179"}, + {file = "pydantic_core-2.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:26242e3593d4929123615bd9365dd86ef79b7b0592d64a96cd11fd83c69c9f34"}, + {file = "pydantic_core-2.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5879ac4791508d8f0eb7dec71ff8521855180688dac0c55f8c99fc4d1a939845"}, + {file = "pydantic_core-2.14.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ad9ea86f5fc50f1b62c31184767fe0cacaa13b54fe57d38898c3776d30602411"}, + {file = "pydantic_core-2.14.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:102ac85a775e77821943ae38da9634ddd774b37a8d407181b4f7b05cdfb36b55"}, + {file = "pydantic_core-2.14.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2459cc06572730e079ec1e694e8f68c99d977b40d98748ae72ff11ef21a56b0b"}, + {file = "pydantic_core-2.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:217dcbfaf429a9b8f1d54eb380908b9c778e78f31378283b30ba463c21e89d5d"}, + {file = "pydantic_core-2.14.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9d59e0d7cdfe8ed1d4fcd28aad09625c715dc18976c7067e37d8a11b06f4be3e"}, + {file = "pydantic_core-2.14.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e2be646a5155d408e68b560c0553e8a83dc7b9f90ec6e5a2fc3ff216719385db"}, + {file = "pydantic_core-2.14.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ffba979801e3931a19cd30ed2049450820effe8f152aaa317e2fd93795d318d7"}, + {file = "pydantic_core-2.14.1-cp312-none-win32.whl", hash = "sha256:132b40e479cb5cebbbb681f77aaceabbc8355df16c9124cff1d4060ada83cde2"}, + {file = "pydantic_core-2.14.1-cp312-none-win_amd64.whl", hash = "sha256:744b807fe2733b6da3b53e8ad93e8b3ea3ee3dfc3abece4dd2824cc1f39aa343"}, + {file = "pydantic_core-2.14.1-cp312-none-win_arm64.whl", hash = "sha256:24ba48f9d0b8d64fc5e42e1600366c3d7db701201294989aebdaca23110c02ab"}, + {file = "pydantic_core-2.14.1-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:ba55d73a2df4771b211d0bcdea8b79454980a81ed34a1d77a19ddcc81f98c895"}, + {file = "pydantic_core-2.14.1-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:e905014815687d88cbb14bbc0496420526cf20d49f20606537d87646b70f1046"}, + {file = "pydantic_core-2.14.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:443dc5eede7fa76b2370213e0abe881eb17c96f7d694501853c11d5d56916602"}, + {file = "pydantic_core-2.14.1-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:abae6fd5504e5e438e4f6f739f8364fd9ff5a5cdca897e68363e2318af90bc28"}, + {file = "pydantic_core-2.14.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9486e27bb3f137f33e2315be2baa0b0b983dae9e2f5f5395240178ad8e644728"}, + {file = "pydantic_core-2.14.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:69df82892ff00491d673b1929538efb8c8d68f534fdc6cb7fd3ac8a5852b9034"}, + {file = "pydantic_core-2.14.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:184ff7b30c3f60e1b775378c060099285fd4b5249271046c9005f8b247b39377"}, + {file = "pydantic_core-2.14.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3d5b2a4b3c10cad0615670cab99059441ff42e92cf793a0336f4bc611e895204"}, + {file = "pydantic_core-2.14.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:871c641a83719caaa856a11dcc61c5e5b35b0db888e1a0d338fe67ce744575e2"}, + {file = "pydantic_core-2.14.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:1e7208946ea9b27a8cef13822c339d4ae96e45952cc01fc4a91c7f1cb0ae2861"}, + {file = "pydantic_core-2.14.1-cp37-none-win32.whl", hash = "sha256:b4ff385a525017f5adf6066d7f9fb309f99ade725dcf17ed623dc7dce1f85d9f"}, + {file = "pydantic_core-2.14.1-cp37-none-win_amd64.whl", hash = "sha256:c7411cd06afeb263182e38c6ca5b4f5fe4f20d91466ad7db0cd6af453a02edec"}, + {file = "pydantic_core-2.14.1-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:2871daf5b2823bf77bf7d3d43825e5d904030c155affdf84b21a00a2e00821d2"}, + {file = "pydantic_core-2.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7977e261cac5f99873dc2c6f044315d09b19a71c4246560e1e67593889a90978"}, + {file = "pydantic_core-2.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5a111f9158555582deadd202a60bd7803b6c68f406391b7cf6905adf0af6811"}, + {file = "pydantic_core-2.14.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac417312bf6b7a0223ba73fb12e26b2854c93bf5b1911f7afef6d24c379b22aa"}, + {file = "pydantic_core-2.14.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c36987f5eb2a7856b5f5feacc3be206b4d1852a6ce799f6799dd9ffb0cba56ae"}, + {file = "pydantic_core-2.14.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6e98227eb02623d57e1fd061788837834b68bb995a869565211b9abf3de4bf4"}, + {file = "pydantic_core-2.14.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:023b6d7ec4e97890b28eb2ee24413e69a6d48de4e8b75123957edd5432f4eeb3"}, + {file = "pydantic_core-2.14.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6015beb28deb5306049ecf2519a59627e9e050892927850a884df6d5672f8c7d"}, + {file = "pydantic_core-2.14.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3f48d4afd973abbd65266ac24b24de1591116880efc7729caf6b6b94a9654c9e"}, + {file = "pydantic_core-2.14.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:28734bcfb8fc5b03293dec5eb5ea73b32ff767f6ef79a31f6e41dad2f5470270"}, + {file = "pydantic_core-2.14.1-cp38-none-win32.whl", hash = "sha256:3303113fdfaca927ef11e0c5f109e2ec196c404f9d7ba5f8ddb63cdf287ea159"}, + {file = "pydantic_core-2.14.1-cp38-none-win_amd64.whl", hash = "sha256:144f2c1d5579108b6ed1193fcc9926124bd4142b0f7020a7744980d1235c8a40"}, + {file = "pydantic_core-2.14.1-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:893bf4fb9bfb9c4639bc12f3de323325ada4c6d60e478d5cded65453e9364890"}, + {file = "pydantic_core-2.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:052d8731aaf844f91fe4cd3faf28983b109a5865b3a256ec550b80a5689ead87"}, + {file = "pydantic_core-2.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb1c6ecb53e4b907ee8486f453dd940b8cbb509946e2b671e3bf807d310a96fc"}, + {file = "pydantic_core-2.14.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:94cf6d0274eb899d39189144dcf52814c67f9b0fd196f211420d9aac793df2da"}, + {file = "pydantic_core-2.14.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:36c3bf96f803e207a80dbcb633d82b98ff02a9faa76dd446e969424dec8e2b9f"}, + {file = "pydantic_core-2.14.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fb290491f1f0786a7da4585250f1feee200fc17ff64855bdd7c42fb54526fa29"}, + {file = "pydantic_core-2.14.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6590ed9d13eb51b28ea17ddcc6c8dbd6050b4eb589d497105f0e13339f223b72"}, + {file = "pydantic_core-2.14.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:69cd74e55a5326d920e7b46daa2d81c2bdb8bcf588eafb2330d981297b742ddc"}, + {file = "pydantic_core-2.14.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d965bdb50725a805b083f5f58d05669a85705f50a6a864e31b545c589290ee31"}, + {file = "pydantic_core-2.14.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ca942a2dc066ca5e04c27feaa8dfb9d353ddad14c6641660c565149186095343"}, + {file = "pydantic_core-2.14.1-cp39-none-win32.whl", hash = "sha256:72c2ef3787c3b577e5d6225d73a77167b942d12cef3c1fbd5e74e55b7f881c36"}, + {file = "pydantic_core-2.14.1-cp39-none-win_amd64.whl", hash = "sha256:55713d155da1e508083c4b08d0b1ad2c3054f68b8ef7eb3d3864822e456f0bb5"}, + {file = "pydantic_core-2.14.1-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:53efe03cc383a83660cfdda6a3cb40ee31372cedea0fde0b2a2e55e838873ab6"}, + {file = "pydantic_core-2.14.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f523e116879bc6714e61d447ce934676473b068069dce6563ea040381dc7a257"}, + {file = "pydantic_core-2.14.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85bb66d661be51b2cba9ca06759264b3469d2dbb53c3e6effb3f05fec6322be6"}, + {file = "pydantic_core-2.14.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f53a3ccdc30234cb4342cec541e3e6ed87799c7ca552f0b5f44e3967a5fed526"}, + {file = "pydantic_core-2.14.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:1bfb63821ada76719ffcd703fc40dd57962e0d8c253e3c565252e6de6d3e0bc6"}, + {file = "pydantic_core-2.14.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e2c689439f262c29cf3fcd5364da1e64d8600facecf9eabea8643b8755d2f0de"}, + {file = "pydantic_core-2.14.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a15f6e5588f7afb7f6fc4b0f4ff064749e515d34f34c666ed6e37933873d8ad8"}, + {file = "pydantic_core-2.14.1-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:f1a30eef060e21af22c7d23349f1028de0611f522941c80efa51c05a63142c62"}, + {file = "pydantic_core-2.14.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16f4a7e1ec6b3ea98a1e108a2739710cd659d68b33fbbeaba066202cab69c7b6"}, + {file = "pydantic_core-2.14.1-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fd80a2d383940eec3db6a5b59d1820f947317acc5c75482ff8d79bf700f8ad6a"}, + {file = "pydantic_core-2.14.1-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:a68a36d71c7f638dda6c9e6b67f6aabf3fa1471b198d246457bfdc7c777cdeb7"}, + {file = "pydantic_core-2.14.1-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ebc79120e105e4bcd7865f369e3b9dbabb0d492d221e1a7f62a3e8e292550278"}, + {file = "pydantic_core-2.14.1-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:c8c466facec2ccdf025b0b1455b18f2c3d574d5f64d24df905d3d7b8f05d5f4e"}, + {file = "pydantic_core-2.14.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b91b5ec423e88caa16777094c4b2b97f11453283e7a837e5e5e1b886abba1251"}, + {file = "pydantic_core-2.14.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:130e49aa0cb316f743bc7792c36aefa39fc2221312f1d4b333b19edbdd71f2b1"}, + {file = "pydantic_core-2.14.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f483467c046f549572f8aca3b7128829e09ae3a9fe933ea421f7cb7c58120edb"}, + {file = "pydantic_core-2.14.1-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:dee4682bd7947afc682d342a8d65ad1834583132383f8e801601a8698cb8d17a"}, + {file = "pydantic_core-2.14.1-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:8d927d042c0ef04607ee7822828b208ab045867d20477ec6593d612156798547"}, + {file = "pydantic_core-2.14.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5a1570875eb0d1479fb2270ed80c88c231aaaf68b0c3f114f35e7fb610435e4f"}, + {file = "pydantic_core-2.14.1-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:cb2fd3ab67558eb16aecfb4f2db4febb4d37dc74e6b8613dc2e7160fb58158a9"}, + {file = "pydantic_core-2.14.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a7991f25b98038252363a03e6a9fe92e60fe390fda2631d238dc3b0e396632f8"}, + {file = "pydantic_core-2.14.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b45b7be9f99991405ecd6f6172fb6798908a8097106ae78d5cc5cc15121bad9"}, + {file = "pydantic_core-2.14.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:51506e7652a2ef1d1cf763c4b51b972ff4568d1dddc96ca83931a6941f5e6389"}, + {file = "pydantic_core-2.14.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:66dc0e63349ec39c1ea66622aa5c2c1f84382112afd3ab2fa0cca4fb01f7db39"}, + {file = "pydantic_core-2.14.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:8e17f0c3ba4cb07faa0038a59ce162de584ed48ba645c8d05a5de1e40d4c21e7"}, + {file = "pydantic_core-2.14.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d983222223f63e323a5f497f5b85e211557a5d8fb670dc88f343784502b466ba"}, + {file = "pydantic_core-2.14.1.tar.gz", hash = "sha256:0d82a6ee815388a362885186e431fac84c7a06623bc136f508e9f88261d8cadb"}, ] [package.dependencies] @@ -6275,6 +7022,64 @@ snappy = ["python-snappy"] test = ["pytest (>=7)"] zstd = ["zstandard"] +[[package]] +name = "pymupdf" +version = "1.24.1" +description = "A high performance Python library for data extraction, analysis, conversion & manipulation of PDF (and other) documents." +optional = false +python-versions = ">=3.8" +files = [ + {file = "PyMuPDF-1.24.1-cp310-none-macosx_10_9_x86_64.whl", hash = "sha256:6427aee313e24447f57edbfc7a28aa6bbca007fe0ad77603f54a371c6c510eeb"}, + {file = "PyMuPDF-1.24.1-cp310-none-macosx_11_0_arm64.whl", hash = "sha256:12078c0bee337de969dbd6d89ef446312794d74db365cb9ac14902b863b35414"}, + {file = "PyMuPDF-1.24.1-cp310-none-manylinux2014_aarch64.whl", hash = "sha256:73f86eefd7f3878f112fa10791aa2e63934cf59a4c024dd54cd6fe94443c352c"}, + {file = "PyMuPDF-1.24.1-cp310-none-manylinux2014_x86_64.whl", hash = "sha256:caf6ceb1dbebe9f70bf7dd683cc91b896604a7c62873e5b50089f9e85e85c517"}, + {file = "PyMuPDF-1.24.1-cp310-none-win32.whl", hash = "sha256:468a8bb2b95828e0f6739fbfe509700cc0dac600f756d8cb6316316e1eba9689"}, + {file = "PyMuPDF-1.24.1-cp310-none-win_amd64.whl", hash = "sha256:e47504391908e2d721c743aed36196310a5e15355a85459c1c4ddcf8f2002fbe"}, + {file = "PyMuPDF-1.24.1-cp311-none-macosx_10_9_x86_64.whl", hash = "sha256:c54ff927257b432ffd39dc6a0a46bd1120e85d192100efca021f27d4b881cfd6"}, + {file = "PyMuPDF-1.24.1-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:6d412da9f9a73f66973eea4284776f292135906700a06c39122e862a1e3ccf58"}, + {file = "PyMuPDF-1.24.1-cp311-none-manylinux2014_aarch64.whl", hash = "sha256:95a54611abb7322f5b10b44cbf19b605ed172df2c4c7995ad78854bc8423dd9c"}, + {file = "PyMuPDF-1.24.1-cp311-none-manylinux2014_x86_64.whl", hash = "sha256:9a3b21c8fc274ff42855ca2da65961e2319b05b75ef9e2caf25c04f9083ec79c"}, + {file = "PyMuPDF-1.24.1-cp311-none-win32.whl", hash = "sha256:8a81106a8bc229823736487d2492fd3af724a94521a1cd9b67849dd04b9c31ed"}, + {file = "PyMuPDF-1.24.1-cp311-none-win_amd64.whl", hash = "sha256:de5b6c4db4a2a9f28937e79135f732827c424f7444c12767cc1081c8006f0430"}, + {file = "PyMuPDF-1.24.1-cp312-none-macosx_10_9_x86_64.whl", hash = "sha256:02a6586979df2ad958b524ba42955beaa67fd21661616a0ed04ac07db009474c"}, + {file = "PyMuPDF-1.24.1-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:8eb292d16671166acdaa280e98cac4368298f32556f2de2ee690782a635df8ee"}, + {file = "PyMuPDF-1.24.1-cp312-none-manylinux2014_aarch64.whl", hash = "sha256:f7b7f2011fa522a57fb3d6a7a58bcdcf01ee59bdad536ef9eb5c3fdf1e04e6c3"}, + {file = "PyMuPDF-1.24.1-cp312-none-manylinux2014_x86_64.whl", hash = "sha256:6832f1d9332810760b587ad375eb84d64ec8d8f29395995b463cb5f30533a413"}, + {file = "PyMuPDF-1.24.1-cp312-none-win32.whl", hash = "sha256:f775bb56391629e81b5f870fc3dec0a0fb44cb34a92b4696b9207b31234711df"}, + {file = "PyMuPDF-1.24.1-cp312-none-win_amd64.whl", hash = "sha256:8489df092473d590fb14903433bd99a07dc3d2924f5a5c8ead615795f2d65a65"}, + {file = "PyMuPDF-1.24.1-cp38-none-macosx_10_9_x86_64.whl", hash = "sha256:ee9cfac470aeb6b5b7deb4f6472b7796c3132856849c635c8e56c7a371e40238"}, + {file = "PyMuPDF-1.24.1-cp38-none-macosx_11_0_arm64.whl", hash = "sha256:825c62367b01e61b4bce0cc96d45b0ec336475422cfa36de6f441b4d3389a26e"}, + {file = "PyMuPDF-1.24.1-cp38-none-manylinux2014_aarch64.whl", hash = "sha256:73d07e127936948a29a7dbd4c831e9eb45a60b495d72e604d454fd040fd08c5f"}, + {file = "PyMuPDF-1.24.1-cp38-none-manylinux2014_x86_64.whl", hash = "sha256:d2b4f8956d0ca7564604491db8b29cd7872a2b4d65f1d7e16a1bccfecf84bb56"}, + {file = "PyMuPDF-1.24.1-cp38-none-win32.whl", hash = "sha256:7df966954ff0edbcd5d743c5f6fb68b3203e67534747e8753691b8ffedeaa518"}, + {file = "PyMuPDF-1.24.1-cp38-none-win_amd64.whl", hash = "sha256:6952d47f0f05cf9338470dda078e4533ddb876368b199ebfa2f9e6076311898b"}, + {file = "PyMuPDF-1.24.1-cp39-none-macosx_10_9_x86_64.whl", hash = "sha256:e3f7a101a14d742c93b660b7586ab4c1491caea9062a5de9c308578a7a4f8b69"}, + {file = "PyMuPDF-1.24.1-cp39-none-macosx_11_0_arm64.whl", hash = "sha256:dbc5d67dfd07123293993eb93bee35d329fce0bc8134b9cd5514ef75c68ffee8"}, + {file = "PyMuPDF-1.24.1-cp39-none-manylinux2014_aarch64.whl", hash = "sha256:0edda1024ada67603e5888f31656048d3fd53167c8b0d56f435b986eb507df8f"}, + {file = "PyMuPDF-1.24.1-cp39-none-manylinux2014_x86_64.whl", hash = "sha256:38728bb6aab9e3879aa8ac4d337be8fe838d33973f43e3b7805b86265c24f349"}, + {file = "PyMuPDF-1.24.1-cp39-none-win32.whl", hash = "sha256:b8a5247d0cec87765481c38d2b8602f0264bf7ca6b5dc3013caf64ce46ad4d5e"}, + {file = "PyMuPDF-1.24.1-cp39-none-win_amd64.whl", hash = "sha256:d1078ea265635e962693d7298bd39be64af7d1dd2c6dc663a8562e75f547f948"}, + {file = "PyMuPDF-1.24.1.tar.gz", hash = "sha256:38e6101dab2ff86c4e2444fcec8a04377ae1d6db1bef0f7a1ddab3ac6abe4d41"}, +] + +[package.dependencies] +PyMuPDFb = "1.24.1" + +[[package]] +name = "pymupdfb" +version = "1.24.1" +description = "MuPDF shared libraries for PyMuPDF." +optional = false +python-versions = ">=3.8" +files = [ + {file = "PyMuPDFb-1.24.1-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:37179e363bf69ce9be637937c5469957b96968341dabe3ce8f4b690a82e9ad92"}, + {file = "PyMuPDFb-1.24.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:17444ea7d6897c27759880ad76af537d19779f901de82ae9548598a70f614558"}, + {file = "PyMuPDFb-1.24.1-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:490f7fff4dbe362bc895cefdfc5030d712311d024d357a1388d64816eb215d34"}, + {file = "PyMuPDFb-1.24.1-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0fbcc0d2a9ce79fa38eb4e8bb5c959b582f7a49938874e9f61d1a6f5eeb1e4b8"}, + {file = "PyMuPDFb-1.24.1-py3-none-win32.whl", hash = "sha256:ae67736058882cdd9459810a4aae9ac2b2e89ac2e916cb5fefb0f651c9739e9e"}, + {file = "PyMuPDFb-1.24.1-py3-none-win_amd64.whl", hash = "sha256:01c8b7f0ce9166310eb28c7aebcb8d5fe12a4bc082f9b00d580095eebeaf0af5"}, +] + [[package]] name = "pyparsing" version = "2.4.7" @@ -6297,9 +7102,6 @@ files = [ {file = "pypdf-4.1.0.tar.gz", hash = "sha256:01c3257ec908676efd60a4537e525b89d48e0852bc92b4e0aa4cc646feda17cc"}, ] -[package.dependencies] -typing_extensions = {version = ">=3.7.4.3", markers = "python_version < \"3.10\""} - [package.extras] crypto = ["PyCryptodome", "cryptography"] dev = ["black", "flit", "pip-tools", "pre-commit (<2.18.0)", "pytest-cov", "pytest-socket", "pytest-timeout", "pytest-xdist", "wheel"] @@ -6498,19 +7300,53 @@ files = [ six = ">=1.5" [[package]] -name = "python-dotenv" -version = "0.21.1" -description = "Read key-value pairs from a .env file and set them as environment variables" +name = "python-docx" +version = "1.1.0" +description = "Create, read, and update Microsoft Word .docx files." optional = false python-versions = ">=3.7" files = [ - {file = "python-dotenv-0.21.1.tar.gz", hash = "sha256:1c93de8f636cde3ce377292818d0e440b6e45a82f215c3744979151fa8151c49"}, - {file = "python_dotenv-0.21.1-py3-none-any.whl", hash = "sha256:41e12e0318bebc859fcc4d97d4db8d20ad21721a6aa5047dd59f090391cb549a"}, + {file = "python-docx-1.1.0.tar.gz", hash = "sha256:5829b722141cf1ab79aedf0c34d9fe9924b29764584c0f2164eb2b02dcdf17c9"}, + {file = "python_docx-1.1.0-py3-none-any.whl", hash = "sha256:bac9773278098a1ddc43a52d84e22f5909c4a3080a624530b3ecb3771b07c6cd"}, +] + +[package.dependencies] +lxml = ">=3.1.0" +typing-extensions = "*" + +[[package]] +name = "python-dotenv" +version = "1.0.0" +description = "Read key-value pairs from a .env file and set them as environment variables" +optional = false +python-versions = ">=3.8" +files = [ + {file = "python-dotenv-1.0.0.tar.gz", hash = "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba"}, + {file = "python_dotenv-1.0.0-py3-none-any.whl", hash = "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a"}, ] [package.extras] cli = ["click (>=5.0)"] +[[package]] +name = "python-engineio" +version = "4.9.0" +description = "Engine.IO server and client for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "python-engineio-4.9.0.tar.gz", hash = "sha256:e87459c15638e567711fd156e6f9c4a402668871bed79523f0ecfec744729ec7"}, + {file = "python_engineio-4.9.0-py3-none-any.whl", hash = "sha256:979859bff770725b75e60353d7ae53b397e8b517d05ba76733b404a3dcca3e4c"}, +] + +[package.dependencies] +simple-websocket = ">=0.10.0" + +[package.extras] +asyncio-client = ["aiohttp (>=3.4)"] +client = ["requests (>=2.21.0)", "websocket-client (>=0.54.0)"] +docs = ["sphinx"] + [[package]] name = "python-iso639" version = "2024.2.7" @@ -6571,6 +7407,26 @@ files = [ [package.extras] dev = ["atomicwrites (==1.2.1)", "attrs (==19.2.0)", "coverage (==6.5.0)", "hatch", "invoke (==2.2.0)", "more-itertools (==4.3.0)", "pbr (==4.3.0)", "pluggy (==1.0.0)", "py (==1.11.0)", "pytest (==7.2.0)", "pytest-cov (==4.0.0)", "pytest-timeout (==2.1.0)", "pyyaml (==5.1)"] +[[package]] +name = "python-socketio" +version = "5.11.2" +description = "Socket.IO server and client for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "python-socketio-5.11.2.tar.gz", hash = "sha256:ae6a1de5c5209ca859dc574dccc8931c4be17ee003e74ce3b8d1306162bb4a37"}, + {file = "python_socketio-5.11.2-py3-none-any.whl", hash = "sha256:b9f22a8ff762d7a6e123d16a43ddb1a27d50f07c3c88ea999334f2f89b0ad52b"}, +] + +[package.dependencies] +bidict = ">=0.21.0" +python-engineio = ">=4.8.0" + +[package.extras] +asyncio-client = ["aiohttp (>=3.4)"] +client = ["requests (>=2.21.0)", "websocket-client (>=0.54.0)"] +docs = ["sphinx"] + [[package]] name = "pytube" version = "15.0.0" @@ -6806,25 +7662,28 @@ fastembed = ["fastembed (==0.2.5)"] [[package]] name = "qianfan" -version = "0.3.0" +version = "0.3.5" description = "文心千帆大模型平台 Python SDK" optional = false python-versions = ">=3.7,<4" files = [ - {file = "qianfan-0.3.0-py3-none-any.whl", hash = "sha256:1fc324aa494f10c8f4569251d298c14e6700ea93f27cc361d8e5cce456b930a1"}, - {file = "qianfan-0.3.0.tar.gz", hash = "sha256:b12aab31b5eb6f58d5423b2d4648627add7941a6cfa2f7c36d7da268302ea72c"}, + {file = "qianfan-0.3.5-py3-none-any.whl", hash = "sha256:0d5712c93ec6877c4176aae21ff58b41ccfef7ba661c6e19c07209c353353a16"}, + {file = "qianfan-0.3.5.tar.gz", hash = "sha256:b71847888bd99d61cee5f84f614f431204f3d656d71dd7ae1d0f9bc9ae51b42b"}, ] [package.dependencies] aiohttp = ">=3.7.0" aiolimiter = ">=1.1.0" bce-python-sdk = ">=0.8.79" +clevercsv = {version = "*", markers = "python_version >= \"3.8\""} +ijson = "*" +multiprocess = "*" numpy = {version = ">=1.22.0", markers = "python_version >= \"3.8\""} prompt-toolkit = ">=3.0.38" pyarrow = {version = ">=14.0.1", markers = "python_version >= \"3.8\""} pydantic = "*" python-dateutil = ">=2.8.2,<3.0.0" -python-dotenv = "<=0.21.1" +python-dotenv = {version = ">=1.0", markers = "python_version >= \"3.8\""} pyyaml = ">=6.0.1,<7.0.0" requests = ">=2.24" rich = ">=13.0.0" @@ -6941,19 +7800,19 @@ full = ["numpy"] [[package]] name = "realtime" -version = "1.0.0" +version = "1.0.3" description = "" optional = false -python-versions = ">=3.8,<4.0" +python-versions = "<4.0,>=3.8" files = [ - {file = "realtime-1.0.0-py3-none-any.whl", hash = "sha256:ceab9e292211ab08b5792ac52b3fa25398440031d5b369bd5799b8125056e2d8"}, - {file = "realtime-1.0.0.tar.gz", hash = "sha256:14e540c4a0cc2736ae83e0cbd7efbbfb8b736df1681df2b9141556cb4848502d"}, + {file = "realtime-1.0.3-py3-none-any.whl", hash = "sha256:809b99a1c09390a4580ca2d37d84c85dffacb1804f80c6f5a4491d312c20e6e3"}, + {file = "realtime-1.0.3.tar.gz", hash = "sha256:1a39b5dcdb345b4cc7fd43bc035feb38ca915c9248962f20d264625bc8eb2c4e"}, ] [package.dependencies] python-dateutil = ">=2.8.1,<3.0.0" typing-extensions = ">=4.2.0,<5.0.0" -websockets = ">=10.3,<11.0" +websockets = ">=11,<13" [[package]] name = "red-black-tree-mod" @@ -7124,6 +7983,20 @@ requests = ">=2.0.0" [package.extras] rsa = ["oauthlib[signedtoken] (>=3.0.0)"] +[[package]] +name = "respx" +version = "0.20.2" +description = "A utility for mocking out the Python HTTPX and HTTP Core libraries." +optional = false +python-versions = ">=3.7" +files = [ + {file = "respx-0.20.2-py2.py3-none-any.whl", hash = "sha256:ab8e1cf6da28a5b2dd883ea617f8130f77f676736e6e9e4a25817ad116a172c9"}, + {file = "respx-0.20.2.tar.gz", hash = "sha256:07cf4108b1c88b82010f67d3c831dae33a375c7b436e54d87737c7f9f99be643"}, +] + +[package.dependencies] +httpx = ">=0.21.0" + [[package]] name = "rich" version = "13.7.1" @@ -7404,45 +8277,45 @@ tests = ["black (>=23.3.0)", "matplotlib (>=3.3.4)", "mypy (>=1.3)", "numpydoc ( [[package]] name = "scipy" -version = "1.12.0" +version = "1.13.0" description = "Fundamental algorithms for scientific computing in Python" optional = true python-versions = ">=3.9" files = [ - {file = "scipy-1.12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:78e4402e140879387187f7f25d91cc592b3501a2e51dfb320f48dfb73565f10b"}, - {file = "scipy-1.12.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:f5f00ebaf8de24d14b8449981a2842d404152774c1a1d880c901bf454cb8e2a1"}, - {file = "scipy-1.12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e53958531a7c695ff66c2e7bb7b79560ffdc562e2051644c5576c39ff8efb563"}, - {file = "scipy-1.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e32847e08da8d895ce09d108a494d9eb78974cf6de23063f93306a3e419960c"}, - {file = "scipy-1.12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4c1020cad92772bf44b8e4cdabc1df5d87376cb219742549ef69fc9fd86282dd"}, - {file = "scipy-1.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:75ea2a144096b5e39402e2ff53a36fecfd3b960d786b7efd3c180e29c39e53f2"}, - {file = "scipy-1.12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:408c68423f9de16cb9e602528be4ce0d6312b05001f3de61fe9ec8b1263cad08"}, - {file = "scipy-1.12.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:5adfad5dbf0163397beb4aca679187d24aec085343755fcdbdeb32b3679f254c"}, - {file = "scipy-1.12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3003652496f6e7c387b1cf63f4bb720951cfa18907e998ea551e6de51a04467"}, - {file = "scipy-1.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b8066bce124ee5531d12a74b617d9ac0ea59245246410e19bca549656d9a40a"}, - {file = "scipy-1.12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8bee4993817e204d761dba10dbab0774ba5a8612e57e81319ea04d84945375ba"}, - {file = "scipy-1.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:a24024d45ce9a675c1fb8494e8e5244efea1c7a09c60beb1eeb80373d0fecc70"}, - {file = "scipy-1.12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e7e76cc48638228212c747ada851ef355c2bb5e7f939e10952bc504c11f4e372"}, - {file = "scipy-1.12.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:f7ce148dffcd64ade37b2df9315541f9adad6efcaa86866ee7dd5db0c8f041c3"}, - {file = "scipy-1.12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c39f92041f490422924dfdb782527a4abddf4707616e07b021de33467f917bc"}, - {file = "scipy-1.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a7ebda398f86e56178c2fa94cad15bf457a218a54a35c2a7b4490b9f9cb2676c"}, - {file = "scipy-1.12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:95e5c750d55cf518c398a8240571b0e0782c2d5a703250872f36eaf737751338"}, - {file = "scipy-1.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:e646d8571804a304e1da01040d21577685ce8e2db08ac58e543eaca063453e1c"}, - {file = "scipy-1.12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:913d6e7956c3a671de3b05ccb66b11bc293f56bfdef040583a7221d9e22a2e35"}, - {file = "scipy-1.12.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:bba1b0c7256ad75401c73e4b3cf09d1f176e9bd4248f0d3112170fb2ec4db067"}, - {file = "scipy-1.12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:730badef9b827b368f351eacae2e82da414e13cf8bd5051b4bdfd720271a5371"}, - {file = "scipy-1.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6546dc2c11a9df6926afcbdd8a3edec28566e4e785b915e849348c6dd9f3f490"}, - {file = "scipy-1.12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:196ebad3a4882081f62a5bf4aeb7326aa34b110e533aab23e4374fcccb0890dc"}, - {file = "scipy-1.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:b360f1b6b2f742781299514e99ff560d1fe9bd1bff2712894b52abe528d1fd1e"}, - {file = "scipy-1.12.0.tar.gz", hash = "sha256:4bf5abab8a36d20193c698b0f1fc282c1d083c94723902c447e5d2f1780936a3"}, + {file = "scipy-1.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ba419578ab343a4e0a77c0ef82f088238a93eef141b2b8017e46149776dfad4d"}, + {file = "scipy-1.13.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:22789b56a999265431c417d462e5b7f2b487e831ca7bef5edeb56efe4c93f86e"}, + {file = "scipy-1.13.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05f1432ba070e90d42d7fd836462c50bf98bd08bed0aa616c359eed8a04e3922"}, + {file = "scipy-1.13.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8434f6f3fa49f631fae84afee424e2483289dfc30a47755b4b4e6b07b2633a4"}, + {file = "scipy-1.13.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:dcbb9ea49b0167de4167c40eeee6e167caeef11effb0670b554d10b1e693a8b9"}, + {file = "scipy-1.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:1d2f7bb14c178f8b13ebae93f67e42b0a6b0fc50eba1cd8021c9b6e08e8fb1cd"}, + {file = "scipy-1.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0fbcf8abaf5aa2dc8d6400566c1a727aed338b5fe880cde64907596a89d576fa"}, + {file = "scipy-1.13.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:5e4a756355522eb60fcd61f8372ac2549073c8788f6114449b37e9e8104f15a5"}, + {file = "scipy-1.13.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5acd8e1dbd8dbe38d0004b1497019b2dbbc3d70691e65d69615f8a7292865d7"}, + {file = "scipy-1.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ff7dad5d24a8045d836671e082a490848e8639cabb3dbdacb29f943a678683d"}, + {file = "scipy-1.13.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4dca18c3ffee287ddd3bc8f1dabaf45f5305c5afc9f8ab9cbfab855e70b2df5c"}, + {file = "scipy-1.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:a2f471de4d01200718b2b8927f7d76b5d9bde18047ea0fa8bd15c5ba3f26a1d6"}, + {file = "scipy-1.13.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d0de696f589681c2802f9090fff730c218f7c51ff49bf252b6a97ec4a5d19e8b"}, + {file = "scipy-1.13.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:b2a3ff461ec4756b7e8e42e1c681077349a038f0686132d623fa404c0bee2551"}, + {file = "scipy-1.13.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bf9fe63e7a4bf01d3645b13ff2aa6dea023d38993f42aaac81a18b1bda7a82a"}, + {file = "scipy-1.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e7626dfd91cdea5714f343ce1176b6c4745155d234f1033584154f60ef1ff42"}, + {file = "scipy-1.13.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:109d391d720fcebf2fbe008621952b08e52907cf4c8c7efc7376822151820820"}, + {file = "scipy-1.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:8930ae3ea371d6b91c203b1032b9600d69c568e537b7988a3073dfe4d4774f21"}, + {file = "scipy-1.13.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5407708195cb38d70fd2d6bb04b1b9dd5c92297d86e9f9daae1576bd9e06f602"}, + {file = "scipy-1.13.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:ac38c4c92951ac0f729c4c48c9e13eb3675d9986cc0c83943784d7390d540c78"}, + {file = "scipy-1.13.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09c74543c4fbeb67af6ce457f6a6a28e5d3739a87f62412e4a16e46f164f0ae5"}, + {file = "scipy-1.13.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28e286bf9ac422d6beb559bc61312c348ca9b0f0dae0d7c5afde7f722d6ea13d"}, + {file = "scipy-1.13.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:33fde20efc380bd23a78a4d26d59fc8704e9b5fd9b08841693eb46716ba13d86"}, + {file = "scipy-1.13.0-cp39-cp39-win_amd64.whl", hash = "sha256:45c08bec71d3546d606989ba6e7daa6f0992918171e2a6f7fbedfa7361c2de1e"}, + {file = "scipy-1.13.0.tar.gz", hash = "sha256:58569af537ea29d3f78e5abd18398459f195546bb3be23d16677fb26616cc11e"}, ] [package.dependencies] -numpy = ">=1.22.4,<1.29.0" +numpy = ">=1.22.4,<2.3" [package.extras] -dev = ["click", "cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy", "pycodestyle", "pydevtool", "rich-click", "ruff", "types-psutil", "typing_extensions"] -doc = ["jupytext", "matplotlib (>2)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (==0.9.0)", "sphinx (!=4.1.0)", "sphinx-design (>=0.2.0)"] -test = ["asv", "gmpy2", "hypothesis", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] +dev = ["cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy", "pycodestyle", "pydevtool", "rich-click", "ruff", "types-psutil", "typing_extensions"] +doc = ["jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.12.0)", "jupytext", "matplotlib (>=3.5)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0)", "sphinx-design (>=0.4.0)"] +test = ["array-api-strict", "asv", "gmpy2", "hypothesis (>=6.30)", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] [[package]] name = "sentence-transformers" @@ -7482,61 +8355,21 @@ testing = ["build[virtualenv]", "filelock (>=3.4.0)", "importlib-metadata", "ini testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] [[package]] -name = "shapely" -version = "2.0.3" -description = "Manipulation and analysis of geometric objects" +name = "simple-websocket" +version = "1.0.0" +description = "Simple WebSocket server and client for Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.6" files = [ - {file = "shapely-2.0.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:af7e9abe180b189431b0f490638281b43b84a33a960620e6b2e8d3e3458b61a1"}, - {file = "shapely-2.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:98040462b36ced9671e266b95c326b97f41290d9d17504a1ee4dc313a7667b9c"}, - {file = "shapely-2.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:71eb736ef2843f23473c6e37f6180f90f0a35d740ab284321548edf4e55d9a52"}, - {file = "shapely-2.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:881eb9dbbb4a6419667e91fcb20313bfc1e67f53dbb392c6840ff04793571ed1"}, - {file = "shapely-2.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f10d2ccf0554fc0e39fad5886c839e47e207f99fdf09547bc687a2330efda35b"}, - {file = "shapely-2.0.3-cp310-cp310-win32.whl", hash = "sha256:6dfdc077a6fcaf74d3eab23a1ace5abc50c8bce56ac7747d25eab582c5a2990e"}, - {file = "shapely-2.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:64c5013dacd2d81b3bb12672098a0b2795c1bf8190cfc2980e380f5ef9d9e4d9"}, - {file = "shapely-2.0.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:56cee3e4e8159d6f2ce32e421445b8e23154fd02a0ac271d6a6c0b266a8e3cce"}, - {file = "shapely-2.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:619232c8276fded09527d2a9fd91a7885ff95c0ff9ecd5e3cb1e34fbb676e2ae"}, - {file = "shapely-2.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b2a7d256db6f5b4b407dc0c98dd1b2fcf1c9c5814af9416e5498d0a2e4307a4b"}, - {file = "shapely-2.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e45f0c8cd4583647db3216d965d49363e6548c300c23fd7e57ce17a03f824034"}, - {file = "shapely-2.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13cb37d3826972a82748a450328fe02a931dcaed10e69a4d83cc20ba021bc85f"}, - {file = "shapely-2.0.3-cp311-cp311-win32.whl", hash = "sha256:9302d7011e3e376d25acd30d2d9e70d315d93f03cc748784af19b00988fc30b1"}, - {file = "shapely-2.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:6b464f2666b13902835f201f50e835f2f153f37741db88f68c7f3b932d3505fa"}, - {file = "shapely-2.0.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:e86e7cb8e331a4850e0c2a8b2d66dc08d7a7b301b8d1d34a13060e3a5b4b3b55"}, - {file = "shapely-2.0.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c91981c99ade980fc49e41a544629751a0ccd769f39794ae913e53b07b2f78b9"}, - {file = "shapely-2.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bd45d456983dc60a42c4db437496d3f08a4201fbf662b69779f535eb969660af"}, - {file = "shapely-2.0.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:882fb1ffc7577e88c1194f4f1757e277dc484ba096a3b94844319873d14b0f2d"}, - {file = "shapely-2.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9f2d93bff2ea52fa93245798cddb479766a18510ea9b93a4fb9755c79474889"}, - {file = "shapely-2.0.3-cp312-cp312-win32.whl", hash = "sha256:99abad1fd1303b35d991703432c9481e3242b7b3a393c186cfb02373bf604004"}, - {file = "shapely-2.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:6f555fe3304a1f40398977789bc4fe3c28a11173196df9ece1e15c5bc75a48db"}, - {file = "shapely-2.0.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a983cc418c1fa160b7d797cfef0e0c9f8c6d5871e83eae2c5793fce6a837fad9"}, - {file = "shapely-2.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18bddb8c327f392189a8d5d6b9a858945722d0bb95ccbd6a077b8e8fc4c7890d"}, - {file = "shapely-2.0.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:442f4dcf1eb58c5a4e3428d88e988ae153f97ab69a9f24e07bf4af8038536325"}, - {file = "shapely-2.0.3-cp37-cp37m-win32.whl", hash = "sha256:31a40b6e3ab00a4fd3a1d44efb2482278642572b8e0451abdc8e0634b787173e"}, - {file = "shapely-2.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:59b16976c2473fec85ce65cc9239bef97d4205ab3acead4e6cdcc72aee535679"}, - {file = "shapely-2.0.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:705efbce1950a31a55b1daa9c6ae1c34f1296de71ca8427974ec2f27d57554e3"}, - {file = "shapely-2.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:601c5c0058a6192df704cb889439f64994708563f57f99574798721e9777a44b"}, - {file = "shapely-2.0.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f24ecbb90a45c962b3b60d8d9a387272ed50dc010bfe605f1d16dfc94772d8a1"}, - {file = "shapely-2.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8c2a2989222c6062f7a0656e16276c01bb308bc7e5d999e54bf4e294ce62e76"}, - {file = "shapely-2.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42bceb9bceb3710a774ce04908fda0f28b291323da2688f928b3f213373b5aee"}, - {file = "shapely-2.0.3-cp38-cp38-win32.whl", hash = "sha256:54d925c9a311e4d109ec25f6a54a8bd92cc03481a34ae1a6a92c1fe6729b7e01"}, - {file = "shapely-2.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:300d203b480a4589adefff4c4af0b13919cd6d760ba3cbb1e56275210f96f654"}, - {file = "shapely-2.0.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:083d026e97b6c1f4a9bd2a9171c7692461092ed5375218170d91705550eecfd5"}, - {file = "shapely-2.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:27b6e1910094d93e9627f2664121e0e35613262fc037051680a08270f6058daf"}, - {file = "shapely-2.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:71b2de56a9e8c0e5920ae5ddb23b923490557ac50cb0b7fa752761bf4851acde"}, - {file = "shapely-2.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d279e56bbb68d218d63f3efc80c819cedcceef0e64efbf058a1df89dc57201b"}, - {file = "shapely-2.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88566d01a30f0453f7d038db46bc83ce125e38e47c5f6bfd4c9c287010e9bf74"}, - {file = "shapely-2.0.3-cp39-cp39-win32.whl", hash = "sha256:58afbba12c42c6ed44c4270bc0e22f3dadff5656d711b0ad335c315e02d04707"}, - {file = "shapely-2.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:5026b30433a70911979d390009261b8c4021ff87c7c3cbd825e62bb2ffa181bc"}, - {file = "shapely-2.0.3.tar.gz", hash = "sha256:4d65d0aa7910af71efa72fd6447e02a8e5dd44da81a983de9d736d6e6ccbe674"}, + {file = "simple-websocket-1.0.0.tar.gz", hash = "sha256:17d2c72f4a2bd85174a97e3e4c88b01c40c3f81b7b648b0cc3ce1305968928c8"}, + {file = "simple_websocket-1.0.0-py3-none-any.whl", hash = "sha256:1d5bf585e415eaa2083e2bcf02a3ecf91f9712e7b3e6b9fa0b461ad04e0837bc"}, ] [package.dependencies] -numpy = ">=1.14,<2" +wsproto = "*" [package.extras] -docs = ["matplotlib", "numpydoc (==1.1.*)", "sphinx", "sphinx-book-theme", "sphinx-remove-toctrees"] -test = ["pytest", "pytest-cov"] +docs = ["sphinx"] [[package]] name = "six" @@ -7705,7 +8538,6 @@ files = [ [package.dependencies] anyio = ">=3.4.0,<5" -typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} [package.extras] full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7)", "pyyaml"] @@ -7742,6 +8574,17 @@ docs = ["myst-parser[linkify]", "sphinx", "sphinx-rtd-theme"] release = ["twine"] test = ["pylint", "pytest", "pytest-black", "pytest-cov", "pytest-pylint"] +[[package]] +name = "striprtf" +version = "0.0.26" +description = "A simple library to convert rtf to text" +optional = false +python-versions = "*" +files = [ + {file = "striprtf-0.0.26-py3-none-any.whl", hash = "sha256:8c8f9d32083cdc2e8bfb149455aa1cc5a4e0a035893bedc75db8b73becb3a1bb"}, + {file = "striprtf-0.0.26.tar.gz", hash = "sha256:fdb2bba7ac440072d1c41eab50d8d74ae88f60a8b6575c6e2c7805dc462093aa"}, +] + [[package]] name = "supabase" version = "2.4.1" @@ -7844,47 +8687,47 @@ files = [ [[package]] name = "tiktoken" -version = "0.6.0" +version = "0.5.2" description = "tiktoken is a fast BPE tokeniser for use with OpenAI's models" optional = false python-versions = ">=3.8" files = [ - {file = "tiktoken-0.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:277de84ccd8fa12730a6b4067456e5cf72fef6300bea61d506c09e45658d41ac"}, - {file = "tiktoken-0.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9c44433f658064463650d61387623735641dcc4b6c999ca30bc0f8ba3fccaf5c"}, - {file = "tiktoken-0.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afb9a2a866ae6eef1995ab656744287a5ac95acc7e0491c33fad54d053288ad3"}, - {file = "tiktoken-0.6.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c62c05b3109fefca26fedb2820452a050074ad8e5ad9803f4652977778177d9f"}, - {file = "tiktoken-0.6.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0ef917fad0bccda07bfbad835525bbed5f3ab97a8a3e66526e48cdc3e7beacf7"}, - {file = "tiktoken-0.6.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e095131ab6092d0769a2fda85aa260c7c383072daec599ba9d8b149d2a3f4d8b"}, - {file = "tiktoken-0.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:05b344c61779f815038292a19a0c6eb7098b63c8f865ff205abb9ea1b656030e"}, - {file = "tiktoken-0.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cefb9870fb55dca9e450e54dbf61f904aab9180ff6fe568b61f4db9564e78871"}, - {file = "tiktoken-0.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:702950d33d8cabc039845674107d2e6dcabbbb0990ef350f640661368df481bb"}, - {file = "tiktoken-0.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8d49d076058f23254f2aff9af603863c5c5f9ab095bc896bceed04f8f0b013a"}, - {file = "tiktoken-0.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:430bc4e650a2d23a789dc2cdca3b9e5e7eb3cd3935168d97d43518cbb1f9a911"}, - {file = "tiktoken-0.6.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:293cb8669757301a3019a12d6770bd55bec38a4d3ee9978ddbe599d68976aca7"}, - {file = "tiktoken-0.6.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7bd1a288b7903aadc054b0e16ea78e3171f70b670e7372432298c686ebf9dd47"}, - {file = "tiktoken-0.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:ac76e000183e3b749634968a45c7169b351e99936ef46f0d2353cd0d46c3118d"}, - {file = "tiktoken-0.6.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:17cc8a4a3245ab7d935c83a2db6bb71619099d7284b884f4b2aea4c74f2f83e3"}, - {file = "tiktoken-0.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:284aebcccffe1bba0d6571651317df6a5b376ff6cfed5aeb800c55df44c78177"}, - {file = "tiktoken-0.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c1a3a5d33846f8cd9dd3b7897c1d45722f48625a587f8e6f3d3e85080559be8"}, - {file = "tiktoken-0.6.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6318b2bb2337f38ee954fd5efa82632c6e5ced1d52a671370fa4b2eff1355e91"}, - {file = "tiktoken-0.6.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1f5f0f2ed67ba16373f9a6013b68da298096b27cd4e1cf276d2d3868b5c7efd1"}, - {file = "tiktoken-0.6.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:75af4c0b16609c2ad02581f3cdcd1fb698c7565091370bf6c0cf8624ffaba6dc"}, - {file = "tiktoken-0.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:45577faf9a9d383b8fd683e313cf6df88b6076c034f0a16da243bb1c139340c3"}, - {file = "tiktoken-0.6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7c1492ab90c21ca4d11cef3a236ee31a3e279bb21b3fc5b0e2210588c4209e68"}, - {file = "tiktoken-0.6.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e2b380c5b7751272015400b26144a2bab4066ebb8daae9c3cd2a92c3b508fe5a"}, - {file = "tiktoken-0.6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9f497598b9f58c99cbc0eb764b4a92272c14d5203fc713dd650b896a03a50ad"}, - {file = "tiktoken-0.6.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e65e8bd6f3f279d80f1e1fbd5f588f036b9a5fa27690b7f0cc07021f1dfa0839"}, - {file = "tiktoken-0.6.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5f1495450a54e564d236769d25bfefbf77727e232d7a8a378f97acddee08c1ae"}, - {file = "tiktoken-0.6.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6c4e4857d99f6fb4670e928250835b21b68c59250520a1941618b5b4194e20c3"}, - {file = "tiktoken-0.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:168d718f07a39b013032741867e789971346df8e89983fe3c0ef3fbd5a0b1cb9"}, - {file = "tiktoken-0.6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:47fdcfe11bd55376785a6aea8ad1db967db7f66ea81aed5c43fad497521819a4"}, - {file = "tiktoken-0.6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fb7d2ccbf1a7784810aff6b80b4012fb42c6fc37eaa68cb3b553801a5cc2d1fc"}, - {file = "tiktoken-0.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ccb7a111ee76af5d876a729a347f8747d5ad548e1487eeea90eaf58894b3138"}, - {file = "tiktoken-0.6.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2048e1086b48e3c8c6e2ceeac866561374cd57a84622fa49a6b245ffecb7744"}, - {file = "tiktoken-0.6.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:07f229a5eb250b6403a61200199cecf0aac4aa23c3ecc1c11c1ca002cbb8f159"}, - {file = "tiktoken-0.6.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:432aa3be8436177b0db5a2b3e7cc28fd6c693f783b2f8722539ba16a867d0c6a"}, - {file = "tiktoken-0.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:8bfe8a19c8b5c40d121ee7938cd9c6a278e5b97dc035fd61714b4f0399d2f7a1"}, - {file = "tiktoken-0.6.0.tar.gz", hash = "sha256:ace62a4ede83c75b0374a2ddfa4b76903cf483e9cb06247f566be3bf14e6beed"}, + {file = "tiktoken-0.5.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8c4e654282ef05ec1bd06ead22141a9a1687991cef2c6a81bdd1284301abc71d"}, + {file = "tiktoken-0.5.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7b3134aa24319f42c27718c6967f3c1916a38a715a0fa73d33717ba121231307"}, + {file = "tiktoken-0.5.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6092e6e77730929c8c6a51bb0d7cfdf1b72b63c4d033d6258d1f2ee81052e9e5"}, + {file = "tiktoken-0.5.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72ad8ae2a747622efae75837abba59be6c15a8f31b4ac3c6156bc56ec7a8e631"}, + {file = "tiktoken-0.5.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:51cba7c8711afa0b885445f0637f0fcc366740798c40b981f08c5f984e02c9d1"}, + {file = "tiktoken-0.5.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3d8c7d2c9313f8e92e987d585ee2ba0f7c40a0de84f4805b093b634f792124f5"}, + {file = "tiktoken-0.5.2-cp310-cp310-win_amd64.whl", hash = "sha256:692eca18c5fd8d1e0dde767f895c17686faaa102f37640e884eecb6854e7cca7"}, + {file = "tiktoken-0.5.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:138d173abbf1ec75863ad68ca289d4da30caa3245f3c8d4bfb274c4d629a2f77"}, + {file = "tiktoken-0.5.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7388fdd684690973fdc450b47dfd24d7f0cbe658f58a576169baef5ae4658607"}, + {file = "tiktoken-0.5.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a114391790113bcff670c70c24e166a841f7ea8f47ee2fe0e71e08b49d0bf2d4"}, + {file = "tiktoken-0.5.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca96f001e69f6859dd52926d950cfcc610480e920e576183497ab954e645e6ac"}, + {file = "tiktoken-0.5.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:15fed1dd88e30dfadcdd8e53a8927f04e1f6f81ad08a5ca824858a593ab476c7"}, + {file = "tiktoken-0.5.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:93f8e692db5756f7ea8cb0cfca34638316dcf0841fb8469de8ed7f6a015ba0b0"}, + {file = "tiktoken-0.5.2-cp311-cp311-win_amd64.whl", hash = "sha256:bcae1c4c92df2ffc4fe9f475bf8148dbb0ee2404743168bbeb9dcc4b79dc1fdd"}, + {file = "tiktoken-0.5.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b76a1e17d4eb4357d00f0622d9a48ffbb23401dcf36f9716d9bd9c8e79d421aa"}, + {file = "tiktoken-0.5.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:01d8b171bb5df4035580bc26d4f5339a6fd58d06f069091899d4a798ea279d3e"}, + {file = "tiktoken-0.5.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42adf7d4fb1ed8de6e0ff2e794a6a15005f056a0d83d22d1d6755a39bffd9e7f"}, + {file = "tiktoken-0.5.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c3f894dbe0adb44609f3d532b8ea10820d61fdcb288b325a458dfc60fefb7db"}, + {file = "tiktoken-0.5.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:58ccfddb4e62f0df974e8f7e34a667981d9bb553a811256e617731bf1d007d19"}, + {file = "tiktoken-0.5.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58902a8bad2de4268c2a701f1c844d22bfa3cbcc485b10e8e3e28a050179330b"}, + {file = "tiktoken-0.5.2-cp312-cp312-win_amd64.whl", hash = "sha256:5e39257826d0647fcac403d8fa0a474b30d02ec8ffc012cfaf13083e9b5e82c5"}, + {file = "tiktoken-0.5.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8bde3b0fbf09a23072d39c1ede0e0821f759b4fa254a5f00078909158e90ae1f"}, + {file = "tiktoken-0.5.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2ddee082dcf1231ccf3a591d234935e6acf3e82ee28521fe99af9630bc8d2a60"}, + {file = "tiktoken-0.5.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35c057a6a4e777b5966a7540481a75a31429fc1cb4c9da87b71c8b75b5143037"}, + {file = "tiktoken-0.5.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c4a049b87e28f1dc60509f8eb7790bc8d11f9a70d99b9dd18dfdd81a084ffe6"}, + {file = "tiktoken-0.5.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5bf5ce759089f4f6521ea6ed89d8f988f7b396e9f4afb503b945f5c949c6bec2"}, + {file = "tiktoken-0.5.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0c964f554af1a96884e01188f480dad3fc224c4bbcf7af75d4b74c4b74ae0125"}, + {file = "tiktoken-0.5.2-cp38-cp38-win_amd64.whl", hash = "sha256:368dd5726d2e8788e47ea04f32e20f72a2012a8a67af5b0b003d1e059f1d30a3"}, + {file = "tiktoken-0.5.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a2deef9115b8cd55536c0a02c0203512f8deb2447f41585e6d929a0b878a0dd2"}, + {file = "tiktoken-0.5.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2ed7d380195affbf886e2f8b92b14edfe13f4768ff5fc8de315adba5b773815e"}, + {file = "tiktoken-0.5.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c76fce01309c8140ffe15eb34ded2bb94789614b7d1d09e206838fc173776a18"}, + {file = "tiktoken-0.5.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60a5654d6a2e2d152637dd9a880b4482267dfc8a86ccf3ab1cec31a8c76bfae8"}, + {file = "tiktoken-0.5.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:41d4d3228e051b779245a8ddd21d4336f8975563e92375662f42d05a19bdff41"}, + {file = "tiktoken-0.5.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a5c1cdec2c92fcde8c17a50814b525ae6a88e8e5b02030dc120b76e11db93f13"}, + {file = "tiktoken-0.5.2-cp39-cp39-win_amd64.whl", hash = "sha256:84ddb36faedb448a50b246e13d1b6ee3437f60b7169b723a4b2abad75e914f3e"}, + {file = "tiktoken-0.5.2.tar.gz", hash = "sha256:f54c581f134a8ea96ce2023ab221d4d4d81ab614efa0b2fbce926387deb56c80"}, ] [package.dependencies] @@ -8021,6 +8864,17 @@ dev = ["tokenizers[testing]"] docs = ["setuptools_rust", "sphinx", "sphinx_rtd_theme"] testing = ["black (==22.3)", "datasets", "numpy", "pytest", "requests"] +[[package]] +name = "toml" +version = "0.10.2" +description = "Python Library for Tom's Obvious, Minimal Language" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] + [[package]] name = "tomli" version = "2.0.1" @@ -8147,13 +9001,13 @@ test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0, [[package]] name = "transformers" -version = "4.39.2" +version = "4.39.3" description = "State-of-the-art Machine Learning for JAX, PyTorch and TensorFlow" optional = true python-versions = ">=3.8.0" files = [ - {file = "transformers-4.39.2-py3-none-any.whl", hash = "sha256:8388a4ae1d91ade935f5c5b36dc47aa1a352b092c30595e3337b49a5f7e71b4e"}, - {file = "transformers-4.39.2.tar.gz", hash = "sha256:be0c7392cb92ab48efab2656f1cfd1cbda33b2b8a2917a18bd1196707dbebe14"}, + {file = "transformers-4.39.3-py3-none-any.whl", hash = "sha256:7838034a12cca3168247f9d2d1dba6724c9de3ae0f73a108258c6b8fc5912601"}, + {file = "transformers-4.39.3.tar.gz", hash = "sha256:2586e5ff4150f122716fc40f5530e92871befc051848fbe82600969c535b762d"}, ] [package.dependencies] @@ -8292,24 +9146,24 @@ files = [ [[package]] name = "types-pillow" -version = "10.2.0.20240324" +version = "10.2.0.20240331" description = "Typing stubs for Pillow" optional = false python-versions = ">=3.8" files = [ - {file = "types-Pillow-10.2.0.20240324.tar.gz", hash = "sha256:e0108f0b30ea926a3a5d00f201cde627cde1574181b586eb36dd6be1e4ba09cf"}, - {file = "types_Pillow-10.2.0.20240324-py3-none-any.whl", hash = "sha256:e0ac3b50ade911b2a238b6633cc6be9559a6f8bc54141db6ad13b70989fd3d99"}, + {file = "types-Pillow-10.2.0.20240331.tar.gz", hash = "sha256:c604e39aeb70719e463d359157a2238bfc0e81bf9c658375703f7b98cfd607da"}, + {file = "types_Pillow-10.2.0.20240331-py3-none-any.whl", hash = "sha256:ceec177ab78d9d7c110b8efdb592298ae9ae3bb4da90f7de28b99818dfbe5179"}, ] [[package]] name = "types-pyasn1" -version = "0.5.0.20240301" +version = "0.6.0.20240402" description = "Typing stubs for pyasn1" optional = false python-versions = ">=3.8" files = [ - {file = "types-pyasn1-0.5.0.20240301.tar.gz", hash = "sha256:da328f5771d54a2016863270b281047f9cc38e39f65a297ba9f987d5de3403f1"}, - {file = "types_pyasn1-0.5.0.20240301-py3-none-any.whl", hash = "sha256:d9989899184bbd6e2adf6f812c8f49c48197fceea251a6fb13666dae3203f80d"}, + {file = "types-pyasn1-0.6.0.20240402.tar.gz", hash = "sha256:5d54dcb33f69dd269071ca098e923ac20c5f03c814631fa7f3ed9ee035a5da3a"}, + {file = "types_pyasn1-0.6.0.20240402-py3-none-any.whl", hash = "sha256:848d01e7313c200acc035a8b3d377fe7b2aecbe77f2be49eb160a7f82835aaaf"}, ] [[package]] @@ -8353,13 +9207,13 @@ files = [ [[package]] name = "types-pywin32" -version = "306.0.0.20240319" +version = "306.0.0.20240331" description = "Typing stubs for pywin32" optional = false python-versions = ">=3.8" files = [ - {file = "types-pywin32-306.0.0.20240319.tar.gz", hash = "sha256:a578ba15167a7a3a2bca0b307a401650d2f6b7bb58b2215d3ad9a6584b7baea5"}, - {file = "types_pywin32-306.0.0.20240319-py3-none-any.whl", hash = "sha256:acaa5da80f1b875115da8af2836c75c3cee4b45a2dd19e0fcac23dd011e2387b"}, + {file = "types-pywin32-306.0.0.20240331.tar.gz", hash = "sha256:3427e60ffbbc47b31e6bc416c3e4c37d579e6774e5152dab953589c9b64c4d58"}, + {file = "types_pywin32-306.0.0.20240331-py3-none-any.whl", hash = "sha256:844b90253f3da38e254c9ce199ba41f63da52c511003daedcda414e88f1cf319"}, ] [[package]] @@ -8390,28 +9244,17 @@ types-pyOpenSSL = "*" [[package]] name = "types-requests" -version = "2.31.0.6" +version = "2.31.0.20240403" description = "Typing stubs for requests" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "types-requests-2.31.0.6.tar.gz", hash = "sha256:cd74ce3b53c461f1228a9b783929ac73a666658f223e28ed29753771477b3bd0"}, - {file = "types_requests-2.31.0.6-py3-none-any.whl", hash = "sha256:a2db9cb228a81da8348b49ad6db3f5519452dd20a9c1e1a868c83c5fe88fd1a9"}, + {file = "types-requests-2.31.0.20240403.tar.gz", hash = "sha256:e1e0cd0b655334f39d9f872b68a1310f0e343647688bf2cee932ec4c2b04de59"}, + {file = "types_requests-2.31.0.20240403-py3-none-any.whl", hash = "sha256:06abf6a68f5c4f2a62f6bb006672dfb26ed50ccbfddb281e1ee6f09a65707d5d"}, ] [package.dependencies] -types-urllib3 = "*" - -[[package]] -name = "types-urllib3" -version = "1.26.25.14" -description = "Typing stubs for urllib3" -optional = false -python-versions = "*" -files = [ - {file = "types-urllib3-1.26.25.14.tar.gz", hash = "sha256:229b7f577c951b8c1b92c1bc2b2fdb0b49847bd2af6d1cc2a2e3dd340f3bda8f"}, - {file = "types_urllib3-1.26.25.14-py3-none-any.whl", hash = "sha256:9683bbb7fb72e32bfe9d2be6e04875fbe1b3eeec3cbb4ea231435aa7fd6b4f0e"}, -] +urllib3 = ">=2" [[package]] name = "typing-extensions" @@ -8467,6 +9310,80 @@ tzdata = {version = "*", markers = "platform_system == \"Windows\""} [package.extras] devenv = ["check-manifest", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3)", "zest.releaser"] +[[package]] +name = "ujson" +version = "5.9.0" +description = "Ultra fast JSON encoder and decoder for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "ujson-5.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ab71bf27b002eaf7d047c54a68e60230fbd5cd9da60de7ca0aa87d0bccead8fa"}, + {file = "ujson-5.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7a365eac66f5aa7a7fdf57e5066ada6226700884fc7dce2ba5483538bc16c8c5"}, + {file = "ujson-5.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e015122b337858dba5a3dc3533af2a8fc0410ee9e2374092f6a5b88b182e9fcc"}, + {file = "ujson-5.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:779a2a88c53039bebfbccca934430dabb5c62cc179e09a9c27a322023f363e0d"}, + {file = "ujson-5.9.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10ca3c41e80509fd9805f7c149068fa8dbee18872bbdc03d7cca928926a358d5"}, + {file = "ujson-5.9.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4a566e465cb2fcfdf040c2447b7dd9718799d0d90134b37a20dff1e27c0e9096"}, + {file = "ujson-5.9.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:f833c529e922577226a05bc25b6a8b3eb6c4fb155b72dd88d33de99d53113124"}, + {file = "ujson-5.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b68a0caab33f359b4cbbc10065c88e3758c9f73a11a65a91f024b2e7a1257106"}, + {file = "ujson-5.9.0-cp310-cp310-win32.whl", hash = "sha256:7cc7e605d2aa6ae6b7321c3ae250d2e050f06082e71ab1a4200b4ae64d25863c"}, + {file = "ujson-5.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:a6d3f10eb8ccba4316a6b5465b705ed70a06011c6f82418b59278fbc919bef6f"}, + {file = "ujson-5.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3b23bbb46334ce51ddb5dded60c662fbf7bb74a37b8f87221c5b0fec1ec6454b"}, + {file = "ujson-5.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6974b3a7c17bbf829e6c3bfdc5823c67922e44ff169851a755eab79a3dd31ec0"}, + {file = "ujson-5.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5964ea916edfe24af1f4cc68488448fbb1ec27a3ddcddc2b236da575c12c8ae"}, + {file = "ujson-5.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ba7cac47dd65ff88571eceeff48bf30ed5eb9c67b34b88cb22869b7aa19600d"}, + {file = "ujson-5.9.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6bbd91a151a8f3358c29355a491e915eb203f607267a25e6ab10531b3b157c5e"}, + {file = "ujson-5.9.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:829a69d451a49c0de14a9fecb2a2d544a9b2c884c2b542adb243b683a6f15908"}, + {file = "ujson-5.9.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:a807ae73c46ad5db161a7e883eec0fbe1bebc6a54890152ccc63072c4884823b"}, + {file = "ujson-5.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8fc2aa18b13d97b3c8ccecdf1a3c405f411a6e96adeee94233058c44ff92617d"}, + {file = "ujson-5.9.0-cp311-cp311-win32.whl", hash = "sha256:70e06849dfeb2548be48fdd3ceb53300640bc8100c379d6e19d78045e9c26120"}, + {file = "ujson-5.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:7309d063cd392811acc49b5016728a5e1b46ab9907d321ebbe1c2156bc3c0b99"}, + {file = "ujson-5.9.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:20509a8c9f775b3a511e308bbe0b72897ba6b800767a7c90c5cca59d20d7c42c"}, + {file = "ujson-5.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b28407cfe315bd1b34f1ebe65d3bd735d6b36d409b334100be8cdffae2177b2f"}, + {file = "ujson-5.9.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d302bd17989b6bd90d49bade66943c78f9e3670407dbc53ebcf61271cadc399"}, + {file = "ujson-5.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f21315f51e0db8ee245e33a649dd2d9dce0594522de6f278d62f15f998e050e"}, + {file = "ujson-5.9.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5635b78b636a54a86fdbf6f027e461aa6c6b948363bdf8d4fbb56a42b7388320"}, + {file = "ujson-5.9.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:82b5a56609f1235d72835ee109163c7041b30920d70fe7dac9176c64df87c164"}, + {file = "ujson-5.9.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:5ca35f484622fd208f55041b042d9d94f3b2c9c5add4e9af5ee9946d2d30db01"}, + {file = "ujson-5.9.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:829b824953ebad76d46e4ae709e940bb229e8999e40881338b3cc94c771b876c"}, + {file = "ujson-5.9.0-cp312-cp312-win32.whl", hash = "sha256:25fa46e4ff0a2deecbcf7100af3a5d70090b461906f2299506485ff31d9ec437"}, + {file = "ujson-5.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:60718f1720a61560618eff3b56fd517d107518d3c0160ca7a5a66ac949c6cf1c"}, + {file = "ujson-5.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d581db9db9e41d8ea0b2705c90518ba623cbdc74f8d644d7eb0d107be0d85d9c"}, + {file = "ujson-5.9.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ff741a5b4be2d08fceaab681c9d4bc89abf3c9db600ab435e20b9b6d4dfef12e"}, + {file = "ujson-5.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdcb02cabcb1e44381221840a7af04433c1dc3297af76fde924a50c3054c708c"}, + {file = "ujson-5.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e208d3bf02c6963e6ef7324dadf1d73239fb7008491fdf523208f60be6437402"}, + {file = "ujson-5.9.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4b3917296630a075e04d3d07601ce2a176479c23af838b6cf90a2d6b39b0d95"}, + {file = "ujson-5.9.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0c4d6adb2c7bb9eb7c71ad6f6f612e13b264942e841f8cc3314a21a289a76c4e"}, + {file = "ujson-5.9.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0b159efece9ab5c01f70b9d10bbb77241ce111a45bc8d21a44c219a2aec8ddfd"}, + {file = "ujson-5.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f0cb4a7814940ddd6619bdce6be637a4b37a8c4760de9373bac54bb7b229698b"}, + {file = "ujson-5.9.0-cp38-cp38-win32.whl", hash = "sha256:dc80f0f5abf33bd7099f7ac94ab1206730a3c0a2d17549911ed2cb6b7aa36d2d"}, + {file = "ujson-5.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:506a45e5fcbb2d46f1a51fead991c39529fc3737c0f5d47c9b4a1d762578fc30"}, + {file = "ujson-5.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d0fd2eba664a22447102062814bd13e63c6130540222c0aa620701dd01f4be81"}, + {file = "ujson-5.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:bdf7fc21a03bafe4ba208dafa84ae38e04e5d36c0e1c746726edf5392e9f9f36"}, + {file = "ujson-5.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2f909bc08ce01f122fd9c24bc6f9876aa087188dfaf3c4116fe6e4daf7e194f"}, + {file = "ujson-5.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd4ea86c2afd41429751d22a3ccd03311c067bd6aeee2d054f83f97e41e11d8f"}, + {file = "ujson-5.9.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:63fb2e6599d96fdffdb553af0ed3f76b85fda63281063f1cb5b1141a6fcd0617"}, + {file = "ujson-5.9.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:32bba5870c8fa2a97f4a68f6401038d3f1922e66c34280d710af00b14a3ca562"}, + {file = "ujson-5.9.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:37ef92e42535a81bf72179d0e252c9af42a4ed966dc6be6967ebfb929a87bc60"}, + {file = "ujson-5.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f69f16b8f1c69da00e38dc5f2d08a86b0e781d0ad3e4cc6a13ea033a439c4844"}, + {file = "ujson-5.9.0-cp39-cp39-win32.whl", hash = "sha256:3382a3ce0ccc0558b1c1668950008cece9bf463ebb17463ebf6a8bfc060dae34"}, + {file = "ujson-5.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:6adef377ed583477cf005b58c3025051b5faa6b8cc25876e594afbb772578f21"}, + {file = "ujson-5.9.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ffdfebd819f492e48e4f31c97cb593b9c1a8251933d8f8972e81697f00326ff1"}, + {file = "ujson-5.9.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4eec2ddc046360d087cf35659c7ba0cbd101f32035e19047013162274e71fcf"}, + {file = "ujson-5.9.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbb90aa5c23cb3d4b803c12aa220d26778c31b6e4b7a13a1f49971f6c7d088e"}, + {file = "ujson-5.9.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba0823cb70866f0d6a4ad48d998dd338dce7314598721bc1b7986d054d782dfd"}, + {file = "ujson-5.9.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:4e35d7885ed612feb6b3dd1b7de28e89baaba4011ecdf995e88be9ac614765e9"}, + {file = "ujson-5.9.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b048aa93eace8571eedbd67b3766623e7f0acbf08ee291bef7d8106210432427"}, + {file = "ujson-5.9.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:323279e68c195110ef85cbe5edce885219e3d4a48705448720ad925d88c9f851"}, + {file = "ujson-5.9.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9ac92d86ff34296f881e12aa955f7014d276895e0e4e868ba7fddebbde38e378"}, + {file = "ujson-5.9.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:6eecbd09b316cea1fd929b1e25f70382917542ab11b692cb46ec9b0a26c7427f"}, + {file = "ujson-5.9.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:473fb8dff1d58f49912323d7cb0859df5585cfc932e4b9c053bf8cf7f2d7c5c4"}, + {file = "ujson-5.9.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f91719c6abafe429c1a144cfe27883eace9fb1c09a9c5ef1bcb3ae80a3076a4e"}, + {file = "ujson-5.9.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b1c0991c4fe256f5fdb19758f7eac7f47caac29a6c57d0de16a19048eb86bad"}, + {file = "ujson-5.9.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a8ea0f55a1396708e564595aaa6696c0d8af532340f477162ff6927ecc46e21"}, + {file = "ujson-5.9.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:07e0cfdde5fd91f54cd2d7ffb3482c8ff1bf558abf32a8b953a5d169575ae1cd"}, + {file = "ujson-5.9.0.tar.gz", hash = "sha256:89cc92e73d5501b8a7f48575eeb14ad27156ad092c2e9fc7e3cf949f07e75532"}, +] + [[package]] name = "unstructured" version = "0.12.5" @@ -8487,6 +9404,7 @@ emoji = "*" filetype = "*" langdetect = "*" lxml = "*" +markdown = {version = "*", optional = true, markers = "extra == \"md\""} nltk = "*" numpy = "*" python-iso639 = "*" @@ -8603,19 +9521,20 @@ files = [ [[package]] name = "urllib3" -version = "1.26.18" +version = "2.2.1" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = ">=3.8" files = [ - {file = "urllib3-1.26.18-py2.py3-none-any.whl", hash = "sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07"}, - {file = "urllib3-1.26.18.tar.gz", hash = "sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0"}, + {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, + {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, ] [package.extras] -brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] [[package]] name = "uvicorn" @@ -8857,91 +9776,94 @@ test = ["websockets"] [[package]] name = "websockets" -version = "10.4" +version = "12.0" description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "websockets-10.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d58804e996d7d2307173d56c297cf7bc132c52df27a3efaac5e8d43e36c21c48"}, - {file = "websockets-10.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc0b82d728fe21a0d03e65f81980abbbcb13b5387f733a1a870672c5be26edab"}, - {file = "websockets-10.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ba089c499e1f4155d2a3c2a05d2878a3428cf321c848f2b5a45ce55f0d7d310c"}, - {file = "websockets-10.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33d69ca7612f0ddff3316b0c7b33ca180d464ecac2d115805c044bf0a3b0d032"}, - {file = "websockets-10.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62e627f6b6d4aed919a2052efc408da7a545c606268d5ab5bfab4432734b82b4"}, - {file = "websockets-10.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38ea7b82bfcae927eeffc55d2ffa31665dc7fec7b8dc654506b8e5a518eb4d50"}, - {file = "websockets-10.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e0cb5cc6ece6ffa75baccfd5c02cffe776f3f5c8bf486811f9d3ea3453676ce8"}, - {file = "websockets-10.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ae5e95cfb53ab1da62185e23b3130e11d64431179debac6dc3c6acf08760e9b1"}, - {file = "websockets-10.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7c584f366f46ba667cfa66020344886cf47088e79c9b9d39c84ce9ea98aaa331"}, - {file = "websockets-10.4-cp310-cp310-win32.whl", hash = "sha256:b029fb2032ae4724d8ae8d4f6b363f2cc39e4c7b12454df8df7f0f563ed3e61a"}, - {file = "websockets-10.4-cp310-cp310-win_amd64.whl", hash = "sha256:8dc96f64ae43dde92530775e9cb169979f414dcf5cff670455d81a6823b42089"}, - {file = "websockets-10.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:47a2964021f2110116cc1125b3e6d87ab5ad16dea161949e7244ec583b905bb4"}, - {file = "websockets-10.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e789376b52c295c4946403bd0efecf27ab98f05319df4583d3c48e43c7342c2f"}, - {file = "websockets-10.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7d3f0b61c45c3fa9a349cf484962c559a8a1d80dae6977276df8fd1fa5e3cb8c"}, - {file = "websockets-10.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f55b5905705725af31ccef50e55391621532cd64fbf0bc6f4bac935f0fccec46"}, - {file = "websockets-10.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00c870522cdb69cd625b93f002961ffb0c095394f06ba8c48f17eef7c1541f96"}, - {file = "websockets-10.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f38706e0b15d3c20ef6259fd4bc1700cd133b06c3c1bb108ffe3f8947be15fa"}, - {file = "websockets-10.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f2c38d588887a609191d30e902df2a32711f708abfd85d318ca9b367258cfd0c"}, - {file = "websockets-10.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:fe10ddc59b304cb19a1bdf5bd0a7719cbbc9fbdd57ac80ed436b709fcf889106"}, - {file = "websockets-10.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:90fcf8929836d4a0e964d799a58823547df5a5e9afa83081761630553be731f9"}, - {file = "websockets-10.4-cp311-cp311-win32.whl", hash = "sha256:b9968694c5f467bf67ef97ae7ad4d56d14be2751000c1207d31bf3bb8860bae8"}, - {file = "websockets-10.4-cp311-cp311-win_amd64.whl", hash = "sha256:a7a240d7a74bf8d5cb3bfe6be7f21697a28ec4b1a437607bae08ac7acf5b4882"}, - {file = "websockets-10.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:74de2b894b47f1d21cbd0b37a5e2b2392ad95d17ae983e64727e18eb281fe7cb"}, - {file = "websockets-10.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3a686ecb4aa0d64ae60c9c9f1a7d5d46cab9bfb5d91a2d303d00e2cd4c4c5cc"}, - {file = "websockets-10.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0d15c968ea7a65211e084f523151dbf8ae44634de03c801b8bd070b74e85033"}, - {file = "websockets-10.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00213676a2e46b6ebf6045bc11d0f529d9120baa6f58d122b4021ad92adabd41"}, - {file = "websockets-10.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:e23173580d740bf8822fd0379e4bf30aa1d5a92a4f252d34e893070c081050df"}, - {file = "websockets-10.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:dd500e0a5e11969cdd3320935ca2ff1e936f2358f9c2e61f100a1660933320ea"}, - {file = "websockets-10.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4239b6027e3d66a89446908ff3027d2737afc1a375f8fd3eea630a4842ec9a0c"}, - {file = "websockets-10.4-cp37-cp37m-win32.whl", hash = "sha256:8a5cc00546e0a701da4639aa0bbcb0ae2bb678c87f46da01ac2d789e1f2d2038"}, - {file = "websockets-10.4-cp37-cp37m-win_amd64.whl", hash = "sha256:a9f9a735deaf9a0cadc2d8c50d1a5bcdbae8b6e539c6e08237bc4082d7c13f28"}, - {file = "websockets-10.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5c1289596042fad2cdceb05e1ebf7aadf9995c928e0da2b7a4e99494953b1b94"}, - {file = "websockets-10.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0cff816f51fb33c26d6e2b16b5c7d48eaa31dae5488ace6aae468b361f422b63"}, - {file = "websockets-10.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:dd9becd5fe29773d140d68d607d66a38f60e31b86df75332703757ee645b6faf"}, - {file = "websockets-10.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45ec8e75b7dbc9539cbfafa570742fe4f676eb8b0d3694b67dabe2f2ceed8aa6"}, - {file = "websockets-10.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f72e5cd0f18f262f5da20efa9e241699e0cf3a766317a17392550c9ad7b37d8"}, - {file = "websockets-10.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:185929b4808b36a79c65b7865783b87b6841e852ef5407a2fb0c03381092fa3b"}, - {file = "websockets-10.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7d27a7e34c313b3a7f91adcd05134315002aaf8540d7b4f90336beafaea6217c"}, - {file = "websockets-10.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:884be66c76a444c59f801ac13f40c76f176f1bfa815ef5b8ed44321e74f1600b"}, - {file = "websockets-10.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:931c039af54fc195fe6ad536fde4b0de04da9d5916e78e55405436348cfb0e56"}, - {file = "websockets-10.4-cp38-cp38-win32.whl", hash = "sha256:db3c336f9eda2532ec0fd8ea49fef7a8df8f6c804cdf4f39e5c5c0d4a4ad9a7a"}, - {file = "websockets-10.4-cp38-cp38-win_amd64.whl", hash = "sha256:48c08473563323f9c9debac781ecf66f94ad5a3680a38fe84dee5388cf5acaf6"}, - {file = "websockets-10.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:40e826de3085721dabc7cf9bfd41682dadc02286d8cf149b3ad05bff89311e4f"}, - {file = "websockets-10.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:56029457f219ade1f2fc12a6504ea61e14ee227a815531f9738e41203a429112"}, - {file = "websockets-10.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f5fc088b7a32f244c519a048c170f14cf2251b849ef0e20cbbb0fdf0fdaf556f"}, - {file = "websockets-10.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2fc8709c00704194213d45e455adc106ff9e87658297f72d544220e32029cd3d"}, - {file = "websockets-10.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0154f7691e4fe6c2b2bc275b5701e8b158dae92a1ab229e2b940efe11905dff4"}, - {file = "websockets-10.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c6d2264f485f0b53adf22697ac11e261ce84805c232ed5dbe6b1bcb84b00ff0"}, - {file = "websockets-10.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9bc42e8402dc5e9905fb8b9649f57efcb2056693b7e88faa8fb029256ba9c68c"}, - {file = "websockets-10.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:edc344de4dac1d89300a053ac973299e82d3db56330f3494905643bb68801269"}, - {file = "websockets-10.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:84bc2a7d075f32f6ed98652db3a680a17a4edb21ca7f80fe42e38753a58ee02b"}, - {file = "websockets-10.4-cp39-cp39-win32.whl", hash = "sha256:c94ae4faf2d09f7c81847c63843f84fe47bf6253c9d60b20f25edfd30fb12588"}, - {file = "websockets-10.4-cp39-cp39-win_amd64.whl", hash = "sha256:bbccd847aa0c3a69b5f691a84d2341a4f8a629c6922558f2a70611305f902d74"}, - {file = "websockets-10.4-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:82ff5e1cae4e855147fd57a2863376ed7454134c2bf49ec604dfe71e446e2193"}, - {file = "websockets-10.4-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d210abe51b5da0ffdbf7b43eed0cfdff8a55a1ab17abbec4301c9ff077dd0342"}, - {file = "websockets-10.4-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:942de28af58f352a6f588bc72490ae0f4ccd6dfc2bd3de5945b882a078e4e179"}, - {file = "websockets-10.4-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9b27d6c1c6cd53dc93614967e9ce00ae7f864a2d9f99fe5ed86706e1ecbf485"}, - {file = "websockets-10.4-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:3d3cac3e32b2c8414f4f87c1b2ab686fa6284a980ba283617404377cd448f631"}, - {file = "websockets-10.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:da39dd03d130162deb63da51f6e66ed73032ae62e74aaccc4236e30edccddbb0"}, - {file = "websockets-10.4-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:389f8dbb5c489e305fb113ca1b6bdcdaa130923f77485db5b189de343a179393"}, - {file = "websockets-10.4-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09a1814bb15eff7069e51fed0826df0bc0702652b5cb8f87697d469d79c23576"}, - {file = "websockets-10.4-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff64a1d38d156d429404aaa84b27305e957fd10c30e5880d1765c9480bea490f"}, - {file = "websockets-10.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:b343f521b047493dc4022dd338fc6db9d9282658862756b4f6fd0e996c1380e1"}, - {file = "websockets-10.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:932af322458da7e4e35df32f050389e13d3d96b09d274b22a7aa1808f292fee4"}, - {file = "websockets-10.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6a4162139374a49eb18ef5b2f4da1dd95c994588f5033d64e0bbfda4b6b6fcf"}, - {file = "websockets-10.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c57e4c1349fbe0e446c9fa7b19ed2f8a4417233b6984277cce392819123142d3"}, - {file = "websockets-10.4-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b627c266f295de9dea86bd1112ed3d5fafb69a348af30a2422e16590a8ecba13"}, - {file = "websockets-10.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:05a7233089f8bd355e8cbe127c2e8ca0b4ea55467861906b80d2ebc7db4d6b72"}, - {file = "websockets-10.4.tar.gz", hash = "sha256:eef610b23933c54d5d921c92578ae5f89813438fded840c2e9809d378dc765d3"}, + {file = "websockets-12.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d554236b2a2006e0ce16315c16eaa0d628dab009c33b63ea03f41c6107958374"}, + {file = "websockets-12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2d225bb6886591b1746b17c0573e29804619c8f755b5598d875bb4235ea639be"}, + {file = "websockets-12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eb809e816916a3b210bed3c82fb88eaf16e8afcf9c115ebb2bacede1797d2547"}, + {file = "websockets-12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c588f6abc13f78a67044c6b1273a99e1cf31038ad51815b3b016ce699f0d75c2"}, + {file = "websockets-12.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5aa9348186d79a5f232115ed3fa9020eab66d6c3437d72f9d2c8ac0c6858c558"}, + {file = "websockets-12.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6350b14a40c95ddd53e775dbdbbbc59b124a5c8ecd6fbb09c2e52029f7a9f480"}, + {file = "websockets-12.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:70ec754cc2a769bcd218ed8d7209055667b30860ffecb8633a834dde27d6307c"}, + {file = "websockets-12.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6e96f5ed1b83a8ddb07909b45bd94833b0710f738115751cdaa9da1fb0cb66e8"}, + {file = "websockets-12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4d87be612cbef86f994178d5186add3d94e9f31cc3cb499a0482b866ec477603"}, + {file = "websockets-12.0-cp310-cp310-win32.whl", hash = "sha256:befe90632d66caaf72e8b2ed4d7f02b348913813c8b0a32fae1cc5fe3730902f"}, + {file = "websockets-12.0-cp310-cp310-win_amd64.whl", hash = "sha256:363f57ca8bc8576195d0540c648aa58ac18cf85b76ad5202b9f976918f4219cf"}, + {file = "websockets-12.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5d873c7de42dea355d73f170be0f23788cf3fa9f7bed718fd2830eefedce01b4"}, + {file = "websockets-12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3f61726cae9f65b872502ff3c1496abc93ffbe31b278455c418492016e2afc8f"}, + {file = "websockets-12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed2fcf7a07334c77fc8a230755c2209223a7cc44fc27597729b8ef5425aa61a3"}, + {file = "websockets-12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e332c210b14b57904869ca9f9bf4ca32f5427a03eeb625da9b616c85a3a506c"}, + {file = "websockets-12.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5693ef74233122f8ebab026817b1b37fe25c411ecfca084b29bc7d6efc548f45"}, + {file = "websockets-12.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e9e7db18b4539a29cc5ad8c8b252738a30e2b13f033c2d6e9d0549b45841c04"}, + {file = "websockets-12.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6e2df67b8014767d0f785baa98393725739287684b9f8d8a1001eb2839031447"}, + {file = "websockets-12.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bea88d71630c5900690fcb03161ab18f8f244805c59e2e0dc4ffadae0a7ee0ca"}, + {file = "websockets-12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dff6cdf35e31d1315790149fee351f9e52978130cef6c87c4b6c9b3baf78bc53"}, + {file = "websockets-12.0-cp311-cp311-win32.whl", hash = "sha256:3e3aa8c468af01d70332a382350ee95f6986db479ce7af14d5e81ec52aa2b402"}, + {file = "websockets-12.0-cp311-cp311-win_amd64.whl", hash = "sha256:25eb766c8ad27da0f79420b2af4b85d29914ba0edf69f547cc4f06ca6f1d403b"}, + {file = "websockets-12.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0e6e2711d5a8e6e482cacb927a49a3d432345dfe7dea8ace7b5790df5932e4df"}, + {file = "websockets-12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:dbcf72a37f0b3316e993e13ecf32f10c0e1259c28ffd0a85cee26e8549595fbc"}, + {file = "websockets-12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12743ab88ab2af1d17dd4acb4645677cb7063ef4db93abffbf164218a5d54c6b"}, + {file = "websockets-12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b645f491f3c48d3f8a00d1fce07445fab7347fec54a3e65f0725d730d5b99cb"}, + {file = "websockets-12.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9893d1aa45a7f8b3bc4510f6ccf8db8c3b62120917af15e3de247f0780294b92"}, + {file = "websockets-12.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f38a7b376117ef7aff996e737583172bdf535932c9ca021746573bce40165ed"}, + {file = "websockets-12.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f764ba54e33daf20e167915edc443b6f88956f37fb606449b4a5b10ba42235a5"}, + {file = "websockets-12.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1e4b3f8ea6a9cfa8be8484c9221ec0257508e3a1ec43c36acdefb2a9c3b00aa2"}, + {file = "websockets-12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9fdf06fd06c32205a07e47328ab49c40fc1407cdec801d698a7c41167ea45113"}, + {file = "websockets-12.0-cp312-cp312-win32.whl", hash = "sha256:baa386875b70cbd81798fa9f71be689c1bf484f65fd6fb08d051a0ee4e79924d"}, + {file = "websockets-12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ae0a5da8f35a5be197f328d4727dbcfafa53d1824fac3d96cdd3a642fe09394f"}, + {file = "websockets-12.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5f6ffe2c6598f7f7207eef9a1228b6f5c818f9f4d53ee920aacd35cec8110438"}, + {file = "websockets-12.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9edf3fc590cc2ec20dc9d7a45108b5bbaf21c0d89f9fd3fd1685e223771dc0b2"}, + {file = "websockets-12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8572132c7be52632201a35f5e08348137f658e5ffd21f51f94572ca6c05ea81d"}, + {file = "websockets-12.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:604428d1b87edbf02b233e2c207d7d528460fa978f9e391bd8aaf9c8311de137"}, + {file = "websockets-12.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a9d160fd080c6285e202327aba140fc9a0d910b09e423afff4ae5cbbf1c7205"}, + {file = "websockets-12.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87b4aafed34653e465eb77b7c93ef058516cb5acf3eb21e42f33928616172def"}, + {file = "websockets-12.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b2ee7288b85959797970114deae81ab41b731f19ebcd3bd499ae9ca0e3f1d2c8"}, + {file = "websockets-12.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7fa3d25e81bfe6a89718e9791128398a50dec6d57faf23770787ff441d851967"}, + {file = "websockets-12.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a571f035a47212288e3b3519944f6bf4ac7bc7553243e41eac50dd48552b6df7"}, + {file = "websockets-12.0-cp38-cp38-win32.whl", hash = "sha256:3c6cc1360c10c17463aadd29dd3af332d4a1adaa8796f6b0e9f9df1fdb0bad62"}, + {file = "websockets-12.0-cp38-cp38-win_amd64.whl", hash = "sha256:1bf386089178ea69d720f8db6199a0504a406209a0fc23e603b27b300fdd6892"}, + {file = "websockets-12.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ab3d732ad50a4fbd04a4490ef08acd0517b6ae6b77eb967251f4c263011a990d"}, + {file = "websockets-12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1d9697f3337a89691e3bd8dc56dea45a6f6d975f92e7d5f773bc715c15dde28"}, + {file = "websockets-12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1df2fbd2c8a98d38a66f5238484405b8d1d16f929bb7a33ed73e4801222a6f53"}, + {file = "websockets-12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23509452b3bc38e3a057382c2e941d5ac2e01e251acce7adc74011d7d8de434c"}, + {file = "websockets-12.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e5fc14ec6ea568200ea4ef46545073da81900a2b67b3e666f04adf53ad452ec"}, + {file = "websockets-12.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46e71dbbd12850224243f5d2aeec90f0aaa0f2dde5aeeb8fc8df21e04d99eff9"}, + {file = "websockets-12.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b81f90dcc6c85a9b7f29873beb56c94c85d6f0dac2ea8b60d995bd18bf3e2aae"}, + {file = "websockets-12.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a02413bc474feda2849c59ed2dfb2cddb4cd3d2f03a2fedec51d6e959d9b608b"}, + {file = "websockets-12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bbe6013f9f791944ed31ca08b077e26249309639313fff132bfbf3ba105673b9"}, + {file = "websockets-12.0-cp39-cp39-win32.whl", hash = "sha256:cbe83a6bbdf207ff0541de01e11904827540aa069293696dd528a6640bd6a5f6"}, + {file = "websockets-12.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc4e7fa5414512b481a2483775a8e8be7803a35b30ca805afa4998a84f9fd9e8"}, + {file = "websockets-12.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:248d8e2446e13c1d4326e0a6a4e9629cb13a11195051a73acf414812700badbd"}, + {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44069528d45a933997a6fef143030d8ca8042f0dfaad753e2906398290e2870"}, + {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c4e37d36f0d19f0a4413d3e18c0d03d0c268ada2061868c1e6f5ab1a6d575077"}, + {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d829f975fc2e527a3ef2f9c8f25e553eb7bc779c6665e8e1d52aa22800bb38b"}, + {file = "websockets-12.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2c71bd45a777433dd9113847af751aae36e448bc6b8c361a566cb043eda6ec30"}, + {file = "websockets-12.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0bee75f400895aef54157b36ed6d3b308fcab62e5260703add87f44cee9c82a6"}, + {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:423fc1ed29f7512fceb727e2d2aecb952c46aa34895e9ed96071821309951123"}, + {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27a5e9964ef509016759f2ef3f2c1e13f403725a5e6a1775555994966a66e931"}, + {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3181df4583c4d3994d31fb235dc681d2aaad744fbdbf94c4802485ececdecf2"}, + {file = "websockets-12.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:b067cb952ce8bf40115f6c19f478dc71c5e719b7fbaa511359795dfd9d1a6468"}, + {file = "websockets-12.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:00700340c6c7ab788f176d118775202aadea7602c5cc6be6ae127761c16d6b0b"}, + {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e469d01137942849cff40517c97a30a93ae79917752b34029f0ec72df6b46399"}, + {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffefa1374cd508d633646d51a8e9277763a9b78ae71324183693959cf94635a7"}, + {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba0cab91b3956dfa9f512147860783a1829a8d905ee218a9837c18f683239611"}, + {file = "websockets-12.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2cb388a5bfb56df4d9a406783b7f9dbefb888c09b71629351cc6b036e9259370"}, + {file = "websockets-12.0-py3-none-any.whl", hash = "sha256:dc284bbc8d7c78a6c69e0c7325ab46ee5e40bb4d50e494d8131a07ef47500e9e"}, + {file = "websockets-12.0.tar.gz", hash = "sha256:81df9cbcbb6c260de1e007e58c011bfebe2dafc8435107b0537f393dd38c8b1b"}, ] [[package]] name = "werkzeug" -version = "3.0.1" +version = "3.0.2" description = "The comprehensive WSGI web application library." optional = false python-versions = ">=3.8" files = [ - {file = "werkzeug-3.0.1-py3-none-any.whl", hash = "sha256:90a285dc0e42ad56b34e696398b8122ee4c681833fb35b8334a095d82c56da10"}, - {file = "werkzeug-3.0.1.tar.gz", hash = "sha256:507e811ecea72b18a404947aded4b3390e1db8f826b494d76550ef45bb3b1dcc"}, + {file = "werkzeug-3.0.2-py3-none-any.whl", hash = "sha256:3aac3f5da756f93030740bc235d3e09449efcf65f2f55e3602e1d851b8f48795"}, + {file = "werkzeug-3.0.2.tar.gz", hash = "sha256:e39b645a6ac92822588e7b39a692e7828724ceae0b0d702ef96701f90e70128d"}, ] [package.dependencies] @@ -9067,6 +9989,137 @@ files = [ {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"}, ] +[[package]] +name = "wsproto" +version = "1.2.0" +description = "WebSockets state-machine based protocol implementation" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736"}, + {file = "wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065"}, +] + +[package.dependencies] +h11 = ">=0.9.0,<1" + +[[package]] +name = "xxhash" +version = "3.4.1" +description = "Python binding for xxHash" +optional = false +python-versions = ">=3.7" +files = [ + {file = "xxhash-3.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:91dbfa55346ad3e18e738742236554531a621042e419b70ad8f3c1d9c7a16e7f"}, + {file = "xxhash-3.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:665a65c2a48a72068fcc4d21721510df5f51f1142541c890491afc80451636d2"}, + {file = "xxhash-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb11628470a6004dc71a09fe90c2f459ff03d611376c1debeec2d648f44cb693"}, + {file = "xxhash-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5bef2a7dc7b4f4beb45a1edbba9b9194c60a43a89598a87f1a0226d183764189"}, + {file = "xxhash-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c0f7b2d547d72c7eda7aa817acf8791f0146b12b9eba1d4432c531fb0352228"}, + {file = "xxhash-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00f2fdef6b41c9db3d2fc0e7f94cb3db86693e5c45d6de09625caad9a469635b"}, + {file = "xxhash-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:23cfd9ca09acaf07a43e5a695143d9a21bf00f5b49b15c07d5388cadf1f9ce11"}, + {file = "xxhash-3.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6a9ff50a3cf88355ca4731682c168049af1ca222d1d2925ef7119c1a78e95b3b"}, + {file = "xxhash-3.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:f1d7c69a1e9ca5faa75546fdd267f214f63f52f12692f9b3a2f6467c9e67d5e7"}, + {file = "xxhash-3.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:672b273040d5d5a6864a36287f3514efcd1d4b1b6a7480f294c4b1d1ee1b8de0"}, + {file = "xxhash-3.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4178f78d70e88f1c4a89ff1ffe9f43147185930bb962ee3979dba15f2b1cc799"}, + {file = "xxhash-3.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9804b9eb254d4b8cc83ab5a2002128f7d631dd427aa873c8727dba7f1f0d1c2b"}, + {file = "xxhash-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c09c49473212d9c87261d22c74370457cfff5db2ddfc7fd1e35c80c31a8c14ce"}, + {file = "xxhash-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:ebbb1616435b4a194ce3466d7247df23499475c7ed4eb2681a1fa42ff766aff6"}, + {file = "xxhash-3.4.1-cp310-cp310-win_arm64.whl", hash = "sha256:25dc66be3db54f8a2d136f695b00cfe88018e59ccff0f3b8f545869f376a8a46"}, + {file = "xxhash-3.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:58c49083801885273e262c0f5bbeac23e520564b8357fbb18fb94ff09d3d3ea5"}, + {file = "xxhash-3.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b526015a973bfbe81e804a586b703f163861da36d186627e27524f5427b0d520"}, + {file = "xxhash-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36ad4457644c91a966f6fe137d7467636bdc51a6ce10a1d04f365c70d6a16d7e"}, + {file = "xxhash-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:248d3e83d119770f96003271fe41e049dd4ae52da2feb8f832b7a20e791d2920"}, + {file = "xxhash-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2070b6d5bbef5ee031666cf21d4953c16e92c2f8a24a94b5c240f8995ba3b1d0"}, + {file = "xxhash-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2746035f518f0410915e247877f7df43ef3372bf36cfa52cc4bc33e85242641"}, + {file = "xxhash-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a8ba6181514681c2591840d5632fcf7356ab287d4aff1c8dea20f3c78097088"}, + {file = "xxhash-3.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0aac5010869240e95f740de43cd6a05eae180c59edd182ad93bf12ee289484fa"}, + {file = "xxhash-3.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4cb11d8debab1626181633d184b2372aaa09825bde709bf927704ed72765bed1"}, + {file = "xxhash-3.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b29728cff2c12f3d9f1d940528ee83918d803c0567866e062683f300d1d2eff3"}, + {file = "xxhash-3.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:a15cbf3a9c40672523bdb6ea97ff74b443406ba0ab9bca10ceccd9546414bd84"}, + {file = "xxhash-3.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6e66df260fed01ed8ea790c2913271641c58481e807790d9fca8bfd5a3c13844"}, + {file = "xxhash-3.4.1-cp311-cp311-win32.whl", hash = "sha256:e867f68a8f381ea12858e6d67378c05359d3a53a888913b5f7d35fbf68939d5f"}, + {file = "xxhash-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:200a5a3ad9c7c0c02ed1484a1d838b63edcf92ff538770ea07456a3732c577f4"}, + {file = "xxhash-3.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:1d03f1c0d16d24ea032e99f61c552cb2b77d502e545187338bea461fde253583"}, + {file = "xxhash-3.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c4bbba9b182697a52bc0c9f8ec0ba1acb914b4937cd4a877ad78a3b3eeabefb3"}, + {file = "xxhash-3.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9fd28a9da300e64e434cfc96567a8387d9a96e824a9be1452a1e7248b7763b78"}, + {file = "xxhash-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6066d88c9329ab230e18998daec53d819daeee99d003955c8db6fc4971b45ca3"}, + {file = "xxhash-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93805bc3233ad89abf51772f2ed3355097a5dc74e6080de19706fc447da99cd3"}, + {file = "xxhash-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:64da57d5ed586ebb2ecdde1e997fa37c27fe32fe61a656b77fabbc58e6fbff6e"}, + {file = "xxhash-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a97322e9a7440bf3c9805cbaac090358b43f650516486746f7fa482672593df"}, + {file = "xxhash-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bbe750d512982ee7d831838a5dee9e9848f3fb440e4734cca3f298228cc957a6"}, + {file = "xxhash-3.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:fd79d4087727daf4d5b8afe594b37d611ab95dc8e29fe1a7517320794837eb7d"}, + {file = "xxhash-3.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:743612da4071ff9aa4d055f3f111ae5247342931dedb955268954ef7201a71ff"}, + {file = "xxhash-3.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:b41edaf05734092f24f48c0958b3c6cbaaa5b7e024880692078c6b1f8247e2fc"}, + {file = "xxhash-3.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:a90356ead70d715fe64c30cd0969072de1860e56b78adf7c69d954b43e29d9fa"}, + {file = "xxhash-3.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ac56eebb364e44c85e1d9e9cc5f6031d78a34f0092fea7fc80478139369a8b4a"}, + {file = "xxhash-3.4.1-cp312-cp312-win32.whl", hash = "sha256:911035345932a153c427107397c1518f8ce456f93c618dd1c5b54ebb22e73747"}, + {file = "xxhash-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:f31ce76489f8601cc7b8713201ce94b4bd7b7ce90ba3353dccce7e9e1fee71fa"}, + {file = "xxhash-3.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:b5beb1c6a72fdc7584102f42c4d9df232ee018ddf806e8c90906547dfb43b2da"}, + {file = "xxhash-3.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6d42b24d1496deb05dee5a24ed510b16de1d6c866c626c2beb11aebf3be278b9"}, + {file = "xxhash-3.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b685fab18876b14a8f94813fa2ca80cfb5ab6a85d31d5539b7cd749ce9e3624"}, + {file = "xxhash-3.4.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:419ffe34c17ae2df019a4685e8d3934d46b2e0bbe46221ab40b7e04ed9f11137"}, + {file = "xxhash-3.4.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0e041ce5714f95251a88670c114b748bca3bf80cc72400e9f23e6d0d59cf2681"}, + {file = "xxhash-3.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc860d887c5cb2f524899fb8338e1bb3d5789f75fac179101920d9afddef284b"}, + {file = "xxhash-3.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:312eba88ffe0a05e332e3a6f9788b73883752be63f8588a6dc1261a3eaaaf2b2"}, + {file = "xxhash-3.4.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:e01226b6b6a1ffe4e6bd6d08cfcb3ca708b16f02eb06dd44f3c6e53285f03e4f"}, + {file = "xxhash-3.4.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9f3025a0d5d8cf406a9313cd0d5789c77433ba2004b1c75439b67678e5136537"}, + {file = "xxhash-3.4.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:6d3472fd4afef2a567d5f14411d94060099901cd8ce9788b22b8c6f13c606a93"}, + {file = "xxhash-3.4.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:43984c0a92f06cac434ad181f329a1445017c33807b7ae4f033878d860a4b0f2"}, + {file = "xxhash-3.4.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a55e0506fdb09640a82ec4f44171273eeabf6f371a4ec605633adb2837b5d9d5"}, + {file = "xxhash-3.4.1-cp37-cp37m-win32.whl", hash = "sha256:faec30437919555b039a8bdbaba49c013043e8f76c999670aef146d33e05b3a0"}, + {file = "xxhash-3.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:c9e1b646af61f1fc7083bb7b40536be944f1ac67ef5e360bca2d73430186971a"}, + {file = "xxhash-3.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:961d948b7b1c1b6c08484bbce3d489cdf153e4122c3dfb07c2039621243d8795"}, + {file = "xxhash-3.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:719a378930504ab159f7b8e20fa2aa1896cde050011af838af7e7e3518dd82de"}, + {file = "xxhash-3.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74fb5cb9406ccd7c4dd917f16630d2e5e8cbbb02fc2fca4e559b2a47a64f4940"}, + {file = "xxhash-3.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5dab508ac39e0ab988039bc7f962c6ad021acd81fd29145962b068df4148c476"}, + {file = "xxhash-3.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c59f3e46e7daf4c589e8e853d700ef6607afa037bfad32c390175da28127e8c"}, + {file = "xxhash-3.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cc07256eff0795e0f642df74ad096f8c5d23fe66bc138b83970b50fc7f7f6c5"}, + {file = "xxhash-3.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e9f749999ed80f3955a4af0eb18bb43993f04939350b07b8dd2f44edc98ffee9"}, + {file = "xxhash-3.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7688d7c02149a90a3d46d55b341ab7ad1b4a3f767be2357e211b4e893efbaaf6"}, + {file = "xxhash-3.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a8b4977963926f60b0d4f830941c864bed16aa151206c01ad5c531636da5708e"}, + {file = "xxhash-3.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:8106d88da330f6535a58a8195aa463ef5281a9aa23b04af1848ff715c4398fb4"}, + {file = "xxhash-3.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4c76a77dbd169450b61c06fd2d5d436189fc8ab7c1571d39265d4822da16df22"}, + {file = "xxhash-3.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:11f11357c86d83e53719c592021fd524efa9cf024dc7cb1dfb57bbbd0d8713f2"}, + {file = "xxhash-3.4.1-cp38-cp38-win32.whl", hash = "sha256:0c786a6cd74e8765c6809892a0d45886e7c3dc54de4985b4a5eb8b630f3b8e3b"}, + {file = "xxhash-3.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:aabf37fb8fa27430d50507deeab2ee7b1bcce89910dd10657c38e71fee835594"}, + {file = "xxhash-3.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6127813abc1477f3a83529b6bbcfeddc23162cece76fa69aee8f6a8a97720562"}, + {file = "xxhash-3.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef2e194262f5db16075caea7b3f7f49392242c688412f386d3c7b07c7733a70a"}, + {file = "xxhash-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71be94265b6c6590f0018bbf73759d21a41c6bda20409782d8117e76cd0dfa8b"}, + {file = "xxhash-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10e0a619cdd1c0980e25eb04e30fe96cf8f4324758fa497080af9c21a6de573f"}, + {file = "xxhash-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa122124d2e3bd36581dd78c0efa5f429f5220313479fb1072858188bc2d5ff1"}, + {file = "xxhash-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17032f5a4fea0a074717fe33477cb5ee723a5f428de7563e75af64bfc1b1e10"}, + {file = "xxhash-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca7783b20e3e4f3f52f093538895863f21d18598f9a48211ad757680c3bd006f"}, + {file = "xxhash-3.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d77d09a1113899fad5f354a1eb4f0a9afcf58cefff51082c8ad643ff890e30cf"}, + {file = "xxhash-3.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:21287bcdd299fdc3328cc0fbbdeaa46838a1c05391264e51ddb38a3f5b09611f"}, + {file = "xxhash-3.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:dfd7a6cc483e20b4ad90224aeb589e64ec0f31e5610ab9957ff4314270b2bf31"}, + {file = "xxhash-3.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:543c7fcbc02bbb4840ea9915134e14dc3dc15cbd5a30873a7a5bf66039db97ec"}, + {file = "xxhash-3.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:fe0a98d990e433013f41827b62be9ab43e3cf18e08b1483fcc343bda0d691182"}, + {file = "xxhash-3.4.1-cp39-cp39-win32.whl", hash = "sha256:b9097af00ebf429cc7c0e7d2fdf28384e4e2e91008130ccda8d5ae653db71e54"}, + {file = "xxhash-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:d699b921af0dcde50ab18be76c0d832f803034d80470703700cb7df0fbec2832"}, + {file = "xxhash-3.4.1-cp39-cp39-win_arm64.whl", hash = "sha256:2be491723405e15cc099ade1280133ccfbf6322d2ef568494fb7d07d280e7eee"}, + {file = "xxhash-3.4.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:431625fad7ab5649368c4849d2b49a83dc711b1f20e1f7f04955aab86cd307bc"}, + {file = "xxhash-3.4.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc6dbd5fc3c9886a9e041848508b7fb65fd82f94cc793253990f81617b61fe49"}, + {file = "xxhash-3.4.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3ff8dbd0ec97aec842476cb8ccc3e17dd288cd6ce3c8ef38bff83d6eb927817"}, + {file = "xxhash-3.4.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef73a53fe90558a4096e3256752268a8bdc0322f4692ed928b6cd7ce06ad4fe3"}, + {file = "xxhash-3.4.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:450401f42bbd274b519d3d8dcf3c57166913381a3d2664d6609004685039f9d3"}, + {file = "xxhash-3.4.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a162840cf4de8a7cd8720ff3b4417fbc10001eefdd2d21541a8226bb5556e3bb"}, + {file = "xxhash-3.4.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b736a2a2728ba45017cb67785e03125a79d246462dfa892d023b827007412c52"}, + {file = "xxhash-3.4.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d0ae4c2e7698adef58710d6e7a32ff518b66b98854b1c68e70eee504ad061d8"}, + {file = "xxhash-3.4.1-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6322c4291c3ff174dcd104fae41500e75dad12be6f3085d119c2c8a80956c51"}, + {file = "xxhash-3.4.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:dd59ed668801c3fae282f8f4edadf6dc7784db6d18139b584b6d9677ddde1b6b"}, + {file = "xxhash-3.4.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:92693c487e39523a80474b0394645b393f0ae781d8db3474ccdcead0559ccf45"}, + {file = "xxhash-3.4.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4603a0f642a1e8d7f3ba5c4c25509aca6a9c1cc16f85091004a7028607ead663"}, + {file = "xxhash-3.4.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fa45e8cbfbadb40a920fe9ca40c34b393e0b067082d94006f7f64e70c7490a6"}, + {file = "xxhash-3.4.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:595b252943b3552de491ff51e5bb79660f84f033977f88f6ca1605846637b7c6"}, + {file = "xxhash-3.4.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:562d8b8f783c6af969806aaacf95b6c7b776929ae26c0cd941d54644ea7ef51e"}, + {file = "xxhash-3.4.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:41ddeae47cf2828335d8d991f2d2b03b0bdc89289dc64349d712ff8ce59d0647"}, + {file = "xxhash-3.4.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c44d584afdf3c4dbb3277e32321d1a7b01d6071c1992524b6543025fb8f4206f"}, + {file = "xxhash-3.4.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd7bddb3a5b86213cc3f2c61500c16945a1b80ecd572f3078ddbbe68f9dabdfb"}, + {file = "xxhash-3.4.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9ecb6c987b62437c2f99c01e97caf8d25660bf541fe79a481d05732e5236719c"}, + {file = "xxhash-3.4.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:696b4e18b7023527d5c50ed0626ac0520edac45a50ec7cf3fc265cd08b1f4c03"}, + {file = "xxhash-3.4.1.tar.gz", hash = "sha256:0379d6cf1ff987cd421609a264ce025e74f346e3e145dd106c0cc2e3ec3f99a9"}, +] + [[package]] name = "yarl" version = "1.9.4" @@ -9170,21 +10223,6 @@ files = [ idna = ">=2.0" multidict = ">=4.0" -[[package]] -name = "zep-python" -version = "2.0.0rc5" -description = "Long-Term Memory for AI Assistants. This is the Python client for the Zep service." -optional = false -python-versions = "<4,>=3.9.0" -files = [ - {file = "zep_python-2.0.0rc5-py3-none-any.whl", hash = "sha256:8b1b5c22c9e1ef439c9ef3d785347abf89b1243c7149e32025dd065cc022af40"}, - {file = "zep_python-2.0.0rc5.tar.gz", hash = "sha256:e6ced8089760374dead948d6b4b88fceb09a356bf9a7fe182b4ceb6e828f0bb1"}, -] - -[package.dependencies] -httpx = ">=0.24.0,<0.29.0" -pydantic = ">=2.0.0" - [[package]] name = "zipp" version = "3.18.1" @@ -9278,5 +10316,5 @@ local = ["ctransformers", "llama-cpp-python", "sentence-transformers"] [metadata] lock-version = "2.0" -python-versions = ">=3.9,<3.12" -content-hash = "1c79f55577a8fa603c09b2b7c02a01a7a397960c6c9c134dcee7e2f6eeea3d9e" +python-versions = ">=3.10,<3.12" +content-hash = "ed8605b2934fceb591d03d5be7461ed05a8f427512b693ce1baefeaa4fa21500" diff --git a/pyproject.toml b/pyproject.toml index 45661c562..5e34c2a0f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langflow" -version = "0.6.12" +version = "1.0.0a4" description = "A Python package with a built-in web application" authors = ["Logspace "] maintainers = [ @@ -23,91 +23,64 @@ documentation = "https://docs.langflow.org" [tool.poetry.scripts] langflow = "langflow.__main__:main" + [tool.poetry.dependencies] -python = ">=3.9,<3.12" -fastapi = "^0.109.0" -uvicorn = "^0.27.0" +python = ">=3.10,<3.12" +langflow-base = { path = "./src/backend/base", develop = true } beautifulsoup4 = "^4.12.2" google-search-results = "^2.4.1" google-api-python-client = "^2.118.0" -typer = "^0.9.0" -gunicorn = "^21.2.0" -langchain = "~0.1.0" -openai = "^1.12.0" -pandas = "2.2.0" -chromadb = "^0.4.0" huggingface-hub = { version = "^0.20.0", extras = ["inference"] } -rich = "^13.7.0" llama-cpp-python = { version = "~0.2.0", optional = true } networkx = "^3.1" -unstructured = "^0.12.0" -pypdf = "^4.0.0" -lxml = "^4.9.2" pysrt = "^1.1.2" fake-useragent = "^1.4.0" -docstring-parser = "^0.15" psycopg2-binary = "^2.9.6" pyarrow = "^14.0.0" -tiktoken = "~0.6.0" wikipedia = "^1.4.0" qdrant-client = "^1.7.0" -websockets = "^10.3" weaviate-client = "*" sentence-transformers = { version = "^2.3.1", optional = true } ctransformers = { version = "^0.2.10", optional = true } -cohere = "^4.47.0" -python-multipart = "^0.0.7" -sqlmodel = "^0.0.14" +cohere = "^5.1.7" faiss-cpu = "^1.7.4" -orjson = "3.9.15" -multiprocess = "^0.70.14" -cachetools = "^5.3.1" types-cachetools = "^5.3.0.5" -platformdirs = "^4.2.0" pinecone-client = "^3.0.3" pymongo = "^4.6.0" supabase = "^2.3.0" certifi = "^2023.11.17" -google-cloud-aiplatform = "^1.42.0" psycopg = "^3.1.9" psycopg-binary = "^3.1.9" fastavro = "^1.8.0" -langchain-experimental = "*" celery = { extras = ["redis"], version = "^5.3.6", optional = true } redis = { version = "^5.0.1", optional = true } flower = { version = "^2.0.0", optional = true } -alembic = "^1.13.0" -passlib = "^1.7.4" -bcrypt = "4.0.1" -python-jose = "^3.3.0" metaphor-python = "^0.1.11" -pydantic = "^2.6.0" -pydantic-settings = "^2.1.0" -zep-python = "*" pywin32 = { version = "^306", markers = "sys_platform == 'win32'" } -loguru = "^0.7.1" langfuse = "^2.9.0" -pillow = "^10.2.0" metal-sdk = "^2.5.0" markupsafe = "^2.1.3" extract-msg = "^0.47.0" # jq is not available for windows -jq = { version = "^1.6.0", markers = "sys_platform != 'win32'" } boto3 = "^1.34.0" numexpr = "^2.8.6" -qianfan = "0.3.0" +qianfan = "0.3.5" pgvector = "^0.2.3" pyautogen = "^0.2.0" -langchain-google-genai = "^0.0.6" +langchain-google-genai = "^1.0.1" +langchain-cohere = "^0.1.0rc1" elasticsearch = "^8.12.0" pytube = "^15.0.0" -llama-index = "0.9.48" -langchain-openai = "^0.0.6" -urllib3 = "<2" -langchain-anthropic = "^0.1.4" +llama-index = "^0.10.13" +langchain-openai = "^0.0.5" +unstructured = { extras = ["md"], version = "^0.12.4" } +dspy-ai = "^2.4.0" +crewai = "^0.22.5" +html2text = "^2024.2.26" +assemblyai = "^0.23.1" +litellm = "^1.34.22" [tool.poetry.group.dev.dependencies] -pytest-asyncio = "^0.23.1" types-redis = "^4.6.0.5" ipykernel = "^6.29.0" mypy = "^1.8.0" @@ -129,10 +102,12 @@ types-pywin32 = "^306.0.0.4" types-google-cloud-ndb = "^2.2.0.0" pytest-sugar = "^1.0.0" pytest-instafail = "^0.5.0" +pytest-asyncio = "^0.23.0" +respx = "^0.20.2" [tool.poetry.extras] -deploy = ["langchain-serve", "celery", "redis", "flower"] +deploy = ["celery", "redis", "flower"] local = ["llama-cpp-python", "sentence-transformers", "ctransformers"] all = ["deploy", "local"] diff --git a/scripts/setup/setup_env.sh b/scripts/setup/setup_env.sh new file mode 100644 index 000000000..70f580784 --- /dev/null +++ b/scripts/setup/setup_env.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# Create a .env if it doesn't exist, log all cases +if [ ! -f .env ]; then + echo "Creating .env file" + touch .env +else + echo ".env file already exists" +fi \ No newline at end of file diff --git a/scripts/setup/update_poetry.sh b/scripts/setup/update_poetry.sh new file mode 100644 index 000000000..94c51fd56 --- /dev/null +++ b/scripts/setup/update_poetry.sh @@ -0,0 +1,148 @@ +#!/bin/bash + +# Check if version argument is provided +if [ -z "$1" ] +then + echo "No argument supplied. Please provide the Poetry version to check." + exit 1 +fi + +# Utility function to display an error message and exit +exit_with_message() { + echo "$1" >&2 + exit 1 +} + +# Check if version argument is provided +if [ -z "$1" ]; then + exit_with_message "No argument supplied. Please provide the Poetry version to check." +fi + +# Detect Operating System +OS="$(uname -s)" +case "$OS" in + Darwin) + OS="macOS" + ;; + Linux) + OS="Linux" + ;; + *) + exit_with_message "Unsupported operating system. This script supports macOS and Linux." + ;; +esac + +echo "Detected Operating System: $OS" + +# Installation of pipx based on the detected OS +install_pipx() { + case $1 in + macOS) + # macOS installation using Homebrew + command -v brew >/dev/null 2>&1 || exit_with_message "Homebrew is not installed. Please install Homebrew first." + echo "Installing pipx using Homebrew..." + brew install pipx + pipx ensurepath + ;; + Linux) + # Linux installation. Further checks are needed to distinguish between distributions + if grep -qEi "(ubuntu|debian)" /etc/*release; then + echo "Installing pipx on Ubuntu/Debian..." + sudo apt update + sudo apt install pipx -y + elif grep -qEi "fedora" /etc/*release; then + echo "Installing pipx on Fedora..." + sudo dnf install pipx -y + else + echo "Installing pipx using pip (other Linux distributions)..." + python3 -m pip install --user pipx + fi + pipx ensurepath + ;; + *) + exit_with_message "Unsupported operating system for pipx installation." + ;; + esac +} + +# Function to fetch the latest version of pipx from GitHub and compare with the installed version +check_for_pipx_update() { + echo "Checking for updates to pipx..." + # Fetch the latest version of pipx, ensuring only to capture the numeric version without 'v' prefix. + local latest_version=$(curl -s https://api.github.com/repos/pypa/pipx/releases/latest | grep '"tag_name":' | sed -E 's/.*"tag_name": "v?([^"]+)".*/\1/') + # Extract the current installed version of pipx. + local current_version=$(pipx --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+') + + if [[ "$latest_version" == "$current_version" ]]; then + echo "You have the latest version of pipx ($current_version)." + else + echo "A newer version of pipx ($latest_version) is available. You have $current_version. Do you want to update? (yes/no)" + read -r user_input + if [[ "$user_input" == "yes" ]]; then + echo "Updating pipx..." + case "$OS" in + macOS) + brew upgrade pipx + ;; + Linux) + if grep -qEi "(ubuntu|debian)" /etc/*release; then + sudo apt update + sudo apt install --only-upgrade pipx -y + elif grep -qEi "fedora" /etc/*release; then + sudo dnf upgrade pipx -y + else + python3 -m pip install --user --upgrade pipx + fi + ;; + *) + exit_with_message "Unsupported operating system for pipx update." + ;; + esac + pipx ensurepath + echo "pipx updated to version $latest_version" + else + echo "Not updating pipx at this time." + fi + fi +} + +# Now, modify the existing check to call check_for_pipx_update even if pipx is installed +if ! command -v pipx &> /dev/null; then + echo "Pipx is not installed. Installing..." + install_pipx "$OS" + echo "Pipx installed successfully." +else + echo "Pipx is already installed." + check_for_pipx_update +fi + + +echo "Checking Poetry installation..." + +# Check if Poetry is installed +if ! command -v poetry &> /dev/null +then + echo "Poetry is not installed. Installing..." + # Also install python 3.10 and use + pipx install poetry --python python3.10 --fetch-missing-python + echo "Poetry installed successfully." +else + echo "Poetry is already installed." +fi + +echo "Checking Poetry version..." + +# Check Poetry version +poetry_version=$(poetry --version | awk '{print $3}' | tr -d '()') +echo "Current Poetry version: $poetry_version" + +# Compare version +if [[ "$(printf '%s\n' "$1" "$poetry_version" | sort -V | head -n1)" != "$1" ]]; then + echo "Poetry version is lower than $1. Updating..." + # Update Poetry + poetry self update + echo "Poetry updated successfully." +else + echo "Poetry version is $1 or higher. No need to update." +fi + diff --git a/scripts/update_dependencies.py b/scripts/update_dependencies.py new file mode 100644 index 000000000..c70cf8f8f --- /dev/null +++ b/scripts/update_dependencies.py @@ -0,0 +1,51 @@ +import re +from pathlib import Path + + +def read_version_from_pyproject(file_path): + with open(file_path, "r") as file: + for line in file: + match = re.search(r'version = "(.*)"', line) + if match: + return match.group(1) + return None + + +def get_version_from_pypi(package_name): + import requests + + response = requests.get(f"https://pypi.org/pypi/{package_name}/json") + if response.ok: + return response.json()["info"]["version"] + return None + + +def update_pyproject_dependency(pyproject_path, version): + pattern = re.compile(r'langflow-base = \{ path = "\./src/backend/base", develop = true \}') + replacement = f'langflow-base = "^{version}"' + with open(pyproject_path, "r") as file: + content = file.read() + content = pattern.sub(replacement, content) + with open(pyproject_path, "w") as file: + file.write(content) + + +if __name__ == "__main__": + # Backing up files + pyproject_path = Path(__file__).resolve().parent / "../pyproject.toml" + pyproject_path = pyproject_path.resolve() + with open(pyproject_path, "r") as original, open(pyproject_path.with_name("pyproject.toml.bak"), "w") as backup: + backup.write(original.read()) + # Now backup poetry.lock + with open(pyproject_path.with_name("poetry.lock"), "r") as original, open( + pyproject_path.with_name("poetry.lock.bak"), "w" + ) as backup: + backup.write(original.read()) + + # Reading version and updating pyproject.toml + langflow_base_path = Path(__file__).resolve().parent / "../src/backend/base/pyproject.toml" + version = get_version_from_pypi("langflow-base") + if version: + update_pyproject_dependency(pyproject_path, version) + else: + print("Error: Version not found.") diff --git a/src/backend/langflow/interface/document_loaders/__init__.py b/src/backend/base/README.md similarity index 100% rename from src/backend/langflow/interface/document_loaders/__init__.py rename to src/backend/base/README.md diff --git a/src/backend/langflow/__main__.py b/src/backend/base/langflow/__main__.py similarity index 85% rename from src/backend/langflow/__main__.py rename to src/backend/base/langflow/__main__.py index bc430e941..55f792c3c 100644 --- a/src/backend/langflow/__main__.py +++ b/src/backend/base/langflow/__main__.py @@ -1,18 +1,20 @@ import platform import socket import sys +import time +import webbrowser from pathlib import Path from typing import Optional +import httpx import typer from dotenv import load_dotenv -from multiprocess import cpu_count # type: ignore +from multiprocess import Process, cpu_count # type: ignore from rich import box from rich import print as rprint from rich.console import Console from rich.panel import Panel from rich.table import Table -from sqlmodel import select from langflow.main import setup_app from langflow.services.database.utils import session_getter @@ -71,7 +73,7 @@ def update_settings( dev: bool = False, remove_api_keys: bool = False, components_path: Optional[Path] = None, - store: bool = False, + store: bool = True, ): """Update the settings from a config file.""" @@ -95,33 +97,6 @@ def update_settings( settings_service.settings.update_settings(STORE=False) -def version_callback(value: bool): - """ - Show the version and exit. - """ - from langflow import __version__ - - if value: - typer.echo(f"Langflow Version: {__version__}") - raise typer.Exit() - - -@app.callback() -def main_entry_point( - version: bool = typer.Option( - None, - "--version", - callback=version_callback, - is_eager=True, - help="Show the version and exit.", - ), -): - """ - Main entry point for the Langflow CLI. - """ - pass - - @app.command() def run( host: str = typer.Option("127.0.0.1", help="Host to bind the server to.", envvar="LANGFLOW_HOST"), @@ -174,13 +149,13 @@ def run( Run the Langflow. """ + configure(log_level=log_level, log_file=log_file) set_var_for_macos_issue() # override env variables with .env file if env_file: load_dotenv(env_file, override=True) - configure(log_level=log_level, log_file=log_file) update_settings( config, dev=dev, @@ -213,12 +188,23 @@ def run( run_on_windows(host, port, log_level, options, app) else: # Run using gunicorn on Linux - run_on_mac_or_linux(host, port, log_level, options, app) + run_on_mac_or_linux(host, port, log_level, options, app, open_browser) -def run_on_mac_or_linux(host, port, log_level, options, app): +def run_on_mac_or_linux(host, port, log_level, options, app, open_browser=True): + webapp_process = Process(target=run_langflow, args=(host, port, log_level, options, app)) + webapp_process.start() + status_code = 0 + while status_code != 200: + try: + status_code = httpx.get(f"http://{host}:{port}/health").status_code + + except Exception: + time.sleep(1) + print_banner(host, port) - run_langflow(host, port, log_level, options, app) + if open_browser: + webbrowser.open(f"http://{host}:{port}") def run_on_windows(host, port, log_level, options, app): @@ -260,10 +246,18 @@ def get_free_port(port): def print_banner(host, port): - # console = Console() + try: + from langflow.version import __version__ # type: ignore - word = "Langflow" - colors = ["#3300cc"] + version = __version__ + word = "Langflow" + except ImportError: + from importlib import metadata + + version = metadata.version("langflow-base") + word = "Langflow Base" + + colors = ["#6e42f5"] styled_word = "" @@ -273,7 +267,7 @@ def print_banner(host, port): # Title with emojis and gradient text title = ( - f"[bold]Welcome to :chains: {styled_word} [/bold]\n\n" + f"[bold]Welcome to :chains: {styled_word} v{version}[/bold]\n" f"Access [link=http://{host}:{port}]http://{host}:{port}[/link]" ) info_text = ( @@ -293,26 +287,25 @@ def run_langflow(host, port, log_level, options, app): Run Langflow server on localhost """ try: - if platform.system() in ["Windows", "Darwin"]: + if platform.system() in ["Windows"]: # Run using uvicorn on MacOS and Windows # Windows doesn't support gunicorn # MacOS requires an env variable to be set to use gunicorn - import uvicorn uvicorn.run( app, host=host, port=port, - log_level=log_level, + log_level=log_level.lower(), + loop="asyncio", ) else: from langflow.server import LangflowApplication LangflowApplication(app, options).run() except KeyboardInterrupt: - logger.info("Shutting down server") - sys.exit(0) + pass except Exception as e: logger.exception(e) sys.exit(1) @@ -322,7 +315,7 @@ def run_langflow(host, port, log_level, options, app): def superuser( username: str = typer.Option(..., prompt=True, help="Username for the superuser."), password: str = typer.Option(..., prompt=True, hide_input=True, help="Password for the superuser."), - log_level: str = typer.Option("critical", help="Logging level.", envvar="LANGFLOW_LOG_LEVEL"), + log_level: str = typer.Option("error", help="Logging level.", envvar="LANGFLOW_LOG_LEVEL"), ): """ Create a superuser. @@ -337,7 +330,7 @@ def superuser( # Verify that the superuser was created from langflow.services.database.models.user.model import User - user: User = session.exec(select(User).where(User.username == username)).first() + user: User = session.query(User).filter(User.username == username).first() if user is None or not user.is_superuser: typer.echo("Superuser creation failed.") return @@ -349,23 +342,11 @@ def superuser( @app.command() -def migration( - test: bool = typer.Option(True, help="Run migrations in test mode."), - fix: bool = typer.Option( - False, - help="Fix migrations. This is a destructive operation, and should only be used if you know what you are doing.", - ), -): +def migration(test: bool = typer.Option(True, help="Run migrations in test mode.")): """ Run or test migrations. """ - if fix: - if not typer.confirm( - "This will delete all data necessary to fix migrations. Are you sure you want to continue?" - ): - raise typer.Abort() - - initialize_services(fix_migration=fix) + initialize_services() db_service = get_db_service() if not test: db_service.run_migrations() diff --git a/src/backend/langflow/alembic.ini b/src/backend/base/langflow/alembic.ini similarity index 100% rename from src/backend/langflow/alembic.ini rename to src/backend/base/langflow/alembic.ini diff --git a/src/backend/langflow/alembic/README b/src/backend/base/langflow/alembic/README similarity index 100% rename from src/backend/langflow/alembic/README rename to src/backend/base/langflow/alembic/README diff --git a/src/backend/langflow/alembic/env.py b/src/backend/base/langflow/alembic/env.py similarity index 72% rename from src/backend/langflow/alembic/env.py rename to src/backend/base/langflow/alembic/env.py index 479db05bb..7400906c8 100644 --- a/src/backend/langflow/alembic/env.py +++ b/src/backend/base/langflow/alembic/env.py @@ -1,4 +1,5 @@ import os +import warnings from logging.config import fileConfig from alembic import context @@ -62,24 +63,32 @@ def run_migrations_online() -> None: and associate a connection with the context. """ - from langflow.services.deps import get_db_service try: + from langflow.services.database.factory import DatabaseServiceFactory + from langflow.services.deps import get_db_service + from langflow.services.manager import initialize_settings_service, service_manager + + initialize_settings_service() + service_manager.register_factory(DatabaseServiceFactory()) connectable = get_db_service().engine except Exception as e: logger.error(f"Error getting database engine: {e}") + url = os.getenv("LANGFLOW_DATABASE_URL") + url = url or config.get_main_option("sqlalchemy.url") + if url: + config.set_main_option("sqlalchemy.url", url) connectable = engine_from_config( config.get_section(config.config_ini_section, {}), prefix="sqlalchemy.", poolclass=pool.NullPool, ) - with connectable.connect() as connection: - context.configure( - connection=connection, target_metadata=target_metadata, render_as_batch=True - ) - - with context.begin_transaction(): - context.run_migrations() + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + with connectable.connect() as connection: + context.configure(connection=connection, target_metadata=target_metadata, render_as_batch=True) + with context.begin_transaction(): + context.run_migrations() if context.is_offline_mode(): diff --git a/src/backend/langflow/alembic/script.py.mako b/src/backend/base/langflow/alembic/script.py.mako similarity index 90% rename from src/backend/langflow/alembic/script.py.mako rename to src/backend/base/langflow/alembic/script.py.mako index 2fbdc930d..bc9bca83a 100644 --- a/src/backend/langflow/alembic/script.py.mako +++ b/src/backend/base/langflow/alembic/script.py.mako @@ -23,10 +23,12 @@ depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)} def upgrade() -> None: conn = op.get_bind() inspector = Inspector.from_engine(conn) # type: ignore + table_names = inspector.get_table_names() ${upgrades if upgrades else "pass"} def downgrade() -> None: conn = op.get_bind() inspector = Inspector.from_engine(conn) # type: ignore + table_names = inspector.get_table_names() ${downgrades if downgrades else "pass"} diff --git a/src/backend/langflow/alembic/versions/006b3990db50_add_unique_constraints.py b/src/backend/base/langflow/alembic/versions/006b3990db50_add_unique_constraints.py similarity index 93% rename from src/backend/langflow/alembic/versions/006b3990db50_add_unique_constraints.py rename to src/backend/base/langflow/alembic/versions/006b3990db50_add_unique_constraints.py index 68b765160..df59c4e9f 100644 --- a/src/backend/langflow/alembic/versions/006b3990db50_add_unique_constraints.py +++ b/src/backend/base/langflow/alembic/versions/006b3990db50_add_unique_constraints.py @@ -26,9 +26,8 @@ def upgrade() -> None: flow_constraints = inspector.get_unique_constraints("flow") user_constraints = inspector.get_unique_constraints("user") try: - if not any(constraint['column_names'] == ['id'] for constraint in api_key_constraints): + if not any(constraint["column_names"] == ["id"] for constraint in api_key_constraints): with op.batch_alter_table("apikey", schema=None) as batch_op: - batch_op.create_unique_constraint("uq_apikey_id", ["id"]) if not any(constraint["column_names"] == ["id"] for constraint in flow_constraints): with op.batch_alter_table("flow", schema=None) as batch_op: @@ -51,16 +50,13 @@ def downgrade() -> None: flow_constraints = inspector.get_unique_constraints("flow") user_constraints = inspector.get_unique_constraints("user") try: - if any( - constraint["name"] == "uq_apikey_id" for constraint in api_key_constraints - ): + if any(constraint["name"] == "uq_apikey_id" for constraint in api_key_constraints): with op.batch_alter_table("user", schema=None) as batch_op: batch_op.drop_constraint("uq_user_id", type_="unique") if any(constraint["name"] == "uq_flow_id" for constraint in flow_constraints): with op.batch_alter_table("flow", schema=None) as batch_op: batch_op.drop_constraint("uq_flow_id", type_="unique") if any(constraint["name"] == "uq_user_id" for constraint in user_constraints): - with op.batch_alter_table("apikey", schema=None) as batch_op: batch_op.drop_constraint("uq_apikey_id", type_="unique") except Exception as e: diff --git a/src/backend/langflow/alembic/versions/0b8757876a7c_.py b/src/backend/base/langflow/alembic/versions/0b8757876a7c_.py similarity index 100% rename from src/backend/langflow/alembic/versions/0b8757876a7c_.py rename to src/backend/base/langflow/alembic/versions/0b8757876a7c_.py diff --git a/src/backend/base/langflow/alembic/versions/1a110b568907_replace_credential_table_with_variable.py b/src/backend/base/langflow/alembic/versions/1a110b568907_replace_credential_table_with_variable.py new file mode 100644 index 000000000..e27d088d0 --- /dev/null +++ b/src/backend/base/langflow/alembic/versions/1a110b568907_replace_credential_table_with_variable.py @@ -0,0 +1,65 @@ +"""Replace Credential table with Variable + +Revision ID: 1a110b568907 +Revises: 63b9c451fd30 +Create Date: 2024-03-25 09:40:02.743453 + +""" +from typing import Sequence, Union + +import sqlalchemy as sa +import sqlmodel +from alembic import op +from sqlalchemy.engine.reflection import Inspector + +# revision identifiers, used by Alembic. +revision: str = "1a110b568907" +down_revision: Union[str, None] = "63b9c451fd30" +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + conn = op.get_bind() + inspector = Inspector.from_engine(conn) # type: ignore + table_names = inspector.get_table_names() + # ### commands auto generated by Alembic - please adjust! ### + if "variable" not in table_names: + op.create_table( + "variable", + sa.Column("name", sqlmodel.sql.sqltypes.AutoString(), nullable=True), + sa.Column("value", sqlmodel.sql.sqltypes.AutoString(), nullable=True), + sa.Column("type", sqlmodel.sql.sqltypes.AutoString(), nullable=True), + sa.Column("id", sqlmodel.sql.sqltypes.GUID(), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=False), + sa.Column("updated_at", sa.DateTime(), nullable=True), + sa.Column("user_id", sqlmodel.sql.sqltypes.GUID(), nullable=False), + sa.ForeignKeyConstraint(["user_id"], ["user.id"], name="fk_variable_user_id"), + sa.PrimaryKeyConstraint("id"), + ) + if "credential" in table_names: + op.drop_table("credential") + # ### end Alembic commands ### + + +def downgrade() -> None: + conn = op.get_bind() + inspector = Inspector.from_engine(conn) # type: ignore + table_names = inspector.get_table_names() + # ### commands auto generated by Alembic - please adjust! ### + if "credential" not in table_names: + op.create_table( + "credential", + sa.Column("name", sa.VARCHAR(), nullable=True), + sa.Column("value", sa.VARCHAR(), nullable=True), + sa.Column("provider", sa.VARCHAR(), nullable=True), + sa.Column("user_id", sa.CHAR(length=32), nullable=False), + sa.Column("id", sa.CHAR(length=32), nullable=False), + sa.Column("created_at", sa.DATETIME(), nullable=False), + sa.Column("updated_at", sa.DATETIME(), nullable=True), + sa.ForeignKeyConstraint(["user_id"], ["user.id"], name="fk_credential_user_id"), + sa.PrimaryKeyConstraint("id"), + ) + if "variable" in table_names: + op.drop_table("variable") + # ### end Alembic commands ### diff --git a/src/backend/langflow/alembic/versions/1ef9c4f3765d_.py b/src/backend/base/langflow/alembic/versions/1ef9c4f3765d_.py similarity index 83% rename from src/backend/langflow/alembic/versions/1ef9c4f3765d_.py rename to src/backend/base/langflow/alembic/versions/1ef9c4f3765d_.py index df92f1f02..db78e33bd 100644 --- a/src/backend/langflow/alembic/versions/1ef9c4f3765d_.py +++ b/src/backend/base/langflow/alembic/versions/1ef9c4f3765d_.py @@ -24,10 +24,8 @@ def upgrade() -> None: # ### commands auto generated by Alembic - please adjust! ### try: with op.batch_alter_table("apikey", schema=None) as batch_op: - batch_op.alter_column( - "name", existing_type=sqlmodel.sql.sqltypes.AutoString(), nullable=True - ) - except Exception as e: + batch_op.alter_column("name", existing_type=sqlmodel.sql.sqltypes.AutoString(), nullable=True) + except Exception: pass # ### end Alembic commands ### @@ -37,6 +35,6 @@ def downgrade() -> None: try: with op.batch_alter_table("apikey", schema=None) as batch_op: batch_op.alter_column("name", existing_type=sa.VARCHAR(), nullable=False) - except Exception as e: + except Exception: pass # ### end Alembic commands ### diff --git a/src/backend/langflow/alembic/versions/260dbcc8b680_adds_tables.py b/src/backend/base/langflow/alembic/versions/260dbcc8b680_adds_tables.py similarity index 81% rename from src/backend/langflow/alembic/versions/260dbcc8b680_adds_tables.py rename to src/backend/base/langflow/alembic/versions/260dbcc8b680_adds_tables.py index 0d7eed582..01db957fe 100644 --- a/src/backend/langflow/alembic/versions/260dbcc8b680_adds_tables.py +++ b/src/backend/base/langflow/alembic/versions/260dbcc8b680_adds_tables.py @@ -31,23 +31,16 @@ def upgrade() -> None: # and other related indices if "flowstyle" in existing_tables: op.drop_table("flowstyle") - if "ix_flowstyle_flow_id" in [ - index["name"] for index in inspector.get_indexes("flowstyle") - ]: - op.drop_index( - "ix_flowstyle_flow_id", table_name="flowstyle", if_exists=True - ) + if "ix_flowstyle_flow_id" in [index["name"] for index in inspector.get_indexes("flowstyle")]: + op.drop_index("ix_flowstyle_flow_id", table_name="flowstyle", if_exists=True) existing_indices_flow = [] existing_fks_flow = [] if "flow" in existing_tables: - existing_indices_flow = [ - index["name"] for index in inspector.get_indexes("flow") - ] + existing_indices_flow = [index["name"] for index in inspector.get_indexes("flow")] # Existing foreign keys for the 'flow' table, if it exists existing_fks_flow = [ - fk["referred_table"] + "." + fk["referred_columns"][0] - for fk in inspector.get_foreign_keys("flow") + fk["referred_table"] + "." + fk["referred_columns"][0] for fk in inspector.get_foreign_keys("flow") ] # Now check if the columns user_id exists in the 'flow' table # If it does not exist, we need to create the foreign key @@ -67,9 +60,7 @@ def upgrade() -> None: sa.UniqueConstraint("id", name="uq_user_id"), ) with op.batch_alter_table("user", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_user_username"), ["username"], unique=True - ) + batch_op.create_index(batch_op.f("ix_user_username"), ["username"], unique=True) if "apikey" not in existing_tables: op.create_table( @@ -82,20 +73,14 @@ def upgrade() -> None: sa.Column("id", sqlmodel.sql.sqltypes.GUID(), nullable=False), sa.Column("api_key", sqlmodel.sql.sqltypes.AutoString(), nullable=False), sa.Column("user_id", sqlmodel.sql.sqltypes.GUID(), nullable=False), - sa.ForeignKeyConstraint( - ["user_id"], ["user.id"], name="fk_apikey_user_id_user" - ), + sa.ForeignKeyConstraint(["user_id"], ["user.id"], name="fk_apikey_user_id_user"), sa.PrimaryKeyConstraint("id", name="pk_apikey"), sa.UniqueConstraint("id", name="uq_apikey_id"), ) with op.batch_alter_table("apikey", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_apikey_api_key"), ["api_key"], unique=True - ) + batch_op.create_index(batch_op.f("ix_apikey_api_key"), ["api_key"], unique=True) batch_op.create_index(batch_op.f("ix_apikey_name"), ["name"], unique=False) - batch_op.create_index( - batch_op.f("ix_apikey_user_id"), ["user_id"], unique=False - ) + batch_op.create_index(batch_op.f("ix_apikey_user_id"), ["user_id"], unique=False) if "flow" not in existing_tables: op.create_table( "flow", @@ -104,9 +89,7 @@ def upgrade() -> None: sa.Column("description", sqlmodel.sql.sqltypes.AutoString(), nullable=True), sa.Column("id", sqlmodel.sql.sqltypes.GUID(), nullable=False), sa.Column("user_id", sqlmodel.sql.sqltypes.GUID(), nullable=False), - sa.ForeignKeyConstraint( - ["user_id"], ["user.id"], name="fk_flow_user_id_user" - ), + sa.ForeignKeyConstraint(["user_id"], ["user.id"], name="fk_flow_user_id_user"), sa.PrimaryKeyConstraint("id", name="pk_flow"), sa.UniqueConstraint("id", name="uq_flow_id"), ) @@ -129,16 +112,12 @@ def upgrade() -> None: if "user.id" not in existing_fks_flow: batch_op.create_foreign_key("fk_flow_user_id", "user", ["user_id"], ["id"]) if "ix_flow_description" not in existing_indices_flow: - batch_op.create_index( - batch_op.f("ix_flow_description"), ["description"], unique=False - ) + batch_op.create_index(batch_op.f("ix_flow_description"), ["description"], unique=False) if "ix_flow_name" not in existing_indices_flow: batch_op.create_index(batch_op.f("ix_flow_name"), ["name"], unique=False) with op.batch_alter_table("flow", schema=None) as batch_op: if "ix_flow_user_id" not in existing_indices_flow: - batch_op.create_index( - batch_op.f("ix_flow_user_id"), ["user_id"], unique=False - ) + batch_op.create_index(batch_op.f("ix_flow_user_id"), ["user_id"], unique=False) # ### end Alembic commands ### @@ -169,10 +148,4 @@ def downgrade() -> None: batch_op.drop_index(batch_op.f("ix_user_username"), if_exists=True) op.drop_table("user") - - if "flowstyle" in existing_tables: - op.drop_table("flowstyle") - - if "component" in existing_tables: - op.drop_table("component") # ### end Alembic commands ### diff --git a/src/backend/langflow/alembic/versions/2ac71eb9c3ae_adds_credential_table.py b/src/backend/base/langflow/alembic/versions/2ac71eb9c3ae_adds_credential_table.py similarity index 92% rename from src/backend/langflow/alembic/versions/2ac71eb9c3ae_adds_credential_table.py rename to src/backend/base/langflow/alembic/versions/2ac71eb9c3ae_adds_credential_table.py index ce2d2cd76..2250a8b8c 100644 --- a/src/backend/langflow/alembic/versions/2ac71eb9c3ae_adds_credential_table.py +++ b/src/backend/base/langflow/alembic/versions/2ac71eb9c3ae_adds_credential_table.py @@ -31,9 +31,7 @@ def upgrade() -> None: "credential", sa.Column("name", sqlmodel.sql.sqltypes.AutoString(), nullable=True), sa.Column("value", sqlmodel.sql.sqltypes.AutoString(), nullable=True), - sa.Column( - "provider", sqlmodel.sql.sqltypes.AutoString(), nullable=True - ), + sa.Column("provider", sqlmodel.sql.sqltypes.AutoString(), nullable=True), sa.Column("user_id", sqlmodel.sql.sqltypes.GUID(), nullable=False), sa.Column("id", sqlmodel.sql.sqltypes.GUID(), nullable=False), sa.Column("created_at", sa.DateTime(), nullable=False), diff --git a/src/backend/base/langflow/alembic/versions/63b9c451fd30_add_icon_and_icon_bg_color_to_flow.py b/src/backend/base/langflow/alembic/versions/63b9c451fd30_add_icon_and_icon_bg_color_to_flow.py new file mode 100644 index 000000000..c6d6893e3 --- /dev/null +++ b/src/backend/base/langflow/alembic/versions/63b9c451fd30_add_icon_and_icon_bg_color_to_flow.py @@ -0,0 +1,50 @@ +"""Add icon and icon_bg_color to Flow + +Revision ID: 63b9c451fd30 +Revises: bc2f01c40e4a +Create Date: 2024-03-06 10:53:47.148658 + +""" + +from typing import Sequence, Union + +import sqlalchemy as sa +import sqlmodel +from alembic import op +from sqlalchemy.engine.reflection import Inspector + +# revision identifiers, used by Alembic. +revision: str = "63b9c451fd30" +down_revision: Union[str, None] = "bc2f01c40e4a" +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + conn = op.get_bind() + inspector = Inspector.from_engine(conn) # type: ignore + table_names = inspector.get_table_names() # noqa + column_names = [column["name"] for column in inspector.get_columns("flow")] + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table("flow", schema=None) as batch_op: + if "icon" not in column_names: + batch_op.add_column(sa.Column("icon", sqlmodel.sql.sqltypes.AutoString(), nullable=True)) + if "icon_bg_color" not in column_names: + batch_op.add_column(sa.Column("icon_bg_color", sqlmodel.sql.sqltypes.AutoString(), nullable=True)) + + # ### end Alembic commands ### + + +def downgrade() -> None: + conn = op.get_bind() + inspector = Inspector.from_engine(conn) # type: ignore + table_names = inspector.get_table_names() # noqa + column_names = [column["name"] for column in inspector.get_columns("flow")] + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table("flow", schema=None) as batch_op: + if "icon" in column_names: + batch_op.drop_column("icon") + if "icon_bg_color" in column_names: + batch_op.drop_column("icon_bg_color") + + # ### end Alembic commands ### diff --git a/src/backend/langflow/alembic/versions/67cc006d50bf_add_profile_image_column.py b/src/backend/base/langflow/alembic/versions/67cc006d50bf_add_profile_image_column.py similarity index 100% rename from src/backend/langflow/alembic/versions/67cc006d50bf_add_profile_image_column.py rename to src/backend/base/langflow/alembic/versions/67cc006d50bf_add_profile_image_column.py diff --git a/src/backend/langflow/alembic/versions/7843803a87b5_store_updates.py b/src/backend/base/langflow/alembic/versions/7843803a87b5_store_updates.py similarity index 82% rename from src/backend/langflow/alembic/versions/7843803a87b5_store_updates.py rename to src/backend/base/langflow/alembic/versions/7843803a87b5_store_updates.py index b1565cd0f..d2a576410 100644 --- a/src/backend/langflow/alembic/versions/7843803a87b5_store_updates.py +++ b/src/backend/base/langflow/alembic/versions/7843803a87b5_store_updates.py @@ -29,18 +29,14 @@ def upgrade() -> None: try: if "is_component" not in flow_columns: with op.batch_alter_table("flow", schema=None) as batch_op: - batch_op.add_column( - sa.Column("is_component", sa.Boolean(), nullable=True) - ) - except Exception as e: + batch_op.add_column(sa.Column("is_component", sa.Boolean(), nullable=True)) + except Exception: pass try: if "store_api_key" not in user_columns: with op.batch_alter_table("user", schema=None) as batch_op: - batch_op.add_column( - sa.Column("store_api_key", sqlmodel.AutoString(), nullable=True) - ) - except Exception as e: + batch_op.add_column(sa.Column("store_api_key", sqlmodel.AutoString(), nullable=True)) + except Exception: pass # ### end Alembic commands ### diff --git a/src/backend/langflow/alembic/versions/7d2162acc8b2_adds_updated_at_and_folder_cols.py b/src/backend/base/langflow/alembic/versions/7d2162acc8b2_adds_updated_at_and_folder_cols.py similarity index 80% rename from src/backend/langflow/alembic/versions/7d2162acc8b2_adds_updated_at_and_folder_cols.py rename to src/backend/base/langflow/alembic/versions/7d2162acc8b2_adds_updated_at_and_folder_cols.py index 5ed929568..b46400899 100644 --- a/src/backend/langflow/alembic/versions/7d2162acc8b2_adds_updated_at_and_folder_cols.py +++ b/src/backend/base/langflow/alembic/versions/7d2162acc8b2_adds_updated_at_and_folder_cols.py @@ -30,9 +30,7 @@ def upgrade() -> None: try: if "name" in api_key_columns: with op.batch_alter_table("apikey", schema=None) as batch_op: - batch_op.alter_column( - "name", existing_type=sa.VARCHAR(), nullable=False - ) + batch_op.alter_column("name", existing_type=sa.VARCHAR(), nullable=False) except Exception as e: print(e) @@ -40,15 +38,9 @@ def upgrade() -> None: try: with op.batch_alter_table("flow", schema=None) as batch_op: if "updated_at" not in flow_columns: - batch_op.add_column( - sa.Column("updated_at", sa.DateTime(), nullable=True) - ) + batch_op.add_column(sa.Column("updated_at", sa.DateTime(), nullable=True)) if "folder" not in flow_columns: - batch_op.add_column( - sa.Column( - "folder", sqlmodel.sql.sqltypes.AutoString(), nullable=True - ) - ) + batch_op.add_column(sa.Column("folder", sqlmodel.sql.sqltypes.AutoString(), nullable=True)) except Exception as e: print(e) @@ -68,7 +60,6 @@ def downgrade() -> None: pass try: - with op.batch_alter_table("apikey", schema=None) as batch_op: batch_op.alter_column("name", existing_type=sa.VARCHAR(), nullable=True) except Exception as e: diff --git a/src/backend/langflow/alembic/versions/b2fa308044b5_add_unique_constraints.py b/src/backend/base/langflow/alembic/versions/b2fa308044b5_add_unique_constraints.py similarity index 81% rename from src/backend/langflow/alembic/versions/b2fa308044b5_add_unique_constraints.py rename to src/backend/base/langflow/alembic/versions/b2fa308044b5_add_unique_constraints.py index bb3c0c7cd..ed5317bf5 100644 --- a/src/backend/langflow/alembic/versions/b2fa308044b5_add_unique_constraints.py +++ b/src/backend/base/langflow/alembic/versions/b2fa308044b5_add_unique_constraints.py @@ -32,33 +32,19 @@ def upgrade() -> None: with op.batch_alter_table("flow", schema=None) as batch_op: flow_columns = [column["name"] for column in inspector.get_columns("flow")] if "is_component" not in flow_columns: - batch_op.add_column( - sa.Column("is_component", sa.Boolean(), nullable=True) - ) + batch_op.add_column(sa.Column("is_component", sa.Boolean(), nullable=True)) if "updated_at" not in flow_columns: - batch_op.add_column( - sa.Column("updated_at", sa.DateTime(), nullable=True) - ) + batch_op.add_column(sa.Column("updated_at", sa.DateTime(), nullable=True)) if "folder" not in flow_columns: - batch_op.add_column( - sa.Column( - "folder", sqlmodel.sql.sqltypes.AutoString(), nullable=True - ) - ) + batch_op.add_column(sa.Column("folder", sqlmodel.sql.sqltypes.AutoString(), nullable=True)) if "user_id" not in flow_columns: - batch_op.add_column( - sa.Column("user_id", sqlmodel.sql.sqltypes.GUID(), nullable=True) - ) + batch_op.add_column(sa.Column("user_id", sqlmodel.sql.sqltypes.GUID(), nullable=True)) indices = inspector.get_indexes("flow") indices_names = [index["name"] for index in indices] if "ix_flow_user_id" not in indices_names: - batch_op.create_index( - batch_op.f("ix_flow_user_id"), ["user_id"], unique=False - ) + batch_op.create_index(batch_op.f("ix_flow_user_id"), ["user_id"], unique=False) if "fk_flow_user_id_user" not in indices_names: - batch_op.create_foreign_key( - "fk_flow_user_id_user", "user", ["user_id"], ["id"] - ) + batch_op.create_foreign_key("fk_flow_user_id_user", "user", ["user_id"], ["id"]) except Exception: pass diff --git a/src/backend/langflow/alembic/versions/bc2f01c40e4a_new_fixes.py b/src/backend/base/langflow/alembic/versions/bc2f01c40e4a_new_fixes.py similarity index 82% rename from src/backend/langflow/alembic/versions/bc2f01c40e4a_new_fixes.py rename to src/backend/base/langflow/alembic/versions/bc2f01c40e4a_new_fixes.py index cfbf74f06..e0fa1add8 100644 --- a/src/backend/langflow/alembic/versions/bc2f01c40e4a_new_fixes.py +++ b/src/backend/base/langflow/alembic/versions/bc2f01c40e4a_new_fixes.py @@ -33,21 +33,13 @@ def upgrade() -> None: if "updated_at" not in flow_columns: batch_op.add_column(sa.Column("updated_at", sa.DateTime(), nullable=True)) if "folder" not in flow_columns: - batch_op.add_column( - sa.Column("folder", sqlmodel.sql.sqltypes.AutoString(), nullable=True) - ) + batch_op.add_column(sa.Column("folder", sqlmodel.sql.sqltypes.AutoString(), nullable=True)) if "user_id" not in flow_columns: - batch_op.add_column( - sa.Column("user_id", sqlmodel.sql.sqltypes.GUID(), nullable=True) - ) + batch_op.add_column(sa.Column("user_id", sqlmodel.sql.sqltypes.GUID(), nullable=True)) if "ix_flow_user_id" not in flow_indexes: - batch_op.create_index( - batch_op.f("ix_flow_user_id"), ["user_id"], unique=False - ) + batch_op.create_index(batch_op.f("ix_flow_user_id"), ["user_id"], unique=False) if "flow_user_id_fkey" not in flow_fks: - batch_op.create_foreign_key( - "flow_user_id_fkey", "user", ["user_id"], ["id"] - ) + batch_op.create_foreign_key("flow_user_id_fkey", "user", ["user_id"], ["id"]) def downgrade() -> None: diff --git a/src/backend/langflow/alembic/versions/eb5866d51fd2_change_columns_to_be_nullable.py b/src/backend/base/langflow/alembic/versions/eb5866d51fd2_change_columns_to_be_nullable.py similarity index 94% rename from src/backend/langflow/alembic/versions/eb5866d51fd2_change_columns_to_be_nullable.py rename to src/backend/base/langflow/alembic/versions/eb5866d51fd2_change_columns_to_be_nullable.py index 4da04c325..acb09cd5f 100644 --- a/src/backend/langflow/alembic/versions/eb5866d51fd2_change_columns_to_be_nullable.py +++ b/src/backend/base/langflow/alembic/versions/eb5866d51fd2_change_columns_to_be_nullable.py @@ -19,7 +19,7 @@ depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: # ### commands auto generated by Alembic - please adjust! ### - connection = op.get_bind() + connection = op.get_bind() # noqa pass # ### end Alembic commands ### diff --git a/src/backend/langflow/alembic/versions/f5ee9749d1a6_user_id_can_be_null_in_flow.py b/src/backend/base/langflow/alembic/versions/f5ee9749d1a6_user_id_can_be_null_in_flow.py similarity index 79% rename from src/backend/langflow/alembic/versions/f5ee9749d1a6_user_id_can_be_null_in_flow.py rename to src/backend/base/langflow/alembic/versions/f5ee9749d1a6_user_id_can_be_null_in_flow.py index 494de22ac..842c55857 100644 --- a/src/backend/langflow/alembic/versions/f5ee9749d1a6_user_id_can_be_null_in_flow.py +++ b/src/backend/base/langflow/alembic/versions/f5ee9749d1a6_user_id_can_be_null_in_flow.py @@ -22,9 +22,7 @@ def upgrade() -> None: # ### commands auto generated by Alembic - please adjust! ### try: with op.batch_alter_table("flow", schema=None) as batch_op: - batch_op.alter_column( - "user_id", existing_type=sa.CHAR(length=32), nullable=True - ) + batch_op.alter_column("user_id", existing_type=sa.CHAR(length=32), nullable=True) except Exception as e: print(e) pass @@ -36,9 +34,7 @@ def downgrade() -> None: # ### commands auto generated by Alembic - please adjust! ### try: with op.batch_alter_table("flow", schema=None) as batch_op: - batch_op.alter_column( - "user_id", existing_type=sa.CHAR(length=32), nullable=False - ) + batch_op.alter_column("user_id", existing_type=sa.CHAR(length=32), nullable=False) except Exception as e: print(e) pass diff --git a/src/backend/langflow/alembic/versions/fd531f8868b1_fix_credential_table.py b/src/backend/base/langflow/alembic/versions/fd531f8868b1_fix_credential_table.py similarity index 93% rename from src/backend/langflow/alembic/versions/fd531f8868b1_fix_credential_table.py rename to src/backend/base/langflow/alembic/versions/fd531f8868b1_fix_credential_table.py index 77e6acd75..de69b491d 100644 --- a/src/backend/langflow/alembic/versions/fd531f8868b1_fix_credential_table.py +++ b/src/backend/base/langflow/alembic/versions/fd531f8868b1_fix_credential_table.py @@ -31,9 +31,7 @@ def upgrade() -> None: try: if "credential" in tables and "fk_credential_user_id" not in foreign_keys_names: with op.batch_alter_table("credential", schema=None) as batch_op: - batch_op.create_foreign_key( - "fk_credential_user_id", "user", ["user_id"], ["id"] - ) + batch_op.create_foreign_key("fk_credential_user_id", "user", ["user_id"], ["id"]) except Exception as e: print(e) pass diff --git a/src/backend/langflow/api/__init__.py b/src/backend/base/langflow/api/__init__.py similarity index 100% rename from src/backend/langflow/api/__init__.py rename to src/backend/base/langflow/api/__init__.py diff --git a/src/backend/langflow/api/router.py b/src/backend/base/langflow/api/router.py similarity index 76% rename from src/backend/langflow/api/router.py rename to src/backend/base/langflow/api/router.py index 24d64b401..569014acf 100644 --- a/src/backend/langflow/api/router.py +++ b/src/backend/base/langflow/api/router.py @@ -4,13 +4,15 @@ from fastapi import APIRouter from langflow.api.v1 import ( api_key_router, chat_router, - credentials_router, endpoints_router, + files_router, flows_router, login_router, + monitor_router, store_router, users_router, validate_router, + variables_router, ) router = APIRouter( @@ -24,4 +26,6 @@ router.include_router(flows_router) router.include_router(users_router) router.include_router(api_key_router) router.include_router(login_router) -router.include_router(credentials_router) +router.include_router(variables_router) +router.include_router(files_router) +router.include_router(monitor_router) diff --git a/src/backend/langflow/api/utils.py b/src/backend/base/langflow/api/utils.py similarity index 55% rename from src/backend/langflow/api/utils.py rename to src/backend/base/langflow/api/utils.py index 141c79229..0500917a3 100644 --- a/src/backend/langflow/api/utils.py +++ b/src/backend/base/langflow/api/utils.py @@ -1,14 +1,19 @@ import warnings from pathlib import Path -from typing import TYPE_CHECKING, List +from typing import TYPE_CHECKING, Optional from fastapi import HTTPException from platformdirs import user_cache_dir +from sqlmodel import Session +from langflow.graph.graph.base import Graph +from langflow.services.chat.service import ChatService +from langflow.services.database.models.flow import Flow from langflow.services.store.schema import StoreComponentCreate from langflow.services.store.utils import get_lf_version_from_pypi if TYPE_CHECKING: + from langflow.graph.vertex.base import Vertex from langflow.services.database.models.flow.model import Flow @@ -120,6 +125,9 @@ def update_template_field(frontend_template, key, value_dict): template_field["value"] = "" template_field["file_path"] = file_path_value + if "load_from_db" in value_dict and value_dict["load_from_db"]: + template_field["load_from_db"] = value_dict["load_from_db"] + def get_file_path_value(file_path): """Get the file path value if the file exists, else return empty string.""" @@ -137,7 +145,7 @@ def get_file_path_value(file_path): return file_path -def validate_is_component(flows: List["Flow"]): +def validate_is_component(flows: list["Flow"]): for flow in flows: if not flow.data or flow.is_component is not None: continue @@ -156,7 +164,7 @@ def get_is_component_from_data(data: dict): async def check_langflow_version(component: StoreComponentCreate): - from langflow import __version__ as current_version + from langflow.version.version import __version__ as current_version # type: ignore if not component.last_tested_version: component.last_tested_version = current_version @@ -171,19 +179,132 @@ async def check_langflow_version(component: StoreComponentCreate): ) -def format_elapsed_time(elapsed_time) -> str: - # Format elapsed time to human readable format coming from - # perf_counter() - # If the elapsed time is less than 1 second, return ms - # If the elapsed time is less than 1 minute, return seconds rounded to 2 decimals - time_str = "" +def format_elapsed_time(elapsed_time: float) -> str: + """Format elapsed time to a human-readable format coming from perf_counter(). + + - Less than 1 second: returns milliseconds + - Less than 1 minute: returns seconds rounded to 2 decimals + - 1 minute or more: returns minutes and seconds + """ if elapsed_time < 1: - elapsed_time = int(round(elapsed_time * 1000)) - time_str = f"{elapsed_time} ms" + milliseconds = int(round(elapsed_time * 1000)) + return f"{milliseconds} ms" elif elapsed_time < 60: - elapsed_time = round(elapsed_time, 2) - time_str = f"{elapsed_time} seconds" + seconds = round(elapsed_time, 2) + unit = "second" if seconds == 1 else "seconds" + return f"{seconds} {unit}" else: - elapsed_time = round(elapsed_time / 60, 2) - time_str = f"{elapsed_time} minutes" - return time_str + minutes = int(elapsed_time // 60) + seconds = round(elapsed_time % 60, 2) + minutes_unit = "minute" if minutes == 1 else "minutes" + seconds_unit = "second" if seconds == 1 else "seconds" + return f"{minutes} {minutes_unit}, {seconds} {seconds_unit}" + + +async def build_and_cache_graph( + flow_id: str, + session: Session, + chat_service: "ChatService", + graph: Optional[Graph] = None, +): + """Build and cache the graph.""" + flow: Optional[Flow] = session.get(Flow, flow_id) + if not flow or not flow.data: + raise ValueError("Invalid flow ID") + other_graph = Graph.from_payload(flow.data, flow_id) + if graph is None: + graph = other_graph + else: + graph = graph.update(other_graph) + await chat_service.set_cache(flow_id, graph) + return graph + + +def format_syntax_error_message(exc: SyntaxError) -> str: + """Format a SyntaxError message for returning to the frontend.""" + if exc.text is None: + return f"Syntax error in code. Error on line {exc.lineno}" + return f"Syntax error in code. Error on line {exc.lineno}: {exc.text.strip()}" + + +def get_causing_exception(exc: BaseException) -> BaseException: + """Get the causing exception from an exception.""" + if hasattr(exc, "__cause__") and exc.__cause__: + return get_causing_exception(exc.__cause__) + return exc + + +def format_exception_message(exc: Exception) -> str: + """Format an exception message for returning to the frontend.""" + # We need to check if the __cause__ is a SyntaxError + # If it is, we need to return the message of the SyntaxError + causing_exception = get_causing_exception(exc) + if isinstance(causing_exception, SyntaxError): + return format_syntax_error_message(causing_exception) + return str(exc) + + +async def get_next_runnable_vertices( + graph: Graph, + vertex: "Vertex", + vertex_id: str, + chat_service: ChatService, + flow_id: str, +): + """ + Retrieves the next runnable vertices in the graph for a given vertex. + + Args: + graph (Graph): The graph object representing the flow. + vertex (Vertex): The current vertex. + vertex_id (str): The ID of the current vertex. + chat_service (ChatService): The chat service object. + flow_id (str): The ID of the flow. + + Returns: + list: A list of IDs of the next runnable vertices. + + """ + async with chat_service._cache_locks[flow_id] as lock: + graph.remove_from_predecessors(vertex_id) + direct_successors_ready = [v for v in vertex.successors_ids if graph.is_vertex_runnable(v)] + if not direct_successors_ready: + # No direct successors ready, look for runnable predecessors of successors + next_runnable_vertices = graph.find_runnable_predecessors_for_successors(vertex_id) + else: + next_runnable_vertices = direct_successors_ready + + for v_id in set(next_runnable_vertices): # Use set to avoid duplicates + graph.vertices_to_run.remove(v_id) + graph.remove_from_predecessors(v_id) + await chat_service.set_cache(flow_id=flow_id, data=graph, lock=lock) + return next_runnable_vertices + + +def get_top_level_vertices(graph, vertices_ids): + """ + Retrieves the top-level vertices from the given graph based on the provided vertex IDs. + + Args: + graph (Graph): The graph object containing the vertices. + vertices_ids (list): A list of vertex IDs. + + Returns: + list: A list of top-level vertex IDs. + + """ + top_level_vertices = [] + for vertex_id in vertices_ids: + vertex = graph.get_vertex(vertex_id) + if vertex.parent_is_top_level: + top_level_vertices.append(vertex.parent_node_id) + else: + top_level_vertices.append(vertex_id) + return top_level_vertices + + +def parse_exception(exc): + """Parse the exception message.""" + if hasattr(exc, "body"): + return exc.body["message"] + return str(exc) diff --git a/src/backend/langflow/api/v1/__init__.py b/src/backend/base/langflow/api/v1/__init__.py similarity index 72% rename from src/backend/langflow/api/v1/__init__.py rename to src/backend/base/langflow/api/v1/__init__.py index 6368a0cc8..0342c76c8 100644 --- a/src/backend/langflow/api/v1/__init__.py +++ b/src/backend/base/langflow/api/v1/__init__.py @@ -1,12 +1,14 @@ from langflow.api.v1.api_key import router as api_key_router from langflow.api.v1.chat import router as chat_router -from langflow.api.v1.credential import router as credentials_router from langflow.api.v1.endpoints import router as endpoints_router +from langflow.api.v1.files import router as files_router from langflow.api.v1.flows import router as flows_router from langflow.api.v1.login import router as login_router +from langflow.api.v1.monitor import router as monitor_router from langflow.api.v1.store import router as store_router from langflow.api.v1.users import router as users_router from langflow.api.v1.validate import router as validate_router +from langflow.api.v1.variable import router as variables_router __all__ = [ "chat_router", @@ -17,5 +19,7 @@ __all__ = [ "users_router", "api_key_router", "login_router", - "credentials_router", + "variables_router", + "monitor_router", + "files_router", ] diff --git a/src/backend/langflow/api/v1/api_key.py b/src/backend/base/langflow/api/v1/api_key.py similarity index 89% rename from src/backend/langflow/api/v1/api_key.py rename to src/backend/base/langflow/api/v1/api_key.py index 48cf7d1ca..77466960d 100644 --- a/src/backend/langflow/api/v1/api_key.py +++ b/src/backend/base/langflow/api/v1/api_key.py @@ -8,20 +8,10 @@ from langflow.api.v1.schemas import ApiKeyCreateRequest, ApiKeysResponse from langflow.services.auth import utils as auth_utils # Assuming you have these methods in your service layer -from langflow.services.database.models.api_key.crud import ( - create_api_key, - delete_api_key, - get_api_keys, -) -from langflow.services.database.models.api_key.model import ( - ApiKeyCreate, - UnmaskedApiKeyRead, -) +from langflow.services.database.models.api_key.crud import create_api_key, delete_api_key, get_api_keys +from langflow.services.database.models.api_key.model import ApiKeyCreate, UnmaskedApiKeyRead from langflow.services.database.models.user.model import User -from langflow.services.deps import ( - get_session, - get_settings_service, -) +from langflow.services.deps import get_session, get_settings_service if TYPE_CHECKING: pass diff --git a/src/backend/base/langflow/api/v1/base.py b/src/backend/base/langflow/api/v1/base.py new file mode 100644 index 000000000..b040d51c4 --- /dev/null +++ b/src/backend/base/langflow/api/v1/base.py @@ -0,0 +1,165 @@ +from typing import Optional + +from pydantic import BaseModel, field_validator, model_serializer + +from langflow.template.frontend_node.base import FrontendNode + + +class CacheResponse(BaseModel): + data: dict + + +class Code(BaseModel): + code: str + + +class FrontendNodeRequest(FrontendNode): + template: dict # type: ignore + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + # Override the default serialization method in FrontendNode + # because we don't need the name in the response (i.e. {name: {}}) + return handler(self) + + +class ValidatePromptRequest(BaseModel): + name: str + template: str + custom_fields: Optional[dict] = None + frontend_node: Optional[FrontendNodeRequest] = None + + +# Build ValidationResponse class for {"imports": {"errors": []}, "function": {"errors": []}} +class CodeValidationResponse(BaseModel): + imports: dict + function: dict + + @field_validator("imports") + @classmethod + def validate_imports(cls, v): + return v or {"errors": []} + + @field_validator("function") + @classmethod + def validate_function(cls, v): + return v or {"errors": []} + + +class PromptValidationResponse(BaseModel): + input_variables: list + # object return for tweak call + frontend_node: Optional[FrontendNodeRequest] = None + + +INVALID_CHARACTERS = { + " ", + ",", + ".", + ":", + ";", + "!", + "?", + "/", + "\\", + "(", + ")", + "[", + "]", +} + +INVALID_NAMES = { + "input_variables", + "output_parser", + "partial_variables", + "template", + "template_format", + "validate_template", +} + + +def is_json_like(var): + if var.startswith("{{") and var.endswith("}}"): + # If it is a double brance variable + # we don't want to validate any of its content + return True + # the above doesn't work on all cases because the json string can be multiline + # or indented which can add \n or spaces at the start or end of the string + # test_case_3 new_var == '\n{{\n "test": "hello",\n "text": "world"\n}}\n' + # what we can do is to remove the \n and spaces from the start and end of the string + # and then check if the string starts with {{ and ends with }} + var = var.strip() + var = var.replace("\n", "") + var = var.replace(" ", "") + # Now it should be a valid json string + return var.startswith("{{") and var.endswith("}}") + + +def fix_variable(var, invalid_chars, wrong_variables): + if not var: + return var, invalid_chars, wrong_variables + new_var = var + + # Handle variables starting with a number + if var[0].isdigit(): + invalid_chars.append(var[0]) + new_var, invalid_chars, wrong_variables = fix_variable(var[1:], invalid_chars, wrong_variables) + + # Temporarily replace {{ and }} to avoid treating them as invalid + new_var = new_var.replace("{{", "ᴛᴇᴍᴘᴏᴘᴇɴ").replace("}}", "ᴛᴇᴍᴘᴄʟᴏsᴇ") + + # Remove invalid characters + for char in new_var: + if char in INVALID_CHARACTERS: + invalid_chars.append(char) + new_var = new_var.replace(char, "") + if var not in wrong_variables: # Avoid duplicating entries + wrong_variables.append(var) + + # Restore {{ and }} + new_var = new_var.replace("ᴛᴇᴍᴘᴏᴘᴇɴ", "{{").replace("ᴛᴇᴍᴘᴄʟᴏsᴇ", "}}") + + return new_var, invalid_chars, wrong_variables + + +def check_variable(var, invalid_chars, wrong_variables, empty_variables): + if any(char in invalid_chars for char in var): + wrong_variables.append(var) + elif var == "": + empty_variables.append(var) + return wrong_variables, empty_variables + + +def check_for_errors(input_variables, fixed_variables, wrong_variables, empty_variables): + if any(var for var in input_variables if var not in fixed_variables): + error_message = ( + f"Error: Input variables contain invalid characters or formats. \n" + f"Invalid variables: {', '.join(wrong_variables)}.\n" + f"Empty variables: {', '.join(empty_variables)}. \n" + f"Fixed variables: {', '.join(fixed_variables)}." + ) + raise ValueError(error_message) + + +def check_input_variables(input_variables): + invalid_chars = [] + fixed_variables = [] + wrong_variables = [] + empty_variables = [] + variables_to_check = [] + + for var in input_variables: + # First, let's check if the variable is a JSON string + # because if it is, it won't be considered a variable + # and we don't need to validate it + if is_json_like(var): + continue + + new_var, wrong_variables, empty_variables = fix_variable(var, invalid_chars, wrong_variables) + wrong_variables, empty_variables = check_variable(var, INVALID_CHARACTERS, wrong_variables, empty_variables) + fixed_variables.append(new_var) + variables_to_check.append(var) + + check_for_errors(variables_to_check, fixed_variables, wrong_variables, empty_variables) + + return fixed_variables diff --git a/src/backend/langflow/api/v1/callback.py b/src/backend/base/langflow/api/v1/callback.py similarity index 69% rename from src/backend/langflow/api/v1/callback.py rename to src/backend/base/langflow/api/v1/callback.py index f9be5d56c..b326311ac 100644 --- a/src/backend/langflow/api/v1/callback.py +++ b/src/backend/base/langflow/api/v1/callback.py @@ -1,17 +1,20 @@ -import asyncio -from typing import Any, Dict, List, Optional +from typing import TYPE_CHECKING, Any, Dict, List, Optional from uuid import UUID from langchain.schema import AgentAction, AgentFinish -from langchain_core.callbacks.base import AsyncCallbackHandler, BaseCallbackHandler -from langflow.api.v1.schemas import ChatResponse, PromptResponse -from langflow.services.deps import get_chat_service -from langflow.utils.util import remove_ansi_escape_codes +from langchain_core.callbacks.base import AsyncCallbackHandler from loguru import logger +from langflow.api.v1.schemas import ChatResponse, PromptResponse +from langflow.services.deps import get_chat_service, get_socket_service +from langflow.utils.util import remove_ansi_escape_codes + +if TYPE_CHECKING: + from langflow.services.socket.service import SocketIOService + # https://github.com/hwchase17/chat-langchain/blob/master/callback.py -class AsyncStreamingLLMCallbackHandler(AsyncCallbackHandler): +class AsyncStreamingLLMCallbackHandleSIO(AsyncCallbackHandler): """Callback handler for streaming LLM responses.""" @property @@ -19,14 +22,16 @@ class AsyncStreamingLLMCallbackHandler(AsyncCallbackHandler): """Whether to ignore chain callbacks.""" return False - def __init__(self, client_id: str): + def __init__(self, session_id: str): self.chat_service = get_chat_service() - self.client_id = client_id - self.websocket = self.chat_service.active_connections[self.client_id] + self.client_id = session_id + self.socketio_service: "SocketIOService" = get_socket_service() + self.sid = session_id + # self.socketio_service = self.chat_service.active_connections[self.client_id] async def on_llm_new_token(self, token: str, **kwargs: Any) -> None: resp = ChatResponse(message=token, type="stream", intermediate_steps="") - await self.websocket.send_json(resp.model_dump()) + await self.socketio_service.emit_token(to=self.sid, data=resp.model_dump()) async def on_tool_start(self, serialized: Dict[str, Any], input_str: str, **kwargs: Any) -> Any: """Run when tool starts running.""" @@ -35,7 +40,7 @@ class AsyncStreamingLLMCallbackHandler(AsyncCallbackHandler): type="stream", intermediate_steps=f"Tool input: {input_str}", ) - await self.websocket.send_json(resp.model_dump()) + await self.socketio_service.emit_token(to=self.sid, data=resp.model_dump()) async def on_tool_end(self, output: str, **kwargs: Any) -> Any: """Run when tool ends running.""" @@ -66,7 +71,7 @@ class AsyncStreamingLLMCallbackHandler(AsyncCallbackHandler): try: # This is to emulate the stream of tokens for resp in resps: - await self.websocket.send_json(resp.model_dump()) + await self.socketio_service.emit_token(to=self.sid, data=resp.model_dump()) except Exception as exc: logger.error(f"Error sending response: {exc}") @@ -92,8 +97,7 @@ class AsyncStreamingLLMCallbackHandler(AsyncCallbackHandler): resp = PromptResponse( prompt=text, ) - await self.websocket.send_json(resp.model_dump()) - self.chat_service.chat_history.add_message(self.client_id, resp) + await self.socketio_service.emit_message(to=self.sid, data=resp.model_dump()) async def on_agent_action(self, action: AgentAction, **kwargs: Any): log = f"Thought: {action.log}" @@ -103,10 +107,10 @@ class AsyncStreamingLLMCallbackHandler(AsyncCallbackHandler): logs = log.split("\n") for log in logs: resp = ChatResponse(message="", type="stream", intermediate_steps=log) - await self.websocket.send_json(resp.model_dump()) + await self.socketio_service.emit_token(to=self.sid, data=resp.model_dump()) else: resp = ChatResponse(message="", type="stream", intermediate_steps=log) - await self.websocket.send_json(resp.model_dump()) + await self.socketio_service.emit_token(to=self.sid, data=resp.model_dump()) async def on_agent_finish(self, finish: AgentFinish, **kwargs: Any) -> Any: """Run on agent end.""" @@ -115,20 +119,4 @@ class AsyncStreamingLLMCallbackHandler(AsyncCallbackHandler): type="stream", intermediate_steps=finish.log, ) - await self.websocket.send_json(resp.model_dump()) - - -class StreamingLLMCallbackHandler(BaseCallbackHandler): - """Callback handler for streaming LLM responses.""" - - def __init__(self, client_id: str): - self.chat_service = get_chat_service() - self.client_id = client_id - self.websocket = self.chat_service.active_connections[self.client_id] - - def on_llm_new_token(self, token: str, **kwargs: Any) -> None: - resp = ChatResponse(message=token, type="stream", intermediate_steps="") - - loop = asyncio.get_event_loop() - coroutine = self.websocket.send_json(resp.model_dump()) - asyncio.run_coroutine_threadsafe(coroutine, loop) + await self.socketio_service.emit_token(to=self.sid, data=resp.model_dump()) diff --git a/src/backend/base/langflow/api/v1/chat.py b/src/backend/base/langflow/api/v1/chat.py new file mode 100644 index 000000000..9ee4edb03 --- /dev/null +++ b/src/backend/base/langflow/api/v1/chat.py @@ -0,0 +1,329 @@ +import time +import uuid +from functools import partial +from typing import TYPE_CHECKING, Annotated, Optional + +from fastapi import APIRouter, BackgroundTasks, Body, Depends, HTTPException +from fastapi.responses import StreamingResponse +from loguru import logger + +from langflow.api.utils import ( + build_and_cache_graph, + format_elapsed_time, + format_exception_message, + get_top_level_vertices, + parse_exception, +) +from langflow.api.v1.schemas import ( + InputValueRequest, + ResultDataResponse, + StreamData, + VertexBuildResponse, + VerticesOrderResponse, +) +from langflow.services.auth.utils import get_current_active_user +from langflow.services.chat.service import ChatService +from langflow.services.deps import get_chat_service, get_session, get_session_service +from langflow.services.monitor.utils import log_vertex_build + +if TYPE_CHECKING: + from langflow.graph.vertex.types import ChatVertex + from langflow.services.session.service import SessionService + +router = APIRouter(tags=["Chat"]) + + +async def try_running_celery_task(vertex, user_id): + # Try running the task in celery + # and set the task_id to the local vertex + # if it fails, run the task locally + try: + from langflow.worker import build_vertex + + task = build_vertex.delay(vertex) + vertex.task_id = task.id + except Exception as exc: + logger.debug(f"Error running task in celery: {exc}") + vertex.task_id = None + await vertex.build(user_id=user_id) + return vertex + + +@router.get("/build/{flow_id}/vertices", response_model=VerticesOrderResponse) +async def get_vertices( + flow_id: str, + stop_component_id: Optional[str] = None, + start_component_id: Optional[str] = None, + chat_service: "ChatService" = Depends(get_chat_service), + session=Depends(get_session), +): + """ + Retrieve the vertices order for a given flow. + + Args: + flow_id (str): The ID of the flow. + stop_component_id (str, optional): The ID of the stop component. Defaults to None. + start_component_id (str, optional): The ID of the start component. Defaults to None. + chat_service (ChatService, optional): The chat service dependency. Defaults to Depends(get_chat_service). + session (Session, optional): The session dependency. Defaults to Depends(get_session). + + Returns: + VerticesOrderResponse: The response containing the ordered vertex IDs and the run ID. + + Raises: + HTTPException: If there is an error checking the build status. + """ + try: + # First, we need to check if the flow_id is in the cache + graph = None + if cache := await chat_service.get_cache(flow_id): + graph = cache.get("result") + graph = await build_and_cache_graph(flow_id, session, chat_service, graph) + if stop_component_id or start_component_id: + try: + first_layer = graph.sort_vertices(stop_component_id, start_component_id) + except Exception as exc: + logger.error(exc) + first_layer = graph.sort_vertices() + else: + first_layer = graph.sort_vertices() + # When we send vertices to the frontend + # we need to remove them from the predecessors + # so they are not considered for building again + # which duplicates the results + for vertex_id in first_layer: + graph.remove_from_predecessors(vertex_id) + + # Now vertices is a list of lists + # We need to get the id of each vertex + # and return the same structure but only with the ids + run_id = uuid.uuid4() + graph.set_run_id(run_id) + vertices_to_run = list(graph.vertices_to_run) + get_top_level_vertices(graph, graph.vertices_to_run) + return VerticesOrderResponse(ids=first_layer, run_id=run_id, vertices_to_run=vertices_to_run) + + except Exception as exc: + logger.error(f"Error checking build status: {exc}") + logger.exception(exc) + raise HTTPException(status_code=500, detail=str(exc)) from exc + + +@router.post("/build/{flow_id}/vertices/{vertex_id}") +async def build_vertex( + flow_id: str, + vertex_id: str, + background_tasks: BackgroundTasks, + inputs: Annotated[Optional[InputValueRequest], Body(embed=True)] = None, + chat_service: "ChatService" = Depends(get_chat_service), + current_user=Depends(get_current_active_user), +): + """Build a vertex instead of the entire graph. + + Args: + flow_id (str): The ID of the flow. + vertex_id (str): The ID of the vertex to build. + background_tasks (BackgroundTasks): The background tasks object for logging. + inputs (Optional[InputValueRequest], optional): The input values for the vertex. Defaults to None. + chat_service (ChatService, optional): The chat service dependency. Defaults to Depends(get_chat_service). + current_user (Any, optional): The current user dependency. Defaults to Depends(get_current_active_user). + + Returns: + VertexBuildResponse: The response containing the built vertex information. + + Raises: + HTTPException: If there is an error building the vertex. + + """ + + start_time = time.perf_counter() + next_runnable_vertices = [] + top_level_vertices = [] + try: + start_time = time.perf_counter() + cache = await chat_service.get_cache(flow_id) + if not cache: + # If there's no cache + logger.warning(f"No cache found for {flow_id}. Building graph starting at {vertex_id}") + graph = await build_and_cache_graph(flow_id=flow_id, session=next(get_session()), chat_service=chat_service) + else: + graph = cache.get("result") + result_data_response = ResultDataResponse(results={}) + duration = "" + vertex = graph.get_vertex(vertex_id) + try: + lock = chat_service._cache_locks[flow_id] + set_cache_coro = partial(chat_service.set_cache, flow_id=flow_id) + ( + next_runnable_vertices, + top_level_vertices, + result_dict, + params, + valid, + artifacts, + vertex, + ) = await graph.build_vertex( + lock=lock, + set_cache_coro=set_cache_coro, + vertex_id=vertex_id, + user_id=current_user.id, + inputs_dict=inputs.model_dump() if inputs else {}, + ) + result_data_response = ResultDataResponse(**result_dict.model_dump()) + + except Exception as exc: + logger.exception(f"Error building vertex: {exc}") + params = format_exception_message(exc) + valid = False + result_data_response = ResultDataResponse(results={}) + artifacts = {} + # If there's an error building the vertex + # we need to clear the cache + await chat_service.clear_cache(flow_id) + + # Log the vertex build + if not vertex.will_stream: + background_tasks.add_task( + log_vertex_build, + flow_id=flow_id, + vertex_id=vertex_id, + valid=valid, + params=params, + data=result_data_response, + artifacts=artifacts, + ) + + timedelta = time.perf_counter() - start_time + duration = format_elapsed_time(timedelta) + result_data_response.duration = duration + result_data_response.timedelta = timedelta + vertex.add_build_time(timedelta) + inactivated_vertices = None + inactivated_vertices = list(graph.inactivated_vertices) + graph.reset_inactivated_vertices() + graph.reset_activated_vertices() + await chat_service.set_cache(flow_id, graph) + + # graph.stop_vertex tells us if the user asked + # to stop the build of the graph at a certain vertex + # if it is in next_vertices_ids, we need to remove other + # vertices from next_vertices_ids + if graph.stop_vertex and graph.stop_vertex in next_runnable_vertices: + next_runnable_vertices = [graph.stop_vertex] + + build_response = VertexBuildResponse( + inactivated_vertices=inactivated_vertices, + next_vertices_ids=next_runnable_vertices, + top_level_vertices=top_level_vertices, + valid=valid, + params=params, + id=vertex.id, + data=result_data_response, + ) + return build_response + except Exception as exc: + logger.error(f"Error building vertex: {exc}") + logger.exception(exc) + message = parse_exception(exc) + raise HTTPException(status_code=500, detail=message) from exc + + +@router.get("/build/{flow_id}/{vertex_id}/stream", response_class=StreamingResponse) +async def build_vertex_stream( + flow_id: str, + vertex_id: str, + session_id: Optional[str] = None, + chat_service: "ChatService" = Depends(get_chat_service), + session_service: "SessionService" = Depends(get_session_service), +): + """Build a vertex instead of the entire graph. + + This function is responsible for building a single vertex instead of the entire graph. + It takes the `flow_id` and `vertex_id` as required parameters, and an optional `session_id`. + It also depends on the `ChatService` and `SessionService` services. + + If `session_id` is not provided, it retrieves the graph from the cache using the `chat_service`. + If `session_id` is provided, it loads the session data using the `session_service`. + + Once the graph is obtained, it retrieves the specified vertex using the `vertex_id`. + If the vertex does not support streaming, an error is raised. + If the vertex has a built result, it sends the result as a chunk. + If the vertex is not frozen or not built, it streams the vertex data. + If the vertex has a result, it sends the result as a chunk. + If none of the above conditions are met, an error is raised. + + If any exception occurs during the process, an error message is sent. + Finally, the stream is closed. + + Returns: + A `StreamingResponse` object with the streamed vertex data in text/event-stream format. + + Raises: + HTTPException: If an error occurs while building the vertex. + """ + try: + + async def stream_vertex(): + try: + if not session_id: + cache = await chat_service.get_cache(flow_id) + if not cache: + # If there's no cache + raise ValueError(f"No cache found for {flow_id}.") + else: + graph = cache.get("result") + else: + session_data = await session_service.load_session(session_id, flow_id=flow_id) + graph, artifacts = session_data if session_data else (None, None) + if not graph: + raise ValueError(f"No graph found for {flow_id}.") + + vertex: "ChatVertex" = graph.get_vertex(vertex_id) + if not hasattr(vertex, "stream"): + raise ValueError(f"Vertex {vertex_id} does not support streaming") + if isinstance(vertex._built_result, str) and vertex._built_result: + stream_data = StreamData( + event="message", + data={"message": f"Streaming vertex {vertex_id}"}, + ) + yield str(stream_data) + stream_data = StreamData( + event="message", + data={"chunk": vertex._built_result}, + ) + yield str(stream_data) + + elif not vertex.frozen or not vertex._built: + logger.debug(f"Streaming vertex {vertex_id}") + stream_data = StreamData( + event="message", + data={"message": f"Streaming vertex {vertex_id}"}, + ) + yield str(stream_data) + async for chunk in vertex.stream(): + stream_data = StreamData( + event="message", + data={"chunk": chunk}, + ) + yield str(stream_data) + elif vertex.result is not None: + stream_data = StreamData( + event="message", + data={"chunk": vertex._built_result}, + ) + yield str(stream_data) + else: + raise ValueError(f"No result found for vertex {vertex_id}") + + except Exception as exc: + logger.exception(f"Error building vertex: {exc}") + exc_message = parse_exception(exc) + if exc_message == "The message must be an iterator or an async iterator.": + exc_message = "This stream has already been closed." + yield str(StreamData(event="error", data={"error": exc_message})) + finally: + logger.debug("Closing stream") + yield str(StreamData(event="close", data={"message": "Stream closed"})) + + return StreamingResponse(stream_vertex(), media_type="text/event-stream") + except Exception as exc: + raise HTTPException(status_code=500, detail="Error building vertex") from exc diff --git a/src/backend/base/langflow/api/v1/endpoints.py b/src/backend/base/langflow/api/v1/endpoints.py new file mode 100644 index 000000000..4b032f6cb --- /dev/null +++ b/src/backend/base/langflow/api/v1/endpoints.py @@ -0,0 +1,455 @@ +from http import HTTPStatus +from typing import Annotated, List, Optional, Union + +import sqlalchemy as sa +from fastapi import APIRouter, Body, Depends, HTTPException, UploadFile, status +from loguru import logger +from sqlmodel import Session, select + +from langflow.api.utils import update_frontend_node_with_template_values +from langflow.api.v1.schemas import ( + CustomComponentRequest, + InputValueRequest, + ProcessResponse, + RunResponse, + SimplifiedAPIRequest, + TaskStatusResponse, + Tweaks, + UpdateCustomComponentRequest, + UploadFileResponse, +) +from langflow.graph.graph.base import Graph +from langflow.graph.schema import RunOutputs +from langflow.interface.custom.custom_component import CustomComponent +from langflow.interface.custom.directory_reader import DirectoryReader +from langflow.interface.custom.utils import build_custom_component_template +from langflow.processing.process import process_tweaks, run_graph_internal +from langflow.services.auth.utils import api_key_security, get_current_active_user +from langflow.services.cache.utils import save_uploaded_file +from langflow.services.database.models.flow import Flow +from langflow.services.database.models.user.model import User +from langflow.services.deps import get_session, get_session_service, get_settings_service, get_task_service +from langflow.services.session.service import SessionService +from langflow.services.task.service import TaskService + +# build router +router = APIRouter(tags=["Base"]) + + +@router.get("/all", dependencies=[Depends(get_current_active_user)]) +def get_all( + settings_service=Depends(get_settings_service), +): + from langflow.interface.types import get_all_types_dict + + logger.debug("Building langchain types dict") + try: + all_types_dict = get_all_types_dict(settings_service.settings.COMPONENTS_PATH) + return all_types_dict + except Exception as exc: + logger.exception(exc) + raise HTTPException(status_code=500, detail=str(exc)) from exc + + +@router.post("/run/{flow_id}", response_model=RunResponse, response_model_exclude_none=True) +async def simplified_run_flow( + db: Annotated[Session, Depends(get_session)], + flow_id: str, + input_request: SimplifiedAPIRequest = SimplifiedAPIRequest(), + stream: bool = False, + api_key_user: User = Depends(api_key_security), + session_service: SessionService = Depends(get_session_service), +): + """ + Executes a specified flow by ID with input customization, performance enhancements through caching, and optional data streaming. + + ### Parameters: + - `db` (Session): Database session for executing queries. + - `flow_id` (str): Unique identifier of the flow to be executed. + - `input_request` (SimplifiedAPIRequest): Request object containing input values, types, output selection, tweaks, and session ID. + - `api_key_user` (User): User object derived from the provided API key, used for authentication. + - `session_service` (SessionService): Service for managing flow sessions, essential for session reuse and caching. + + ### SimplifiedAPIRequest: + - `input_value` (Optional[str], default=""): Input value to pass to the flow. + - `input_type` (Optional[Literal["chat", "text", "any"]], default="chat"): Type of the input value, determining how the input is interpreted. + - `output_type` (Optional[Literal["chat", "text", "any", "debug"]], default="chat"): Desired type of output, affecting which components' outputs are included in the response. If set to "debug", all outputs are returned. + - `output_component` (Optional[str], default=None): Specific component output to retrieve. If provided, only the output of the specified component is returned. This overrides the `output_type` parameter. + - `tweaks` (Optional[Tweaks], default=None): Adjustments to the flow's behavior, allowing for custom execution parameters. + - `session_id` (Optional[str], default=None): An identifier for reusing session data, aiding in performance for subsequent requests. + + + ### Tweaks + A dictionary of tweaks to customize the flow execution. The tweaks can be used to modify the flow's parameters and components. Tweaks can be overridden by the input values. + You can use Component's `id` or Display Name as key to tweak a specific component (e.g., `{"Component Name": {"parameter_name": "value"}}`). + You can also use the parameter name as key to tweak all components with that parameter (e.g., `{"parameter_name": "value"}`). + + ### Returns: + - A `RunResponse` object containing the execution results, including selected (or all, based on `output_type`) outputs of the flow and the session ID, facilitating result retrieval and further interactions in a session context. + + ### Raises: + - HTTPException: 404 if the specified flow ID curl -X 'POST' \ + + ### Example: + ```bash + curl -X 'POST' \ + 'http:///run/{flow_id}' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'x-api-key: YOU_API_KEY' \ + -H ' + -d '{ + "input_value": "Sample input", + "input_type": "chat", + "output_type": "chat", + "tweaks": {}, + }' + ``` + + This endpoint provides a powerful interface for executing flows with enhanced flexibility and efficiency, supporting a wide range of applications by allowing for dynamic input and output configuration along with performance optimizations through session management and caching. + """ + session_id = input_request.session_id + try: + task_result: List[RunOutputs] = [] + artifacts = {} + if input_request.session_id: + session_data = await session_service.load_session(input_request.session_id, flow_id=flow_id) + graph, artifacts = session_data if session_data else (None, None) + if graph is None: + raise ValueError(f"Session {input_request.session_id} not found") + else: + # Get the flow that matches the flow_id and belongs to the user + # flow = session.query(Flow).filter(Flow.id == flow_id).filter(Flow.user_id == api_key_user.id).first() + flow = db.exec(select(Flow).where(Flow.id == flow_id).where(Flow.user_id == api_key_user.id)).first() + if flow is None: + raise ValueError(f"Flow {flow_id} not found") + + if flow.data is None: + raise ValueError(f"Flow {flow_id} has no data") + graph_data = flow.data + graph_data = process_tweaks(graph_data, input_request.tweaks or {}) + graph = Graph.from_payload(graph_data, flow_id=flow_id) + inputs = [ + InputValueRequest(components=[], input_value=input_request.input_value, type=input_request.input_type) + ] + # outputs is a list of all components that should return output + # we need to get them by checking their type + # if the output type is debug, we return all outputs + # if the output type is any, we return all outputs that are either chat or text + # if the output type is chat or text, we return only the outputs that match the type + if input_request.output_component: + outputs = [input_request.output_component] + else: + outputs = [ + vertex.id + for vertex in graph.vertices + if input_request.output_type == "debug" + or ( + vertex.is_output + and (input_request.output_type == "any" or input_request.output_type in vertex.id.lower()) + ) + ] + task_result, session_id = await run_graph_internal( + graph=graph, + flow_id=flow_id, + session_id=input_request.session_id, + inputs=inputs, + outputs=outputs, + artifacts=artifacts, + session_service=session_service, + stream=stream, + ) + + return RunResponse(outputs=task_result, session_id=session_id) + except sa.exc.StatementError as exc: + # StatementError('(builtins.ValueError) badly formed hexadecimal UUID string') + if "badly formed hexadecimal UUID string" in str(exc): + logger.error(f"Flow ID {flow_id} is not a valid UUID") + # This means the Flow ID is not a valid UUID which means it can't find the flow + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc + except ValueError as exc: + if f"Flow {flow_id} not found" in str(exc): + logger.error(f"Flow {flow_id} not found") + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc + elif f"Session {session_id} not found" in str(exc): + logger.error(f"Session {session_id} not found") + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc + else: + logger.exception(exc) + raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(exc)) from exc + except Exception as exc: + logger.exception(exc) + raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(exc)) from exc + + +@router.post("/run/advanced/{flow_id}", response_model=RunResponse, response_model_exclude_none=True) +async def experimental_run_flow( + session: Annotated[Session, Depends(get_session)], + flow_id: str, + inputs: Optional[List[InputValueRequest]] = [InputValueRequest(components=[], input_value="")], + outputs: Optional[List[str]] = [], + tweaks: Annotated[Optional[Tweaks], Body(embed=True)] = None, # noqa: F821 + stream: Annotated[bool, Body(embed=True)] = False, # noqa: F821 + session_id: Annotated[Union[None, str], Body(embed=True)] = None, # noqa: F821 + api_key_user: User = Depends(api_key_security), + session_service: SessionService = Depends(get_session_service), +): + """ + Executes a specified flow by ID with optional input values, output selection, tweaks, and streaming capability. + This endpoint supports running flows with caching to enhance performance and efficiency. + + ### Parameters: + - `flow_id` (str): The unique identifier of the flow to be executed. + - `inputs` (List[InputValueRequest], optional): A list of inputs specifying the input values and components for the flow. Each input can target specific components and provide custom values. + - `outputs` (List[str], optional): A list of output names to retrieve from the executed flow. If not provided, all outputs are returned. + - `tweaks` (Optional[Tweaks], optional): A dictionary of tweaks to customize the flow execution. The tweaks can be used to modify the flow's parameters and components. Tweaks can be overridden by the input values. + - `stream` (bool, optional): Specifies whether the results should be streamed. Defaults to False. + - `session_id` (Union[None, str], optional): An optional session ID to utilize existing session data for the flow execution. + - `api_key_user` (User): The user associated with the current API key. Automatically resolved from the API key. + - `session_service` (SessionService): The session service object for managing flow sessions. + + ### Returns: + A `RunResponse` object containing the selected outputs (or all if not specified) of the executed flow and the session ID. The structure of the response accommodates multiple inputs, providing a nested list of outputs for each input. + + ### Raises: + HTTPException: Indicates issues with finding the specified flow, invalid input formats, or internal errors during flow execution. + + ### Example usage: + ```json + POST /run/{flow_id} + x-api-key: YOUR_API_KEY + Payload: + { + "inputs": [ + {"components": ["component1"], "input_value": "value1"}, + {"components": ["component3"], "input_value": "value2"} + ], + "outputs": ["Component Name", "component_id"], + "tweaks": {"parameter_name": "value", "Component Name": {"parameter_name": "value"}, "component_id": {"parameter_name": "value"}} + "stream": false + } + ``` + + This endpoint facilitates complex flow executions with customized inputs, outputs, and configurations, catering to diverse application requirements. + """ + try: + if outputs is None: + outputs = [] + + task_result: List[RunOutputs] = [] + artifacts = {} + if session_id: + session_data = await session_service.load_session(session_id, flow_id=flow_id) + graph, artifacts = session_data if session_data else (None, None) + if graph is None: + raise ValueError(f"Session {session_id} not found") + else: + # Get the flow that matches the flow_id and belongs to the user + # flow = session.query(Flow).filter(Flow.id == flow_id).filter(Flow.user_id == api_key_user.id).first() + flow = session.exec(select(Flow).where(Flow.id == flow_id).where(Flow.user_id == api_key_user.id)).first() + if flow is None: + raise ValueError(f"Flow {flow_id} not found") + + if flow.data is None: + raise ValueError(f"Flow {flow_id} has no data") + graph_data = flow.data + graph_data = process_tweaks(graph_data, tweaks or {}) + graph = Graph.from_payload(graph_data, flow_id=flow_id) + task_result, session_id = await run_graph_internal( + graph=graph, + flow_id=flow_id, + session_id=session_id, + inputs=inputs, + outputs=outputs, + artifacts=artifacts, + session_service=session_service, + stream=stream, + ) + + return RunResponse(outputs=task_result, session_id=session_id) + except sa.exc.StatementError as exc: + # StatementError('(builtins.ValueError) badly formed hexadecimal UUID string') + if "badly formed hexadecimal UUID string" in str(exc): + logger.error(f"Flow ID {flow_id} is not a valid UUID") + # This means the Flow ID is not a valid UUID which means it can't find the flow + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc + except ValueError as exc: + if f"Flow {flow_id} not found" in str(exc): + logger.error(f"Flow {flow_id} not found") + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc + elif f"Session {session_id} not found" in str(exc): + logger.error(f"Session {session_id} not found") + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc + else: + logger.exception(exc) + raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(exc)) from exc + except Exception as exc: + logger.exception(exc) + raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(exc)) from exc + + +@router.post( + "/predict/{flow_id}", + response_model=ProcessResponse, + dependencies=[Depends(api_key_security)], +) +@router.post( + "/process/{flow_id}", + response_model=ProcessResponse, +) +async def process( + session: Annotated[Session, Depends(get_session)], + flow_id: str, + inputs: Optional[Union[List[dict], dict]] = None, + tweaks: Optional[dict] = None, + clear_cache: Annotated[bool, Body(embed=True)] = False, # noqa: F821 + session_id: Annotated[Union[None, str], Body(embed=True)] = None, # noqa: F821 + task_service: "TaskService" = Depends(get_task_service), + api_key_user: User = Depends(api_key_security), + sync: Annotated[bool, Body(embed=True)] = True, # noqa: F821 + session_service: SessionService = Depends(get_session_service), +): + """ + Endpoint to process an input with a given flow_id. + """ + # Raise a depreciation warning + logger.warning( + "The /process endpoint is deprecated and will be removed in a future version. " "Please use /run instead." + ) + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="The /process endpoint is deprecated and will be removed in a future version. " + "Please use /run instead.", + ) + + +@router.get("/task/{task_id}", response_model=TaskStatusResponse) +async def get_task_status(task_id: str): + task_service = get_task_service() + task = task_service.get_task(task_id) + result = None + if task is None: + raise HTTPException(status_code=404, detail="Task not found") + if task.ready(): + result = task.result + # If result isinstance of Exception, can we get the traceback? + if isinstance(result, Exception): + logger.exception(task.traceback) + + if isinstance(result, dict) and "result" in result: + result = result["result"] + elif hasattr(result, "result"): + result = result.result + + if task.status == "FAILURE": + result = str(task.result) + logger.error(f"Task {task_id} failed: {task.traceback}") + + return TaskStatusResponse(status=task.status, result=result) + + +@router.post( + "/upload/{flow_id}", + response_model=UploadFileResponse, + status_code=HTTPStatus.CREATED, +) +async def create_upload_file( + file: UploadFile, + flow_id: str, +): + try: + file_path = save_uploaded_file(file, folder_name=flow_id) + + return UploadFileResponse( + flowId=flow_id, + file_path=file_path, + ) + except Exception as exc: + logger.error(f"Error saving file: {exc}") + raise HTTPException(status_code=500, detail=str(exc)) from exc + + +# get endpoint to return version of langflow +@router.get("/version") +def get_version(): + try: + from langflow.version import __version__ + + version = __version__ + package = "Langflow" + except ImportError: + from importlib import metadata + + version = metadata.version("langflow-base") + package = "Langflow Base" + return {"version": version, "package": package} + + +@router.post("/custom_component", status_code=HTTPStatus.OK) +async def custom_component( + raw_code: CustomComponentRequest, + user: User = Depends(get_current_active_user), +): + component = CustomComponent(code=raw_code.code) + + built_frontend_node, _ = build_custom_component_template(component, user_id=user.id) + + built_frontend_node = update_frontend_node_with_template_values(built_frontend_node, raw_code.frontend_node) + return built_frontend_node + + +@router.post("/custom_component/reload", status_code=HTTPStatus.OK) +async def reload_custom_component(path: str, user: User = Depends(get_current_active_user)): + from langflow.interface.custom.utils import build_custom_component_template + + try: + reader = DirectoryReader("") + valid, content = reader.process_file(path) + if not valid: + raise ValueError(content) + + extractor = CustomComponent(code=content) + frontend_node, _ = build_custom_component_template(extractor, user_id=user.id) + return frontend_node + except Exception as exc: + raise HTTPException(status_code=400, detail=str(exc)) + + +@router.post("/custom_component/update", status_code=HTTPStatus.OK) +async def custom_component_update( + code_request: UpdateCustomComponentRequest, + user: User = Depends(get_current_active_user), +): + """ + Update a custom component with the provided code request. + + This endpoint generates the CustomComponentFrontendNode normally but then runs the `update_build_config` method + on the latest version of the template. This ensures that every time it runs, it has the latest version of the template. + + Args: + code_request (CustomComponentRequest): The code request containing the updated code for the custom component. + user (User, optional): The user making the request. Defaults to the current active user. + + Returns: + dict: The updated custom component node. + + """ + try: + component = CustomComponent(code=code_request.code) + + component_node, cc_instance = build_custom_component_template( + component, + user_id=user.id, + ) + + updated_build_config = cc_instance.update_build_config( + build_config=code_request.get_template(), + field_value=code_request.field_value, + field_name=code_request.field, + ) + component_node["template"] = updated_build_config + + return component_node + except Exception as exc: + logger.exception(exc) + raise HTTPException(status_code=400, detail=str(exc)) from exc diff --git a/src/backend/base/langflow/api/v1/files.py b/src/backend/base/langflow/api/v1/files.py new file mode 100644 index 000000000..435aea826 --- /dev/null +++ b/src/backend/base/langflow/api/v1/files.py @@ -0,0 +1,116 @@ +import hashlib +from http import HTTPStatus +from io import BytesIO + +from fastapi import APIRouter, Depends, HTTPException, UploadFile +from fastapi.responses import StreamingResponse + + +from langflow.api.v1.schemas import UploadFileResponse +from langflow.services.auth.utils import get_current_active_user +from langflow.services.database.models.flow import Flow +from langflow.services.deps import get_session, get_storage_service +from langflow.services.storage.service import StorageService +from langflow.services.storage.utils import build_content_type_from_extension + +router = APIRouter(tags=["Files"], prefix="/files") + + +# Create dep that gets the flow_id from the request +# then finds it in the database and returns it while +# using the current user as the owner +def get_flow_id( + flow_id: str, + current_user=Depends(get_current_active_user), + session=Depends(get_session), +): + # AttributeError: 'SelectOfScalar' object has no attribute 'first' + flow = session.get(Flow, flow_id) + if not flow: + raise HTTPException(status_code=404, detail="Flow not found") + if flow.user_id != current_user.id: + raise HTTPException(status_code=403, detail="You don't have access to this flow") + return flow_id + + +@router.post("/upload/{flow_id}", status_code=HTTPStatus.CREATED) +async def upload_file( + file: UploadFile, + flow_id: str = Depends(get_flow_id), + storage_service: StorageService = Depends(get_storage_service), +): + try: + file_content = await file.read() + file_name = file.filename or hashlib.sha256(file_content).hexdigest() + folder = flow_id + await storage_service.save_file(flow_id=folder, file_name=file_name, data=file_content) + return UploadFileResponse(flowId=flow_id, file_path=f"{folder}/{file_name}") + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) + + +@router.get("/download/{flow_id}/{file_name}") +async def download_file(file_name: str, flow_id: str, storage_service: StorageService = Depends(get_storage_service)): + try: + extension = file_name.split(".")[-1] + + if not extension: + raise HTTPException(status_code=500, detail=f"Extension not found for file {file_name}") + + content_type = build_content_type_from_extension(extension) + + if not content_type: + raise HTTPException(status_code=500, detail=f"Content type not found for extension {extension}") + + file_content = await storage_service.get_file(flow_id=flow_id, file_name=file_name) + headers = { + "Content-Disposition": f"attachment; filename={file_name} filename*=UTF-8''{file_name}", + "Content-Type": "application/octet-stream", + "Content-Length": str(len(file_content)), + } + return StreamingResponse(BytesIO(file_content), media_type=content_type, headers=headers) + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) + + +@router.get("/images/{flow_id}/{file_name}") +async def download_image(file_name: str, flow_id: str, storage_service: StorageService = Depends(get_storage_service)): + try: + extension = file_name.split(".")[-1] + + if not extension: + raise HTTPException(status_code=500, detail=f"Extension not found for file {file_name}") + + content_type = build_content_type_from_extension(extension) + + if not content_type: + raise HTTPException(status_code=500, detail=f"Content type not found for extension {extension}") + elif not content_type.startswith("image"): + raise HTTPException(status_code=500, detail=f"Content type {content_type} is not an image") + + file_content = await storage_service.get_file(flow_id=flow_id, file_name=file_name) + return StreamingResponse(BytesIO(file_content), media_type=content_type) + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) + + +@router.get("/list/{flow_id}") +async def list_files( + flow_id: str = Depends(get_flow_id), storage_service: StorageService = Depends(get_storage_service) +): + try: + files = await storage_service.list_files(flow_id=flow_id) + return {"files": files} + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) + + +@router.delete("/delete/{flow_id}/{file_name}") +async def delete_file( + file_name: str, flow_id: str = Depends(get_flow_id), storage_service: StorageService = Depends(get_storage_service) +): + try: + await storage_service.delete_file(flow_id=flow_id, file_name=file_name) + return {"message": f"File {file_name} deleted successfully"} + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) diff --git a/src/backend/langflow/api/v1/flows.py b/src/backend/base/langflow/api/v1/flows.py similarity index 67% rename from src/backend/langflow/api/v1/flows.py rename to src/backend/base/langflow/api/v1/flows.py index 517ff33c1..bd055f120 100644 --- a/src/backend/langflow/api/v1/flows.py +++ b/src/backend/base/langflow/api/v1/flows.py @@ -5,14 +5,17 @@ from uuid import UUID import orjson from fastapi import APIRouter, Depends, File, HTTPException, UploadFile from fastapi.encoders import jsonable_encoder +from loguru import logger from sqlmodel import Session, select from langflow.api.utils import remove_api_keys, validate_is_component from langflow.api.v1.schemas import FlowListCreate, FlowListRead +from langflow.initial_setup.setup import STARTER_FOLDER_NAME from langflow.services.auth.utils import get_current_active_user from langflow.services.database.models.flow import Flow, FlowCreate, FlowRead, FlowUpdate from langflow.services.database.models.user.model import User from langflow.services.deps import get_session, get_settings_service +from langflow.services.settings.service import SettingsService # build router router = APIRouter(prefix="/flows", tags=["Flows"]) @@ -42,11 +45,36 @@ def create_flow( def read_flows( *, current_user: User = Depends(get_current_active_user), + session: Session = Depends(get_session), + settings_service: "SettingsService" = Depends(get_settings_service), ): """Read all flows.""" try: - flows = current_user.flows - flows = validate_is_component(flows) + auth_settings = settings_service.auth_settings + if auth_settings.AUTO_LOGIN: + flows = session.exec( + select(Flow).where( + (Flow.user_id == None) | (Flow.user_id == current_user.id) # noqa + ) + ).all() + else: + flows = current_user.flows + + flows = validate_is_component(flows) # type: ignore + flow_ids = [flow.id for flow in flows] + # with the session get the flows that DO NOT have a user_id + try: + example_flows = session.exec( + select(Flow).where( + Flow.user_id == None, # noqa + Flow.folder == STARTER_FOLDER_NAME, + ) + ).all() + for example_flow in example_flows: + if example_flow.id not in flow_ids: + flows.append(example_flow) # type: ignore + except Exception as e: + logger.error(e) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) from e return [jsonable_encoder(flow) for flow in flows] @@ -58,9 +86,18 @@ def read_flow( session: Session = Depends(get_session), flow_id: UUID, current_user: User = Depends(get_current_active_user), + settings_service: "SettingsService" = Depends(get_settings_service), ): """Read a flow.""" - if user_flow := (session.exec(select(Flow).where(Flow.id == flow_id, Flow.user_id == current_user.id)).first()): + auth_settings = settings_service.auth_settings + stmt = select(Flow).where(Flow.id == flow_id) + if auth_settings.AUTO_LOGIN: + # If auto login is enable user_id can be current_user.id or None + # so write an OR + stmt = stmt.where( + (Flow.user_id == current_user.id) | (Flow.user_id == None) # noqa + ) # noqa + if user_flow := session.exec(stmt).first(): return user_flow else: raise HTTPException(status_code=404, detail="Flow not found") @@ -77,7 +114,12 @@ def update_flow( ): """Update a flow.""" - db_flow = read_flow(session=session, flow_id=flow_id, current_user=current_user) + db_flow = read_flow( + session=session, + flow_id=flow_id, + current_user=current_user, + settings_service=settings_service, + ) if not db_flow: raise HTTPException(status_code=404, detail="Flow not found") flow_data = flow.model_dump(exclude_unset=True) @@ -99,9 +141,15 @@ def delete_flow( session: Session = Depends(get_session), flow_id: UUID, current_user: User = Depends(get_current_active_user), + settings_service=Depends(get_settings_service), ): """Delete a flow.""" - flow = read_flow(session=session, flow_id=flow_id, current_user=current_user) + flow = read_flow( + session=session, + flow_id=flow_id, + current_user=current_user, + settings_service=settings_service, + ) if not flow: raise HTTPException(status_code=404, detail="Flow not found") session.delete(flow) @@ -109,9 +157,6 @@ def delete_flow( return {"message": "Flow deleted successfully"} -# Define a new model to handle multiple flows - - @router.post("/batch/", response_model=List[FlowRead], status_code=201) def create_flows( *, @@ -157,8 +202,9 @@ async def upload_file( async def download_file( *, session: Session = Depends(get_session), + settings_service: "SettingsService" = Depends(get_settings_service), current_user: User = Depends(get_current_active_user), ): """Download all flows as a file.""" - flows = read_flows(current_user=current_user) + flows = read_flows(current_user=current_user, session=session, settings_service=settings_service) return FlowListRead(flows=flows) diff --git a/src/backend/langflow/api/v1/login.py b/src/backend/base/langflow/api/v1/login.py similarity index 88% rename from src/backend/langflow/api/v1/login.py rename to src/backend/base/langflow/api/v1/login.py index b0946fd0a..fba61d3b4 100644 --- a/src/backend/langflow/api/v1/login.py +++ b/src/backend/base/langflow/api/v1/login.py @@ -10,6 +10,7 @@ from langflow.services.auth.utils import ( create_user_tokens, ) from langflow.services.deps import get_session, get_settings_service +from langflow.services.settings.manager import SettingsService router = APIRouter(tags=["Login"]) @@ -41,6 +42,7 @@ async def login_to_get_access_token( httponly=auth_settings.REFRESH_HTTPONLY, samesite=auth_settings.REFRESH_SAME_SITE, secure=auth_settings.REFRESH_SECURE, + expires=auth_settings.REFRESH_TOKEN_EXPIRE_SECONDS, ) response.set_cookie( "access_token_lf", @@ -48,6 +50,7 @@ async def login_to_get_access_token( httponly=auth_settings.ACCESS_HTTPONLY, samesite=auth_settings.ACCESS_SAME_SITE, secure=auth_settings.ACCESS_SECURE, + expires=auth_settings.ACCESS_TOKEN_EXPIRE_SECONDS, ) return tokens else: @@ -73,6 +76,7 @@ async def auto_login( httponly=auth_settings.ACCESS_HTTPONLY, samesite=auth_settings.ACCESS_SAME_SITE, secure=auth_settings.ACCESS_SECURE, + expires=None, # Set to None to make it a session cookie ) return tokens @@ -87,7 +91,7 @@ async def auto_login( @router.post("/refresh") async def refresh_token( - request: Request, response: Response, settings_service=Depends(get_settings_service) + request: Request, response: Response, settings_service: "SettingsService" = Depends(get_settings_service) ): auth_settings = settings_service.auth_settings @@ -101,6 +105,7 @@ async def refresh_token( httponly=auth_settings.REFRESH_HTTPONLY, samesite=auth_settings.REFRESH_SAME_SITE, secure=auth_settings.REFRESH_SECURE, + expires=auth_settings.REFRESH_TOKEN_EXPIRE_SECONDS, ) response.set_cookie( "access_token_lf", @@ -108,6 +113,7 @@ async def refresh_token( httponly=auth_settings.ACCESS_HTTPONLY, samesite=auth_settings.ACCESS_SAME_SITE, secure=auth_settings.ACCESS_SECURE, + expires=auth_settings.ACCESS_TOKEN_EXPIRE_SECONDS, ) return tokens else: diff --git a/src/backend/base/langflow/api/v1/monitor.py b/src/backend/base/langflow/api/v1/monitor.py new file mode 100644 index 000000000..dbefd1c3b --- /dev/null +++ b/src/backend/base/langflow/api/v1/monitor.py @@ -0,0 +1,73 @@ +from typing import Optional + +from fastapi import APIRouter, Depends, HTTPException, Query + + +from langflow.services.deps import get_monitor_service +from langflow.services.monitor.schema import VertexBuildMapModel +from langflow.services.monitor.service import MonitorService + +router = APIRouter(prefix="/monitor", tags=["Monitor"]) + + +# Get vertex_builds data from the monitor service +@router.get("/builds", response_model=VertexBuildMapModel) +async def get_vertex_builds( + flow_id: Optional[str] = Query(None), + vertex_id: Optional[str] = Query(None), + valid: Optional[bool] = Query(None), + order_by: Optional[str] = Query("timestamp"), + monitor_service: MonitorService = Depends(get_monitor_service), +): + try: + vertex_build_dicts = monitor_service.get_vertex_builds( + flow_id=flow_id, vertex_id=vertex_id, valid=valid, order_by=order_by + ) + vertex_build_map = VertexBuildMapModel.from_list_of_dicts(vertex_build_dicts) + return vertex_build_map + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) + + +@router.delete("/builds", status_code=204) +async def delete_vertex_builds( + flow_id: Optional[str] = Query(None), + monitor_service: MonitorService = Depends(get_monitor_service), +): + try: + monitor_service.delete_vertex_builds(flow_id=flow_id) + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) + + +@router.get("/messages") +async def get_messages( + session_id: Optional[str] = Query(None), + sender: Optional[str] = Query(None), + sender_name: Optional[str] = Query(None), + order_by: Optional[str] = Query("timestamp"), + monitor_service: MonitorService = Depends(get_monitor_service), +): + try: + return monitor_service.get_messages( + sender=sender, + sender_name=sender_name, + session_id=session_id, + order_by=order_by, + ) + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) + + +@router.get("/transactions") +async def get_transactions( + source: Optional[str] = Query(None), + target: Optional[str] = Query(None), + status: Optional[str] = Query(None), + order_by: Optional[str] = Query("timestamp"), + monitor_service: MonitorService = Depends(get_monitor_service), +): + try: + return monitor_service.get_transactions(source=source, target=target, status=status, order_by=order_by) + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) diff --git a/src/backend/base/langflow/api/v1/schemas.py b/src/backend/base/langflow/api/v1/schemas.py new file mode 100644 index 000000000..631c37fbb --- /dev/null +++ b/src/backend/base/langflow/api/v1/schemas.py @@ -0,0 +1,325 @@ +from datetime import datetime +from enum import Enum +from pathlib import Path +from typing import Any, Dict, List, Optional, Union +from uuid import UUID + +from pydantic import BaseModel, ConfigDict, Field, RootModel, field_validator, model_serializer + +from langflow.graph.schema import RunOutputs +from langflow.schema import dotdict +from langflow.schema.schema import InputType, OutputType +from langflow.services.database.models.api_key.model import ApiKeyRead +from langflow.services.database.models.base import orjson_dumps +from langflow.services.database.models.flow import FlowCreate, FlowRead +from langflow.services.database.models.user import UserRead + + +class BuildStatus(Enum): + """Status of the build.""" + + SUCCESS = "success" + FAILURE = "failure" + STARTED = "started" + IN_PROGRESS = "in_progress" + + +class TweaksRequest(BaseModel): + tweaks: Optional[Dict[str, Dict[str, str]]] = Field(default_factory=dict) + + +class UpdateTemplateRequest(BaseModel): + template: dict + + +class TaskResponse(BaseModel): + """Task response schema.""" + + id: Optional[str] = Field(None) + href: Optional[str] = Field(None) + + +class ProcessResponse(BaseModel): + """Process response schema.""" + + result: Any + status: Optional[str] = None + task: Optional[TaskResponse] = None + session_id: Optional[str] = None + backend: Optional[str] = None + + +class RunResponse(BaseModel): + """Run response schema.""" + + outputs: Optional[List[RunOutputs]] = [] + session_id: Optional[str] = None + + @model_serializer(mode="plain") + def serialize(self): + # Serialize all the outputs if they are base models + serialized = {"session_id": self.session_id, "outputs": []} + if self.outputs: + serialized_outputs = [] + for output in self.outputs: + if isinstance(output, BaseModel) and not isinstance(output, RunOutputs): + serialized_outputs.append(output.model_dump(exclude_none=True)) + else: + serialized_outputs.append(output) + serialized["outputs"] = serialized_outputs + return serialized + + +class PreloadResponse(BaseModel): + """Preload response schema.""" + + session_id: Optional[str] = None + is_clear: Optional[bool] = None + + +class TaskStatusResponse(BaseModel): + """Task status response schema.""" + + status: str + result: Optional[Any] = None + + +class ChatMessage(BaseModel): + """Chat message schema.""" + + is_bot: bool = False + message: Union[str, None, dict] = None + chatKey: Optional[str] = None + type: str = "human" + + +class ChatResponse(ChatMessage): + """Chat response schema.""" + + intermediate_steps: str + + type: str + is_bot: bool = True + files: list = [] + + @field_validator("type") + @classmethod + def validate_message_type(cls, v): + if v not in ["start", "stream", "end", "error", "info", "file"]: + raise ValueError("type must be start, stream, end, error, info, or file") + return v + + +class PromptResponse(ChatMessage): + """Prompt response schema.""" + + prompt: str + type: str = "prompt" + is_bot: bool = True + + +class FileResponse(ChatMessage): + """File response schema.""" + + data: Any = None + data_type: str + type: str = "file" + is_bot: bool = True + + @field_validator("data_type") + @classmethod + def validate_data_type(cls, v): + if v not in ["image", "csv"]: + raise ValueError("data_type must be image or csv") + return v + + +class FlowListCreate(BaseModel): + flows: List[FlowCreate] + + +class FlowListRead(BaseModel): + flows: List[FlowRead] + + +class InitResponse(BaseModel): + flowId: str + + +class BuiltResponse(BaseModel): + built: bool + + +class UploadFileResponse(BaseModel): + """Upload file response schema.""" + + flowId: str + file_path: Path + + +class StreamData(BaseModel): + event: str + data: dict + + def __str__(self) -> str: + return f"event: {self.event}\ndata: {orjson_dumps(self.data, indent_2=False)}\n\n" + + +class CustomComponentRequest(BaseModel): + model_config = ConfigDict(arbitrary_types_allowed=True) + code: str + frontend_node: Optional[dict] = None + + +class UpdateCustomComponentRequest(CustomComponentRequest): + field: str + field_value: Optional[Union[str, int, float, bool, dict, list]] = None + template: dict + + def get_template(self): + return dotdict(self.template) + + +class CustomComponentResponseError(BaseModel): + detail: str + traceback: str + + +class ComponentListCreate(BaseModel): + flows: List[FlowCreate] + + +class ComponentListRead(BaseModel): + flows: List[FlowRead] + + +class UsersResponse(BaseModel): + total_count: int + users: List[UserRead] + + +class ApiKeyResponse(BaseModel): + id: str + api_key: str + name: str + created_at: str + last_used_at: str + + +class ApiKeysResponse(BaseModel): + total_count: int + user_id: UUID + api_keys: List[ApiKeyRead] + + +class CreateApiKeyRequest(BaseModel): + name: str + + +class Token(BaseModel): + access_token: str + refresh_token: str + token_type: str + + +class ApiKeyCreateRequest(BaseModel): + api_key: str + + +class VerticesOrderResponse(BaseModel): + ids: List[str] + run_id: UUID + vertices_to_run: List[str] + + +class ResultDataResponse(BaseModel): + results: Optional[Any] = Field(default_factory=dict) + artifacts: Optional[Any] = Field(default_factory=dict) + timedelta: Optional[float] = None + duration: Optional[str] = None + + +class VertexBuildResponse(BaseModel): + id: Optional[str] = None + inactivated_vertices: Optional[List[str]] = None + next_vertices_ids: Optional[List[str]] = None + top_level_vertices: Optional[List[str]] = None + valid: bool + params: Optional[Any] = Field(default_factory=dict) + """JSON string of the params.""" + data: ResultDataResponse + """Mapping of vertex ids to result dict containing the param name and result value.""" + timestamp: Optional[datetime] = Field(default_factory=datetime.utcnow) + """Timestamp of the build.""" + + +class VerticesBuiltResponse(BaseModel): + vertices: List[VertexBuildResponse] + + +class InputValueRequest(BaseModel): + components: Optional[List[str]] = [] + input_value: Optional[str] = None + type: Optional[InputType] = Field( + "any", + description="Defines on which components the input value should be applied. 'any' applies to all input components.", + ) + + # add an example + model_config = ConfigDict( + json_schema_extra={ + "examples": [ + { + "components": ["components_id", "Component Name"], + "input_value": "input_value", + }, + {"components": ["Component Name"], "input_value": "input_value"}, + {"input_value": "input_value"}, + {"type": "chat", "input_value": "input_value"}, + {"type": "json", "input_value": '{"key": "value"}'}, + ] + }, + extra="forbid", + ) + + +class Tweaks(RootModel): + root: dict[str, Union[str, dict[str, str]]] = Field( + description="A dictionary of tweaks to adjust the flow's execution. Allows customizing flow behavior dynamically. All tweaks are overridden by the input values.", + ) + model_config = { + "json_schema_extra": { + "examples": [ + { + "parameter_name": "value", + "Component Name": {"parameter_name": "value"}, + "component_id": {"parameter_name": "value"}, + } + ] + } + } + + # This should behave like a dict + def __getitem__(self, key): + return self.root[key] + + def __setitem__(self, key, value): + self.root[key] = value + + def __delitem__(self, key): + del self.root[key] + + def items(self): + return self.root.items() + + +class SimplifiedAPIRequest(BaseModel): + input_value: Optional[str] = Field(default="", description="The input value") + input_type: Optional[InputType] = Field(default="chat", description="The input type") + output_type: Optional[OutputType] = Field(default="chat", description="The output type") + output_component: Optional[str] = Field( + default="", + description="If there are multiple output components, you can specify the component to get the output from.", + ) + tweaks: Optional[Tweaks] = Field(default=None, description="The tweaks") + session_id: Optional[str] = Field(default=None, description="The session id") diff --git a/src/backend/langflow/api/v1/store.py b/src/backend/base/langflow/api/v1/store.py similarity index 100% rename from src/backend/langflow/api/v1/store.py rename to src/backend/base/langflow/api/v1/store.py diff --git a/src/backend/langflow/api/v1/users.py b/src/backend/base/langflow/api/v1/users.py similarity index 100% rename from src/backend/langflow/api/v1/users.py rename to src/backend/base/langflow/api/v1/users.py diff --git a/src/backend/base/langflow/api/v1/validate.py b/src/backend/base/langflow/api/v1/validate.py new file mode 100644 index 000000000..97841bca6 --- /dev/null +++ b/src/backend/base/langflow/api/v1/validate.py @@ -0,0 +1,81 @@ +from collections import defaultdict + +from fastapi import APIRouter, HTTPException +from loguru import logger + +from langflow.api.v1.base import Code, CodeValidationResponse, PromptValidationResponse, ValidatePromptRequest +from langflow.base.prompts.utils import ( + add_new_variables_to_template, + get_old_custom_fields, + remove_old_variables_from_template, + update_input_variables_field, + validate_prompt, +) +from langflow.utils.validate import validate_code + +# build router +router = APIRouter(prefix="/validate", tags=["Validate"]) + + +@router.post("/code", status_code=200, response_model=CodeValidationResponse) +def post_validate_code(code: Code): + try: + errors = validate_code(code.code) + return CodeValidationResponse( + imports=errors.get("imports", {}), + function=errors.get("function", {}), + ) + except Exception as e: + return HTTPException(status_code=500, detail=str(e)) + + +@router.post("/prompt", status_code=200, response_model=PromptValidationResponse) +def post_validate_prompt(prompt_request: ValidatePromptRequest): + try: + input_variables = validate_prompt(prompt_request.template) + # Check if frontend_node is None before proceeding to avoid attempting to update a non-existent node. + if prompt_request.frontend_node is None: + return PromptValidationResponse( + input_variables=input_variables, + frontend_node=None, + ) + if not prompt_request.frontend_node.custom_fields: + prompt_request.frontend_node.custom_fields = defaultdict(list) + old_custom_fields = get_old_custom_fields(prompt_request.frontend_node.custom_fields, prompt_request.name) + + add_new_variables_to_template( + input_variables, + prompt_request.frontend_node.custom_fields, + prompt_request.frontend_node.template, + prompt_request.name, + ) + + remove_old_variables_from_template( + old_custom_fields, + input_variables, + prompt_request.frontend_node.custom_fields, + prompt_request.frontend_node.template, + prompt_request.name, + ) + + update_input_variables_field(input_variables, prompt_request.frontend_node.template) + + # If frontend_node.template contains only one field that is type == 'prompt', then we can remove all fields that are not + # 'code', and not in the input_variables list. + prompt_fields = [ + key + for key, field in prompt_request.frontend_node.template.items() + if isinstance(field, dict) and field["type"] == "prompt" + ] + + if len(prompt_fields) == 1: + for key, field in prompt_request.frontend_node.template.copy().items(): + if isinstance(field, dict) and field["type"] != "code" and key not in input_variables + prompt_fields: + del prompt_request.frontend_node.template[key] + return PromptValidationResponse( + input_variables=input_variables, + frontend_node=prompt_request.frontend_node, + ) + except Exception as e: + logger.exception(e) + raise HTTPException(status_code=500, detail=str(e)) from e diff --git a/src/backend/base/langflow/api/v1/variable.py b/src/backend/base/langflow/api/v1/variable.py new file mode 100644 index 000000000..123086676 --- /dev/null +++ b/src/backend/base/langflow/api/v1/variable.py @@ -0,0 +1,113 @@ +from datetime import datetime +from uuid import UUID + +from fastapi import APIRouter, Depends, HTTPException +from sqlmodel import Session, select + +from langflow.services.auth import utils as auth_utils +from langflow.services.auth.utils import get_current_active_user +from langflow.services.database.models.user.model import User +from langflow.services.database.models.variable import Variable, VariableCreate, VariableRead, VariableUpdate +from langflow.services.deps import get_session, get_settings_service + +router = APIRouter(prefix="/variables", tags=["Variables"]) + + +@router.post("/", response_model=VariableRead, status_code=201) +def create_variable( + *, + session: Session = Depends(get_session), + variable: VariableCreate, + current_user: User = Depends(get_current_active_user), + settings_service=Depends(get_settings_service), +): + """Create a new variable.""" + try: + # check if variable name already exists + variable_exists = session.exec( + select(Variable).where( + Variable.name == variable.name, + Variable.user_id == current_user.id, + ) + ).first() + if variable_exists: + raise HTTPException(status_code=400, detail="Variable name already exists") + + variable_dict = variable.model_dump() + variable_dict["user_id"] = current_user.id + + db_variable = Variable.model_validate(variable_dict) + if not db_variable.value: + raise HTTPException(status_code=400, detail="Variable value cannot be empty") + encrypted = auth_utils.encrypt_api_key(db_variable.value, settings_service=settings_service) + db_variable.value = encrypted + db_variable.user_id = current_user.id + session.add(db_variable) + session.commit() + session.refresh(db_variable) + return db_variable + except Exception as e: + if isinstance(e, HTTPException): + raise e + raise HTTPException(status_code=500, detail=str(e)) from e + + +@router.get("/", response_model=list[VariableRead], status_code=200) +def read_variables( + *, + session: Session = Depends(get_session), + current_user: User = Depends(get_current_active_user), +): + """Read all variables.""" + try: + variables = session.exec(select(Variable).where(Variable.user_id == current_user.id)).all() + return variables + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) from e + + +@router.patch("/{variable_id}", response_model=VariableRead, status_code=200) +def update_variable( + *, + session: Session = Depends(get_session), + variable_id: UUID, + variable: VariableUpdate, + current_user: User = Depends(get_current_active_user), +): + """Update a variable.""" + try: + db_variable = session.exec( + select(Variable).where(Variable.id == variable_id, Variable.user_id == current_user.id) + ).first() + if not db_variable: + raise HTTPException(status_code=404, detail="Variable not found") + + variable_data = variable.model_dump(exclude_unset=True) + for key, value in variable_data.items(): + setattr(db_variable, key, value) + db_variable.updated_at = datetime.utcnow() + session.commit() + session.refresh(db_variable) + return db_variable + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) from e + + +@router.delete("/{variable_id}", status_code=204) +def delete_variable( + *, + session: Session = Depends(get_session), + variable_id: UUID, + current_user: User = Depends(get_current_active_user), +): + """Delete a variable.""" + try: + db_variable = session.exec( + select(Variable).where(Variable.id == variable_id, Variable.user_id == current_user.id) + ).first() + if not db_variable: + raise HTTPException(status_code=404, detail="Variable not found") + session.delete(db_variable) + session.commit() + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) from e diff --git a/src/backend/langflow/interface/embeddings/__init__.py b/src/backend/base/langflow/base/__init__.py similarity index 100% rename from src/backend/langflow/interface/embeddings/__init__.py rename to src/backend/base/langflow/base/__init__.py diff --git a/src/backend/langflow/interface/initialize/__init__.py b/src/backend/base/langflow/base/agents/__init__.py similarity index 100% rename from src/backend/langflow/interface/initialize/__init__.py rename to src/backend/base/langflow/base/agents/__init__.py diff --git a/src/backend/base/langflow/base/agents/agent.py b/src/backend/base/langflow/base/agents/agent.py new file mode 100644 index 000000000..5ef498b66 --- /dev/null +++ b/src/backend/base/langflow/base/agents/agent.py @@ -0,0 +1,75 @@ +from typing import List, Optional, Union, cast + +from langchain.agents import AgentExecutor, BaseMultiActionAgent, BaseSingleActionAgent +from langchain_core.runnables import Runnable + +from langflow.custom import CustomComponent +from langflow.field_typing import BaseMemory, Text, Tool + + +class LCAgentComponent(CustomComponent): + def build_config(self): + return { + "lc": { + "display_name": "LangChain", + "info": "The LangChain to interact with.", + }, + "handle_parsing_errors": { + "display_name": "Handle Parsing Errors", + "info": "If True, the agent will handle parsing errors. If False, the agent will raise an error.", + "advanced": True, + }, + "output_key": { + "display_name": "Output Key", + "info": "The key to use to get the output from the agent.", + "advanced": True, + }, + "memory": { + "display_name": "Memory", + "info": "Memory to use for the agent.", + }, + "tools": { + "display_name": "Tools", + "info": "Tools the agent can use.", + }, + "input_value": { + "display_name": "Input", + "info": "Input text to pass to the agent.", + }, + } + + async def run_agent( + self, + agent: Union[Runnable, BaseSingleActionAgent, BaseMultiActionAgent, AgentExecutor], + inputs: str, + input_variables: list[str], + tools: List[Tool], + memory: Optional[BaseMemory] = None, + handle_parsing_errors: bool = True, + output_key: str = "output", + ) -> Text: + if isinstance(agent, AgentExecutor): + runnable = agent + else: + runnable = AgentExecutor.from_agent_and_tools( + agent=agent, # type: ignore + tools=tools, + verbose=True, + memory=memory, + handle_parsing_errors=handle_parsing_errors, + ) + input_dict = {"input": inputs} + for var in input_variables: + if var not in ["agent_scratchpad", "input"]: + input_dict[var] = "" + result = await runnable.ainvoke(input_dict) + self.status = result + if output_key in result: + return cast(str, result.get(output_key)) + elif "output" not in result: + if output_key != "output": + raise ValueError(f"Output key not found in result. Tried '{output_key}' and 'output'.") + else: + raise ValueError("Output key not found in result. Tried 'output'.") + + return cast(str, result.get("output")) diff --git a/src/backend/base/langflow/base/constants.py b/src/backend/base/langflow/base/constants.py new file mode 100644 index 000000000..a54d6eff5 --- /dev/null +++ b/src/backend/base/langflow/base/constants.py @@ -0,0 +1,27 @@ +""" +This module contains constants used in the Langflow base module. + +Constants: +- STREAM_INFO_TEXT: A string representing the information about streaming the response from the model. +- NODE_FORMAT_ATTRIBUTES: A list of attributes used for formatting nodes. +- FIELD_FORMAT_ATTRIBUTES: A list of attributes used for formatting fields. +""" +STREAM_INFO_TEXT = "Stream the response from the model. Streaming works only in Chat." + +NODE_FORMAT_ATTRIBUTES = ["beta", "icon", "display_name", "description"] + + +FIELD_FORMAT_ATTRIBUTES = [ + "info", + "display_name", + "required", + "list", + "multiline", + "fileTypes", + "password", + "input_types", + "title_case", + "real_time_refresh", + "refresh_button", + "refresh_button_text", +] diff --git a/src/backend/langflow/interface/output_parsers/__init__.py b/src/backend/base/langflow/base/data/__init__.py similarity index 100% rename from src/backend/langflow/interface/output_parsers/__init__.py rename to src/backend/base/langflow/base/data/__init__.py diff --git a/src/backend/base/langflow/base/data/utils.py b/src/backend/base/langflow/base/data/utils.py new file mode 100644 index 000000000..c3fda5e34 --- /dev/null +++ b/src/backend/base/langflow/base/data/utils.py @@ -0,0 +1,141 @@ +import json +import xml.etree.ElementTree as ET +from concurrent import futures +from pathlib import Path +from typing import Callable, List, Optional, Text + +import yaml + +from langflow.schema.schema import Record + +# Types of files that can be read simply by file.read() +# and have 100% to be completely readable +TEXT_FILE_TYPES = ["txt", "md", "mdx", "csv", "json", "yaml", "yml", "xml", "html", "htm", "pdf", "docx"] + + +def is_hidden(path: Path) -> bool: + return path.name.startswith(".") + + +def retrieve_file_paths( + path: str, + load_hidden: bool, + recursive: bool, + depth: int, + types: List[str] = TEXT_FILE_TYPES, +) -> List[str]: + path_obj = Path(path) + if not path_obj.exists() or not path_obj.is_dir(): + raise ValueError(f"Path {path} must exist and be a directory.") + + def match_types(p: Path) -> bool: + return any(p.suffix == f".{t}" for t in types) if types else True + + def is_not_hidden(p: Path) -> bool: + return not is_hidden(p) or load_hidden + + def walk_level(directory: Path, max_depth: int): + directory = directory.resolve() + prefix_length = len(directory.parts) + for p in directory.rglob("*" if recursive else "[!.]*"): + if len(p.parts) - prefix_length <= max_depth: + yield p + + glob = "**/*" if recursive else "*" + paths = walk_level(path_obj, depth) if depth else path_obj.glob(glob) + file_paths = [Text(p) for p in paths if p.is_file() and match_types(p) and is_not_hidden(p)] + + return file_paths + + +def partition_file_to_record(file_path: str, silent_errors: bool) -> Optional[Record]: + # Use the partition function to load the file + from unstructured.partition.auto import partition # type: ignore + + try: + elements = partition(file_path) + except Exception as e: + if not silent_errors: + raise ValueError(f"Error loading file {file_path}: {e}") from e + return None + + # Create a Record + text = "\n\n".join([Text(el) for el in elements]) + metadata = elements.metadata if hasattr(elements, "metadata") else {} + metadata["file_path"] = file_path + record = Record(text=text, data=metadata) + return record + + +def read_text_file(file_path: str) -> str: + with open(file_path, "r") as f: + return f.read() + + +def read_docx_file(file_path: str) -> str: + from docx import Document # type: ignore + + doc = Document(file_path) + return "\n\n".join([p.text for p in doc.paragraphs]) + + +def parse_pdf_to_text(file_path: str) -> str: + from pypdf import PdfReader # type: ignore + + with open(file_path, "rb") as f: + reader = PdfReader(f) + return "\n\n".join([page.extract_text() for page in reader.pages]) + + +def parse_text_file_to_record(file_path: str, silent_errors: bool) -> Optional[Record]: + try: + if file_path.endswith(".pdf"): + text = parse_pdf_to_text(file_path) + elif file_path.endswith(".docx"): + text = read_docx_file(file_path) + else: + text = read_text_file(file_path) + # if file is json, yaml, or xml, we can parse it + if file_path.endswith(".json"): + text = json.loads(text) + elif file_path.endswith(".yaml") or file_path.endswith(".yml"): + text = yaml.safe_load(text) + elif file_path.endswith(".xml"): + xml_element = ET.fromstring(text) + text = ET.tostring(xml_element, encoding="unicode") + except Exception as e: + if not silent_errors: + raise ValueError(f"Error loading file {file_path}: {e}") from e + return None + + record = Record(data={"file_path": file_path, "text": text}) + return record + + +def get_elements( + file_paths: List[str], + silent_errors: bool, + max_concurrency: int, + use_multithreading: bool, +) -> List[Optional[Record]]: + if use_multithreading: + records = parallel_load_records(file_paths, silent_errors, max_concurrency) + else: + records = [partition_file_to_record(file_path, silent_errors) for file_path in file_paths] + records = list(filter(None, records)) + return records + + +def parallel_load_records( + file_paths: List[str], + silent_errors: bool, + max_concurrency: int, + load_function: Callable = parse_text_file_to_record, +) -> List[Optional[Record]]: + with futures.ThreadPoolExecutor(max_workers=max_concurrency) as executor: + loaded_files = executor.map( + lambda file_path: load_function(file_path, silent_errors), + file_paths, + ) + # loaded_files is an iterator, so we need to convert it to a list + return list(loaded_files) diff --git a/src/backend/langflow/interface/retrievers/__init__.py b/src/backend/base/langflow/base/io/__init__.py similarity index 100% rename from src/backend/langflow/interface/retrievers/__init__.py rename to src/backend/base/langflow/base/io/__init__.py diff --git a/src/backend/base/langflow/base/io/chat.py b/src/backend/base/langflow/base/io/chat.py new file mode 100644 index 000000000..eb9787a79 --- /dev/null +++ b/src/backend/base/langflow/base/io/chat.py @@ -0,0 +1,118 @@ +import warnings +from typing import Optional, Union + +from langflow.field_typing import Text +from langflow.helpers.record import records_to_text +from langflow.interface.custom.custom_component import CustomComponent +from langflow.memory import add_messages +from langflow.schema import Record + + +class ChatComponent(CustomComponent): + display_name = "Chat Component" + description = "Use as base for chat components." + + def build_config(self): + return { + "input_value": { + "input_types": ["Text"], + "display_name": "Message", + "multiline": True, + }, + "sender": { + "options": ["Machine", "User"], + "display_name": "Sender Type", + "advanced": True, + }, + "sender_name": {"display_name": "Sender Name"}, + "session_id": { + "display_name": "Session ID", + "info": "If provided, the message will be stored in the memory.", + "advanced": True, + }, + "return_record": { + "display_name": "Return Record", + "info": "Return the message as a record containing the sender, sender_name, and session_id.", + "advanced": True, + }, + "record_template": { + "display_name": "Record Template", + "multiline": True, + "info": "In case of Message being a Record, this template will be used to convert it to text.", + "advanced": True, + }, + } + + def store_message( + self, + message: Union[str, Text, Record], + session_id: Optional[str] = None, + sender: Optional[str] = None, + sender_name: Optional[str] = None, + ) -> list[Record]: + if not message: + warnings.warn("No message provided.") + return [] + + if not session_id or not sender or not sender_name: + raise ValueError("All of session_id, sender, and sender_name must be provided.") + if isinstance(message, Record): + record = message + record.data.update( + { + "session_id": session_id, + "sender": sender, + "sender_name": sender_name, + } + ) + else: + record = Record( + data={ + "text": message, + "session_id": session_id, + "sender": sender, + "sender_name": sender_name, + }, + ) + + self.status = record + records = add_messages([record]) + return records[0] + + def build( + self, + sender: Optional[str] = "User", + sender_name: Optional[str] = "User", + input_value: Optional[Union[str, Record]] = None, + session_id: Optional[str] = None, + return_record: Optional[bool] = False, + record_template: str = "Text: {text}\nData: {data}", + ) -> Union[Text, Record]: + input_value_record: Optional[Record] = None + if return_record: + if isinstance(input_value, Record): + # Update the data of the record + input_value.data["sender"] = sender + input_value.data["sender_name"] = sender_name + input_value.data["session_id"] = session_id + else: + input_value_record = Record( + text=input_value, + data={ + "sender": sender, + "sender_name": sender_name, + "session_id": session_id, + }, + ) + elif isinstance(input_value, Record): + input_value = records_to_text(template=record_template, records=input_value) + if not input_value: + input_value = "" + if return_record and input_value_record: + result: Union[Text, Record] = input_value_record + else: + result = input_value + self.status = result + if session_id and isinstance(result, (Record, str)): + self.store_message(result, session_id, sender, sender_name) + return result diff --git a/src/backend/base/langflow/base/io/text.py b/src/backend/base/langflow/base/io/text.py new file mode 100644 index 000000000..5974e7d13 --- /dev/null +++ b/src/backend/base/langflow/base/io/text.py @@ -0,0 +1,42 @@ +from typing import Optional + +from langflow.field_typing import Text +from langflow.helpers.record import records_to_text +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema.schema import Record + + +class TextComponent(CustomComponent): + display_name = "Text Component" + description = "Used to pass text to the next component." + + def build_config(self): + return { + "input_value": { + "display_name": "Value", + "input_types": ["Text", "Record"], + "info": "Text or Record to be passed.", + }, + "record_template": { + "display_name": "Record Template", + "multiline": True, + "info": "Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.", + "advanced": True, + }, + } + + def build( + self, + input_value: Optional[Text] = "", + record_template: Optional[str] = "{text}", + ) -> Text: + if isinstance(input_value, Record): + if record_template == "": + # it should be dynamically set to the Record's .text_key value + # meaning, if text_key = "bacon", then record_template = "{bacon}" + record_template = "{" + input_value.text_key + "}" + input_value = records_to_text(template=record_template, records=input_value) + self.status = input_value + if not input_value: + input_value = "" + return input_value diff --git a/src/backend/base/langflow/base/models/__init__.py b/src/backend/base/langflow/base/models/__init__.py new file mode 100644 index 000000000..921f10336 --- /dev/null +++ b/src/backend/base/langflow/base/models/__init__.py @@ -0,0 +1,3 @@ +from .model import LCModelComponent + +__all__ = ["LCModelComponent"] diff --git a/src/backend/base/langflow/base/models/model.py b/src/backend/base/langflow/base/models/model.py new file mode 100644 index 000000000..b8ef38e07 --- /dev/null +++ b/src/backend/base/langflow/base/models/model.py @@ -0,0 +1,50 @@ +from typing import Optional, Union + +from langchain_core.language_models.chat_models import BaseChatModel +from langchain_core.language_models.llms import LLM +from langchain_core.messages import HumanMessage, SystemMessage + +from langflow.custom import CustomComponent + + +class LCModelComponent(CustomComponent): + display_name: str = "Model Name" + description: str = "Model Description" + + def get_result(self, runnable: LLM, stream: bool, input_value: str): + """ + Retrieves the result from the output of a Runnable object. + + Args: + output (Runnable): The output object to retrieve the result from. + stream (bool): Indicates whether to use streaming or invocation mode. + input_value (str): The input value to pass to the output object. + + Returns: + The result obtained from the output object. + """ + if stream: + result = runnable.stream(input_value) + else: + message = runnable.invoke(input_value) + result = message.content if hasattr(message, "content") else message + self.status = result + return result + + def get_chat_result( + self, runnable: BaseChatModel, stream: bool, input_value: str, system_message: Optional[str] = None + ): + messages: list[Union[HumanMessage, SystemMessage]] = [] + if not input_value and not system_message: + raise ValueError("The message you want to send to the model is empty.") + if system_message: + messages.append(SystemMessage(content=system_message)) + if input_value: + messages.append(HumanMessage(content=input_value)) + if stream: + return runnable.stream(messages) + else: + message = runnable.invoke(messages) + result = message.content + self.status = result + return result diff --git a/src/backend/langflow/interface/toolkits/__init__.py b/src/backend/base/langflow/base/prompts/__init__.py similarity index 100% rename from src/backend/langflow/interface/toolkits/__init__.py rename to src/backend/base/langflow/base/prompts/__init__.py diff --git a/src/backend/base/langflow/base/prompts/utils.py b/src/backend/base/langflow/base/prompts/utils.py new file mode 100644 index 000000000..ff4cf5079 --- /dev/null +++ b/src/backend/base/langflow/base/prompts/utils.py @@ -0,0 +1,137 @@ +from fastapi import HTTPException +from langchain.prompts import PromptTemplate +from langchain_core.documents import Document +from loguru import logger + +from langflow.api.v1.base import INVALID_NAMES, check_input_variables +from langflow.interface.utils import extract_input_variables_from_prompt +from langflow.schema import Record +from langflow.template.field.prompt import DefaultPromptField + + +def dict_values_to_string(d: dict) -> dict: + """ + Converts the values of a dictionary to strings. + + Args: + d (dict): The dictionary whose values need to be converted. + + Returns: + dict: The dictionary with values converted to strings. + """ + # Do something similar to the above + for key, value in d.items(): + # it could be a list of records or documents or strings + if isinstance(value, list): + for i, item in enumerate(value): + if isinstance(item, Record): + d[key][i] = record_to_string(item) + elif isinstance(item, Document): + d[key][i] = document_to_string(item) + elif isinstance(value, Record): + d[key] = record_to_string(value) + elif isinstance(value, Document): + d[key] = document_to_string(value) + return d + + +def record_to_string(record: Record) -> str: + """ + Convert a record to a string. + + Args: + record (Record): The record to convert. + + Returns: + str: The record as a string. + """ + return record.get_text() + + +def document_to_string(document: Document) -> str: + """ + Convert a document to a string. + + Args: + document (Document): The document to convert. + + Returns: + str: The document as a string. + """ + return document.page_content + + +def validate_prompt(prompt_template: str, silent_errors: bool = False) -> list[str]: + input_variables = extract_input_variables_from_prompt(prompt_template) + + # Check if there are invalid characters in the input_variables + input_variables = check_input_variables(input_variables) + if any(var in INVALID_NAMES for var in input_variables): + raise ValueError(f"Invalid input variables. None of the variables can be named {', '.join(input_variables)}. ") + + try: + PromptTemplate(template=prompt_template, input_variables=input_variables) + except Exception as exc: + logger.error(f"Invalid prompt: {exc}") + if not silent_errors: + raise ValueError(f"Invalid prompt: {exc}") from exc + + return input_variables + + +def get_old_custom_fields(custom_fields, name): + try: + if len(custom_fields) == 1 and name == "": + # If there is only one custom field and the name is empty string + # then we are dealing with the first prompt request after the node was created + name = list(custom_fields.keys())[0] + + old_custom_fields = custom_fields[name] + if not old_custom_fields: + old_custom_fields = [] + + old_custom_fields = old_custom_fields.copy() + except KeyError: + old_custom_fields = [] + custom_fields[name] = [] + return old_custom_fields + + +def add_new_variables_to_template(input_variables, custom_fields, template, name): + for variable in input_variables: + try: + template_field = DefaultPromptField(name=variable, display_name=variable) + if variable in template: + # Set the new field with the old value + template_field.value = template[variable]["value"] + + template[variable] = template_field.to_dict() + + # Check if variable is not already in the list before appending + if variable not in custom_fields[name]: + custom_fields[name].append(variable) + + except Exception as exc: + logger.exception(exc) + raise HTTPException(status_code=500, detail=str(exc)) from exc + + +def remove_old_variables_from_template(old_custom_fields, input_variables, custom_fields, template, name): + for variable in old_custom_fields: + if variable not in input_variables: + try: + # Remove the variable from custom_fields associated with the given name + if variable in custom_fields[name]: + custom_fields[name].remove(variable) + + # Remove the variable from the template + template.pop(variable, None) + + except Exception as exc: + logger.exception(exc) + raise HTTPException(status_code=500, detail=str(exc)) from exc + + +def update_input_variables_field(input_variables, template): + if "input_variables" in template: + template["input_variables"]["value"] = input_variables diff --git a/src/backend/base/langflow/components/__init__.py b/src/backend/base/langflow/components/__init__.py new file mode 100644 index 000000000..fdd1144c9 --- /dev/null +++ b/src/backend/base/langflow/components/__init__.py @@ -0,0 +1,17 @@ +__all__ = [ + "agents", + "chains", + "documentloaders", + "embeddings", + "experimental", + "inputs", + "memories", + "model_specs", + "outputs", + "retrievers", + "textsplitters", + "toolkits", + "tools", + "vectorsearch", + "vectorstores", +] diff --git a/src/backend/langflow/components/agents/AgentInitializer.py b/src/backend/base/langflow/components/agents/AgentInitializer.py similarity index 96% rename from src/backend/langflow/components/agents/AgentInitializer.py rename to src/backend/base/langflow/components/agents/AgentInitializer.py index 3d936df8a..d1f09d5cf 100644 --- a/src/backend/langflow/components/agents/AgentInitializer.py +++ b/src/backend/base/langflow/components/agents/AgentInitializer.py @@ -1,8 +1,9 @@ from typing import Callable, List, Optional, Union from langchain.agents import AgentExecutor, AgentType, initialize_agent, types -from langflow import CustomComponent + from langflow.field_typing import BaseChatMemory, BaseLanguageModel, Tool +from langflow.interface.custom.custom_component import CustomComponent class AgentInitializerComponent(CustomComponent): diff --git a/src/backend/base/langflow/components/agents/CSVAgent.py b/src/backend/base/langflow/components/agents/CSVAgent.py new file mode 100644 index 000000000..57774568f --- /dev/null +++ b/src/backend/base/langflow/components/agents/CSVAgent.py @@ -0,0 +1,34 @@ +from langchain_experimental.agents.agent_toolkits.csv.base import create_csv_agent + +from langflow.custom import CustomComponent +from langflow.field_typing import AgentExecutor, BaseLanguageModel + + +class CSVAgentComponent(CustomComponent): + display_name = "CSVAgent" + description = "Construct a CSV agent from a CSV and tools." + documentation = "https://python.langchain.com/docs/modules/agents/toolkits/csv" + + def build_config(self): + return { + "llm": {"display_name": "LLM", "type": BaseLanguageModel}, + "path": {"display_name": "Path", "field_type": "file", "suffixes": [".csv"], "file_types": [".csv"]}, + "handle_parsing_errors": {"display_name": "Handle Parse Errors", "advanced": True}, + "agent_type": { + "display_name": "Agent Type", + "options": ["zero-shot-react-description", "openai-functions", "openai-tools"], + "advanced": True, + }, + } + + def build( + self, llm: BaseLanguageModel, path: str, handle_parsing_errors: bool = True, agent_type: str = "openai-tools" + ) -> AgentExecutor: + # Instantiate and return the CSV agent class with the provided llm and path + return create_csv_agent( + llm=llm, + path=path, + agent_type=agent_type, + verbose=True, + agent_executor_kwargs=dict(handle_parsing_errors=handle_parsing_errors), + ) diff --git a/src/backend/langflow/components/agents/JsonAgent.py b/src/backend/base/langflow/components/agents/JsonAgent.py similarity index 90% rename from src/backend/langflow/components/agents/JsonAgent.py rename to src/backend/base/langflow/components/agents/JsonAgent.py index 0197b9210..5fa342417 100644 --- a/src/backend/langflow/components/agents/JsonAgent.py +++ b/src/backend/base/langflow/components/agents/JsonAgent.py @@ -1,9 +1,10 @@ -from langflow import CustomComponent from langchain.agents import AgentExecutor, create_json_agent +from langchain_community.agent_toolkits.json.toolkit import JsonToolkit + from langflow.field_typing import ( BaseLanguageModel, ) -from langchain_community.agent_toolkits.json.toolkit import JsonToolkit +from langflow.interface.custom.custom_component import CustomComponent class JsonAgentComponent(CustomComponent): diff --git a/src/backend/langflow/components/agents/OpenAIConversationalAgent.py b/src/backend/base/langflow/components/agents/OpenAIConversationalAgent.py similarity index 95% rename from src/backend/langflow/components/agents/OpenAIConversationalAgent.py rename to src/backend/base/langflow/components/agents/OpenAIConversationalAgent.py index 5dfb53387..0edf8ea55 100644 --- a/src/backend/langflow/components/agents/OpenAIConversationalAgent.py +++ b/src/backend/base/langflow/components/agents/OpenAIConversationalAgent.py @@ -9,13 +9,15 @@ from langchain.prompts.chat import MessagesPlaceholder from langchain.schema.memory import BaseMemory from langchain.tools import Tool from langchain_community.chat_models import ChatOpenAI -from langflow import CustomComponent + from langflow.field_typing.range_spec import RangeSpec +from langflow.interface.custom.custom_component import CustomComponent class ConversationalAgent(CustomComponent): display_name: str = "OpenAI Conversational Agent" description: str = "Conversational Agent that can use OpenAI's function calling API" + icon = "OpenAI" def build_config(self): openai_function_models = [ @@ -40,7 +42,7 @@ class ConversationalAgent(CustomComponent): "temperature": { "display_name": "Temperature", "value": 0.2, - "range_spec": RangeSpec(min=0, max=2, step=0.1), + "rangeSpec": RangeSpec(min=0, max=2, step=0.1), }, } diff --git a/src/backend/langflow/components/agents/SQLAgent.py b/src/backend/base/langflow/components/agents/SQLAgent.py similarity index 90% rename from src/backend/langflow/components/agents/SQLAgent.py rename to src/backend/base/langflow/components/agents/SQLAgent.py index 42b1b48f3..68f65d18f 100644 --- a/src/backend/langflow/components/agents/SQLAgent.py +++ b/src/backend/base/langflow/components/agents/SQLAgent.py @@ -1,10 +1,12 @@ -from langflow import CustomComponent -from typing import Union, Callable +from typing import Callable, Union + from langchain.agents import AgentExecutor -from langflow.field_typing import BaseLanguageModel -from langchain_community.agent_toolkits.sql.base import create_sql_agent from langchain.sql_database import SQLDatabase from langchain_community.agent_toolkits import SQLDatabaseToolkit +from langchain_community.agent_toolkits.sql.base import create_sql_agent + +from langflow.field_typing import BaseLanguageModel +from langflow.interface.custom.custom_component import CustomComponent class SQLAgentComponent(CustomComponent): diff --git a/src/backend/langflow/components/agents/VectorStoreAgent.py b/src/backend/base/langflow/components/agents/VectorStoreAgent.py similarity index 87% rename from src/backend/langflow/components/agents/VectorStoreAgent.py rename to src/backend/base/langflow/components/agents/VectorStoreAgent.py index b70ea4d59..095f9da41 100644 --- a/src/backend/langflow/components/agents/VectorStoreAgent.py +++ b/src/backend/base/langflow/components/agents/VectorStoreAgent.py @@ -1,8 +1,10 @@ -from langflow import CustomComponent +from typing import Callable, Union + from langchain.agents import AgentExecutor, create_vectorstore_agent from langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreToolkit -from typing import Union, Callable + from langflow.field_typing import BaseLanguageModel +from langflow.interface.custom.custom_component import CustomComponent class VectorStoreAgentComponent(CustomComponent): diff --git a/src/backend/langflow/components/agents/VectorStoreRouterAgent.py b/src/backend/base/langflow/components/agents/VectorStoreRouterAgent.py similarity index 91% rename from src/backend/langflow/components/agents/VectorStoreRouterAgent.py rename to src/backend/base/langflow/components/agents/VectorStoreRouterAgent.py index 3174d9513..514a9767c 100644 --- a/src/backend/langflow/components/agents/VectorStoreRouterAgent.py +++ b/src/backend/base/langflow/components/agents/VectorStoreRouterAgent.py @@ -1,9 +1,11 @@ -from langflow import CustomComponent -from langchain_core.language_models.base import BaseLanguageModel -from langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreRouterToolkit -from langchain.agents import create_vectorstore_router_agent from typing import Callable +from langchain.agents import create_vectorstore_router_agent +from langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreRouterToolkit +from langchain_core.language_models.base import BaseLanguageModel + +from langflow.interface.custom.custom_component import CustomComponent + class VectorStoreRouterAgentComponent(CustomComponent): display_name = "VectorStoreRouterAgent" diff --git a/src/backend/base/langflow/components/agents/XMLAgent.py b/src/backend/base/langflow/components/agents/XMLAgent.py new file mode 100644 index 000000000..687bfff6f --- /dev/null +++ b/src/backend/base/langflow/components/agents/XMLAgent.py @@ -0,0 +1,89 @@ +from typing import List, Optional + +from langchain.agents import create_xml_agent +from langchain_core.prompts import PromptTemplate + +from langflow.base.agents.agent import LCAgentComponent +from langflow.field_typing import BaseLLM, BaseMemory, Text, Tool + + +class XMLAgentComponent(LCAgentComponent): + display_name = "XMLAgent" + description = "Construct an XML agent from an LLM and tools." + + def build_config(self): + return { + "llm": {"display_name": "LLM"}, + "tools": {"display_name": "Tools"}, + "prompt": { + "display_name": "Prompt", + "multiline": True, + "info": "This prompt must contain 'tools' and 'agent_scratchpad' keys.", + "value": """You are a helpful assistant. Help the user answer any questions. + + You have access to the following tools: + + {tools} + + In order to use a tool, you can use and tags. You will then get back a response in the form + For example, if you have a tool called 'search' that could run a google search, in order to search for the weather in SF you would respond: + + searchweather in SF + 64 degrees + + When you are done, respond with a final answer between . For example: + + The weather in SF is 64 degrees + + Begin! + + Previous Conversation: + {chat_history} + + Question: {input} + {agent_scratchpad}""", + }, + "tool_template": { + "display_name": "Tool Template", + "info": "Template for rendering tools in the prompt. Tools have 'name' and 'description' keys.", + "advanced": True, + }, + "handle_parsing_errors": { + "display_name": "Handle Parsing Errors", + "info": "If True, the agent will handle parsing errors. If False, the agent will raise an error.", + "advanced": True, + }, + "memory": { + "display_name": "Memory", + "info": "Memory to use for the agent.", + }, + "input_value": { + "display_name": "Inputs", + "info": "Input text to pass to the agent.", + }, + } + + async def build( + self, + input_value: str, + llm: BaseLLM, + tools: List[Tool], + prompt: str, + memory: Optional[BaseMemory] = None, + tool_template: str = "{name}: {description}", + handle_parsing_errors: bool = True, + ) -> Text: + if "input" not in prompt: + raise ValueError("Prompt must contain 'input' key.") + + def render_tool_description(tools): + return "\n".join( + [tool_template.format(name=tool.name, description=tool.description, args=tool.args) for tool in tools] + ) + + prompt_template = PromptTemplate.from_template(prompt) + input_variables = prompt_template.input_variables + agent = create_xml_agent(llm, tools, prompt_template, tools_renderer=render_tool_description) + result = await self.run_agent(agent, input_value, input_variables, tools, memory, handle_parsing_errors) + self.status = result + return result diff --git a/src/backend/base/langflow/components/agents/__init__.py b/src/backend/base/langflow/components/agents/__init__.py new file mode 100644 index 000000000..f2a118b58 --- /dev/null +++ b/src/backend/base/langflow/components/agents/__init__.py @@ -0,0 +1,19 @@ +from .AgentInitializer import AgentInitializerComponent +from .CSVAgent import CSVAgentComponent +from .JsonAgent import JsonAgentComponent +from .OpenAIConversationalAgent import ConversationalAgent +from .SQLAgent import SQLAgentComponent +from .VectorStoreAgent import VectorStoreAgentComponent +from .VectorStoreRouterAgent import VectorStoreRouterAgentComponent +from .XMLAgent import XMLAgentComponent + +__all__ = [ + "AgentInitializerComponent", + "CSVAgentComponent", + "JsonAgentComponent", + "ConversationalAgent", + "SQLAgentComponent", + "VectorStoreAgentComponent", + "VectorStoreRouterAgentComponent", + "XMLAgentComponent", +] diff --git a/src/backend/base/langflow/components/chains/ConversationChain.py b/src/backend/base/langflow/components/chains/ConversationChain.py new file mode 100644 index 000000000..2b8dd09a3 --- /dev/null +++ b/src/backend/base/langflow/components/chains/ConversationChain.py @@ -0,0 +1,46 @@ +from typing import Optional + +from langchain.chains import ConversationChain + +from langflow.field_typing import BaseLanguageModel, BaseMemory, Text +from langflow.interface.custom.custom_component import CustomComponent + + +class ConversationChainComponent(CustomComponent): + display_name = "ConversationChain" + description = "Chain to have a conversation and load context from memory." + + def build_config(self): + return { + "prompt": {"display_name": "Prompt"}, + "llm": {"display_name": "LLM"}, + "memory": { + "display_name": "Memory", + "info": "Memory to load context from. If none is provided, a ConversationBufferMemory will be used.", + }, + "input_value": { + "display_name": "Input Value", + "info": "The input value to pass to the chain.", + }, + } + + def build( + self, + input_value: Text, + llm: BaseLanguageModel, + memory: Optional[BaseMemory] = None, + ) -> Text: + if memory is None: + chain = ConversationChain(llm=llm) + else: + chain = ConversationChain(llm=llm, memory=memory) + result = chain.invoke({"input": input_value}) + if isinstance(result, dict): + result = result.get(chain.output_key, "") # type: ignore + + elif isinstance(result, str): + result = result + else: + result = result.get("response") + self.status = result + return str(result) diff --git a/src/backend/langflow/components/chains/LLMChain.py b/src/backend/base/langflow/components/chains/LLMChain.py similarity index 53% rename from src/backend/langflow/components/chains/LLMChain.py rename to src/backend/base/langflow/components/chains/LLMChain.py index c6efd04c7..9c2b3eae2 100644 --- a/src/backend/langflow/components/chains/LLMChain.py +++ b/src/backend/base/langflow/components/chains/LLMChain.py @@ -1,14 +1,9 @@ -from typing import Callable, Optional, Union +from typing import Optional from langchain.chains import LLMChain -from langflow import CustomComponent -from langflow.field_typing import ( - BaseLanguageModel, - BaseMemory, - BasePromptTemplate, - Chain, -) +from langflow.field_typing import BaseLanguageModel, BaseMemory, BasePromptTemplate, Text +from langflow.interface.custom.custom_component import CustomComponent class LLMChainComponent(CustomComponent): @@ -20,7 +15,6 @@ class LLMChainComponent(CustomComponent): "prompt": {"display_name": "Prompt"}, "llm": {"display_name": "LLM"}, "memory": {"display_name": "Memory"}, - "code": {"show": False}, } def build( @@ -28,5 +22,10 @@ class LLMChainComponent(CustomComponent): prompt: BasePromptTemplate, llm: BaseLanguageModel, memory: Optional[BaseMemory] = None, - ) -> Union[Chain, Callable, LLMChain]: - return LLMChain(prompt=prompt, llm=llm, memory=memory) + ) -> Text: + runnable = LLMChain(prompt=prompt, llm=llm, memory=memory) + result_dict = runnable.invoke({}) + output_key = runnable.output_key + result = result_dict[output_key] + self.status = result + return result diff --git a/src/backend/base/langflow/components/chains/LLMCheckerChain.py b/src/backend/base/langflow/components/chains/LLMCheckerChain.py new file mode 100644 index 000000000..04e6fe67d --- /dev/null +++ b/src/backend/base/langflow/components/chains/LLMCheckerChain.py @@ -0,0 +1,31 @@ +from langchain.chains import LLMCheckerChain + +from langflow.field_typing import BaseLanguageModel, Text +from langflow.interface.custom.custom_component import CustomComponent + + +class LLMCheckerChainComponent(CustomComponent): + display_name = "LLMCheckerChain" + description = "" + documentation = "https://python.langchain.com/docs/modules/chains/additional/llm_checker" + + def build_config(self): + return { + "llm": {"display_name": "LLM"}, + "input_value": { + "display_name": "Input Value", + "info": "The input value to pass to the chain.", + }, + } + + def build( + self, + input_value: Text, + llm: BaseLanguageModel, + ) -> Text: + chain = LLMCheckerChain.from_llm(llm=llm) + response = chain.invoke({chain.input_key: input_value}) + result = response.get(chain.output_key, "") + result_str = Text(result) + self.status = result_str + return result_str diff --git a/src/backend/langflow/components/chains/LLMMathChain.py b/src/backend/base/langflow/components/chains/LLMMathChain.py similarity index 56% rename from src/backend/langflow/components/chains/LLMMathChain.py rename to src/backend/base/langflow/components/chains/LLMMathChain.py index 28f430e6d..0b7374da6 100644 --- a/src/backend/langflow/components/chains/LLMMathChain.py +++ b/src/backend/base/langflow/components/chains/LLMMathChain.py @@ -1,9 +1,9 @@ -from typing import Callable, Optional, Union +from typing import Optional from langchain.chains import LLMChain, LLMMathChain -from langflow import CustomComponent -from langflow.field_typing import BaseLanguageModel, BaseMemory, Chain +from langflow.field_typing import BaseLanguageModel, BaseMemory, Text +from langflow.interface.custom.custom_component import CustomComponent class LLMMathChainComponent(CustomComponent): @@ -18,14 +18,30 @@ class LLMMathChainComponent(CustomComponent): "memory": {"display_name": "Memory"}, "input_key": {"display_name": "Input Key"}, "output_key": {"display_name": "Output Key"}, + "input_value": { + "display_name": "Input Value", + "info": "The input value to pass to the chain.", + }, } def build( self, + input_value: Text, llm: BaseLanguageModel, llm_chain: LLMChain, input_key: str = "question", output_key: str = "answer", memory: Optional[BaseMemory] = None, - ) -> Union[LLMMathChain, Callable, Chain]: - return LLMMathChain(llm=llm, llm_chain=llm_chain, input_key=input_key, output_key=output_key, memory=memory) + ) -> Text: + chain = LLMMathChain( + llm=llm, + llm_chain=llm_chain, + input_key=input_key, + output_key=output_key, + memory=memory, + ) + response = chain.invoke({input_key: input_value}) + result = response.get(output_key) + result_str = Text(result) + self.status = result_str + return result_str diff --git a/src/backend/base/langflow/components/chains/RetrievalQA.py b/src/backend/base/langflow/components/chains/RetrievalQA.py new file mode 100644 index 000000000..7b6ba49e4 --- /dev/null +++ b/src/backend/base/langflow/components/chains/RetrievalQA.py @@ -0,0 +1,68 @@ +from typing import Optional + +from langchain.chains.retrieval_qa.base import RetrievalQA +from langchain_core.documents import Document + +from langflow.field_typing import BaseLanguageModel, BaseMemory, BaseRetriever, Text +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema.schema import Record + + +class RetrievalQAComponent(CustomComponent): + display_name = "Retrieval QA" + description = "Chain for question-answering against an index." + + def build_config(self): + return { + "llm": {"display_name": "LLM"}, + "chain_type": {"display_name": "Chain Type", "options": ["Stuff", "Map Reduce", "Refine", "Map Rerank"]}, + "retriever": {"display_name": "Retriever"}, + "memory": {"display_name": "Memory", "required": False}, + "input_key": {"display_name": "Input Key", "advanced": True}, + "output_key": {"display_name": "Output Key", "advanced": True}, + "return_source_documents": {"display_name": "Return Source Documents"}, + "input_value": { + "display_name": "Input", + "input_types": ["Record", "Document"], + }, + } + + def build( + self, + llm: BaseLanguageModel, + chain_type: str, + retriever: BaseRetriever, + input_value: str = "", + memory: Optional[BaseMemory] = None, + input_key: str = "query", + output_key: str = "result", + return_source_documents: bool = True, + ) -> Text: + chain_type = chain_type.lower().replace(" ", "_") + runnable = RetrievalQA.from_chain_type( + llm=llm, + chain_type=chain_type, + retriever=retriever, + memory=memory, + input_key=input_key, + output_key=output_key, + return_source_documents=return_source_documents, + ) + if isinstance(input_value, Document): + input_value = input_value.page_content + if isinstance(input_value, Record): + input_value = input_value.get_text() + self.status = runnable + result = runnable.invoke({input_key: input_value}) + result = result.content if hasattr(result, "content") else result + # Result is a dict with keys "query", "result" and "source_documents" + # for now we just return the result + records = self.to_records(result.get("source_documents")) + references_str = "" + if return_source_documents: + references_str = self.create_references_from_records(records) + result_str = result.get("result", "") + + final_result = "\n".join([Text(result_str), references_str]) + self.status = final_result + return final_result # OK diff --git a/src/backend/base/langflow/components/chains/RetrievalQAWithSourcesChain.py b/src/backend/base/langflow/components/chains/RetrievalQAWithSourcesChain.py new file mode 100644 index 000000000..75a9131f5 --- /dev/null +++ b/src/backend/base/langflow/components/chains/RetrievalQAWithSourcesChain.py @@ -0,0 +1,63 @@ +from typing import Optional + +from langchain.chains import RetrievalQAWithSourcesChain +from langchain_core.documents import Document + +from langflow.field_typing import BaseLanguageModel, BaseMemory, BaseRetriever, Text +from langflow.interface.custom.custom_component import CustomComponent + + +class RetrievalQAWithSourcesChainComponent(CustomComponent): + display_name = "RetrievalQAWithSourcesChain" + description = "Question-answering with sources over an index." + + def build_config(self): + return { + "llm": {"display_name": "LLM"}, + "chain_type": { + "display_name": "Chain Type", + "options": ["Stuff", "Map Reduce", "Refine", "Map Rerank"], + "info": "The type of chain to use to combined Documents.", + }, + "memory": {"display_name": "Memory"}, + "return_source_documents": {"display_name": "Return Source Documents"}, + "retriever": {"display_name": "Retriever"}, + "input_value": { + "display_name": "Input Value", + "info": "The input value to pass to the chain.", + }, + } + + def build( + self, + input_value: Text, + retriever: BaseRetriever, + llm: BaseLanguageModel, + chain_type: str, + memory: Optional[BaseMemory] = None, + return_source_documents: Optional[bool] = True, + ) -> Text: + chain_type = chain_type.lower().replace(" ", "_") + runnable = RetrievalQAWithSourcesChain.from_chain_type( + llm=llm, + chain_type=chain_type, + memory=memory, + return_source_documents=return_source_documents, + retriever=retriever, + ) + if isinstance(input_value, Document): + input_value = input_value.page_content + self.status = runnable + input_key = runnable.input_keys[0] + result = runnable.invoke({input_key: input_value}) + result = result.content if hasattr(result, "content") else result + # Result is a dict with keys "query", "result" and "source_documents" + # for now we just return the result + records = self.to_records(result.get("source_documents")) + references_str = "" + if return_source_documents: + references_str = self.create_references_from_records(records) + result_str = Text(result.get("answer", "")) + final_result = "\n".join([result_str, references_str]) + self.status = final_result + return final_result diff --git a/src/backend/base/langflow/components/chains/SQLGenerator.py b/src/backend/base/langflow/components/chains/SQLGenerator.py new file mode 100644 index 000000000..3b111ba71 --- /dev/null +++ b/src/backend/base/langflow/components/chains/SQLGenerator.py @@ -0,0 +1,61 @@ +from typing import Optional + +from langchain.chains import create_sql_query_chain +from langchain_community.utilities.sql_database import SQLDatabase +from langchain_core.prompts import PromptTemplate +from langchain_core.runnables import Runnable + +from langflow.field_typing import BaseLanguageModel, Text +from langflow.interface.custom.custom_component import CustomComponent + + +class SQLGeneratorComponent(CustomComponent): + display_name = "Natural Language to SQL" + description = "Generate SQL from natural language." + + def build_config(self): + return { + "db": {"display_name": "Database"}, + "llm": {"display_name": "LLM"}, + "prompt": { + "display_name": "Prompt", + "info": "The prompt must contain `{question}`.", + }, + "top_k": { + "display_name": "Top K", + "info": "The number of results per select statement to return. If 0, no limit.", + }, + "input_value": { + "display_name": "Input Value", + "info": "The input value to pass to the chain.", + }, + } + + def build( + self, + input_value: Text, + db: SQLDatabase, + llm: BaseLanguageModel, + top_k: int = 5, + prompt: Optional[Text] = None, + ) -> Text: + if prompt: + prompt_template = PromptTemplate.from_template(template=prompt) + else: + prompt_template = None + + if top_k < 1: + raise ValueError("Top K must be greater than 0.") + + if not prompt_template: + sql_query_chain = create_sql_query_chain(llm=llm, db=db, k=top_k) + else: + # Check if {question} is in the prompt + if "{question}" not in prompt_template.template or "question" not in prompt_template.input_variables: + raise ValueError("Prompt must contain `{question}` to be used with Natural Language to SQL.") + sql_query_chain = create_sql_query_chain(llm=llm, db=db, prompt=prompt_template, k=top_k) + query_writer: Runnable = sql_query_chain | {"query": lambda x: x.replace("SQLQuery:", "").strip()} + response = query_writer.invoke({"question": input_value}) + query = response.get("query") + self.status = query + return query diff --git a/src/backend/base/langflow/components/chains/__init__.py b/src/backend/base/langflow/components/chains/__init__.py new file mode 100644 index 000000000..365a80eb6 --- /dev/null +++ b/src/backend/base/langflow/components/chains/__init__.py @@ -0,0 +1,17 @@ +from .ConversationChain import ConversationChainComponent +from .LLMChain import LLMChainComponent +from .LLMCheckerChain import LLMCheckerChainComponent +from .LLMMathChain import LLMMathChainComponent +from .RetrievalQA import RetrievalQAComponent +from .RetrievalQAWithSourcesChain import RetrievalQAWithSourcesChainComponent +from .SQLGenerator import SQLGeneratorComponent + +__all__ = [ + "ConversationChainComponent", + "LLMChainComponent", + "LLMCheckerChainComponent", + "LLMMathChainComponent", + "RetrievalQAComponent", + "RetrievalQAWithSourcesChainComponent", + "SQLGeneratorComponent", +] diff --git a/src/backend/base/langflow/components/data/APIRequest.py b/src/backend/base/langflow/components/data/APIRequest.py new file mode 100644 index 000000000..988fc0d4c --- /dev/null +++ b/src/backend/base/langflow/components/data/APIRequest.py @@ -0,0 +1,121 @@ +import asyncio +import json +from typing import List, Optional + +import httpx + +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema import Record + + +class APIRequest(CustomComponent): + display_name: str = "API Request" + description: str = "Make HTTP requests given one or more URLs." + output_types: list[str] = ["Record"] + documentation: str = "https://docs.langflow.org/components/utilities#api-request" + icon = "Globe" + + field_config = { + "urls": {"display_name": "URLs", "info": "URLs to make requests to."}, + "method": { + "display_name": "Method", + "info": "The HTTP method to use.", + "field_type": "str", + "options": ["GET", "POST", "PATCH", "PUT"], + "value": "GET", + }, + "headers": { + "display_name": "Headers", + "info": "The headers to send with the request.", + "input_types": ["Record"], + }, + "body": { + "display_name": "Body", + "info": "The body to send with the request (for POST, PATCH, PUT).", + "input_types": ["Record"], + }, + "timeout": { + "display_name": "Timeout", + "field_type": "int", + "info": "The timeout to use for the request.", + "value": 5, + }, + } + + async def make_request( + self, + client: httpx.AsyncClient, + method: str, + url: str, + headers: Optional[Record] = None, + body: Optional[Record] = None, + timeout: int = 5, + ) -> Record: + method = method.upper() + if method not in ["GET", "POST", "PATCH", "PUT", "DELETE"]: + raise ValueError(f"Unsupported method: {method}") + + data = body if body else None + payload = json.dumps(data) + try: + response = await client.request(method, url, headers=headers, content=payload, timeout=timeout) + try: + result = response.json() + except Exception: + result = response.text + return Record( + data={ + "source": url, + "headers": headers, + "status_code": response.status_code, + "result": result, + }, + ) + except httpx.TimeoutException: + return Record( + data={ + "source": url, + "headers": headers, + "status_code": 408, + "error": "Request timed out", + }, + ) + except Exception as exc: + return Record( + data={ + "source": url, + "headers": headers, + "status_code": 500, + "error": str(exc), + }, + ) + + async def build( + self, + method: str, + urls: List[str], + _headers: Optional[Record] = None, + body: Optional[Record] = None, + timeout: int = 5, + ) -> List[Record]: + if _headers is None: + headers = {} + else: + headers = _headers.data + + bodies = [] + if body: + if isinstance(body, list): + bodies = [b.data for b in body] + else: + bodies = [body.data] + + if len(urls) != len(bodies): + # add bodies with None + bodies += [None] * (len(urls) - len(bodies)) # type: ignore + async with httpx.AsyncClient() as client: + results = await asyncio.gather( + *[self.make_request(client, method, u, headers, rec, timeout) for u, rec in zip(urls, bodies)] + ) + self.status = results + return results diff --git a/src/backend/base/langflow/components/data/Directory.py b/src/backend/base/langflow/components/data/Directory.py new file mode 100644 index 000000000..87dc99287 --- /dev/null +++ b/src/backend/base/langflow/components/data/Directory.py @@ -0,0 +1,63 @@ +from typing import Any, Dict, List, Optional + +from langflow.base.data.utils import parallel_load_records, parse_text_file_to_record, retrieve_file_paths +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema import Record + + +class DirectoryComponent(CustomComponent): + display_name = "Directory" + description = "Recursively load files from a directory." + icon = "folder" + + def build_config(self) -> Dict[str, Any]: + return { + "path": {"display_name": "Path"}, + "types": { + "display_name": "Types", + "info": "File types to load. Leave empty to load all types.", + }, + "depth": {"display_name": "Depth", "info": "Depth to search for files."}, + "max_concurrency": {"display_name": "Max Concurrency", "advanced": True}, + "load_hidden": { + "display_name": "Load Hidden", + "advanced": True, + "info": "If true, hidden files will be loaded.", + }, + "recursive": { + "display_name": "Recursive", + "advanced": True, + "info": "If true, the search will be recursive.", + }, + "silent_errors": { + "display_name": "Silent Errors", + "advanced": True, + "info": "If true, errors will not raise an exception.", + }, + "use_multithreading": { + "display_name": "Use Multithreading", + "advanced": True, + }, + } + + def build( + self, + path: str, + depth: int = 0, + max_concurrency: int = 2, + load_hidden: bool = False, + recursive: bool = True, + silent_errors: bool = False, + use_multithreading: bool = True, + ) -> List[Optional[Record]]: + resolved_path = self.resolve_path(path) + file_paths = retrieve_file_paths(resolved_path, load_hidden, recursive, depth) + loaded_records = [] + + if use_multithreading: + loaded_records = parallel_load_records(file_paths, silent_errors, max_concurrency) + else: + loaded_records = [parse_text_file_to_record(file_path, silent_errors) for file_path in file_paths] + loaded_records = list(filter(None, loaded_records)) + self.status = loaded_records + return loaded_records diff --git a/src/backend/base/langflow/components/data/File.py b/src/backend/base/langflow/components/data/File.py new file mode 100644 index 000000000..70fe1dccc --- /dev/null +++ b/src/backend/base/langflow/components/data/File.py @@ -0,0 +1,48 @@ +from pathlib import Path +from typing import Any, Dict + +from langflow.base.data.utils import TEXT_FILE_TYPES, parse_text_file_to_record +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema import Record + + +class FileComponent(CustomComponent): + display_name = "File" + description = "A generic file loader." + icon = "file-text" + + def build_config(self) -> Dict[str, Any]: + return { + "path": { + "display_name": "Path", + "field_type": "file", + "file_types": TEXT_FILE_TYPES, + "info": f"Supported file types: {', '.join(TEXT_FILE_TYPES)}", + }, + "silent_errors": { + "display_name": "Silent Errors", + "advanced": True, + "info": "If true, errors will not raise an exception.", + }, + } + + def load_file(self, path: str, silent_errors: bool = False) -> Record: + resolved_path = self.resolve_path(path) + path_obj = Path(resolved_path) + extension = path_obj.suffix[1:].lower() + if extension == "doc": + raise ValueError("doc files are not supported. Please save as .docx") + if extension not in TEXT_FILE_TYPES: + raise ValueError(f"Unsupported file type: {extension}") + record = parse_text_file_to_record(resolved_path, silent_errors) + self.status = record if record else "No data" + return record or Record() + + def build( + self, + path: str, + silent_errors: bool = False, + ) -> Record: + record = self.load_file(path, silent_errors) + self.status = record + return record diff --git a/src/backend/base/langflow/components/data/URL.py b/src/backend/base/langflow/components/data/URL.py new file mode 100644 index 000000000..2b286e126 --- /dev/null +++ b/src/backend/base/langflow/components/data/URL.py @@ -0,0 +1,27 @@ +from typing import Any, Dict + +from langchain_community.document_loaders.web_base import WebBaseLoader + +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema import Record + + +class URLComponent(CustomComponent): + display_name = "URL" + description = "Fetch content from one or more URLs." + icon = "layout-template" + + def build_config(self) -> Dict[str, Any]: + return { + "urls": {"display_name": "URL"}, + } + + def build( + self, + urls: list[str], + ) -> list[Record]: + loader = WebBaseLoader(web_paths=urls) + docs = loader.load() + records = self.to_records(docs) + self.status = records + return records diff --git a/src/backend/base/langflow/components/data/__init__.py b/src/backend/base/langflow/components/data/__init__.py new file mode 100644 index 000000000..ca82e3eb8 --- /dev/null +++ b/src/backend/base/langflow/components/data/__init__.py @@ -0,0 +1,7 @@ +from .APIRequest import APIRequest +from .Directory import DirectoryComponent +from .File import FileComponent + +from .URL import URLComponent + +__all__ = ["APIRequest", "DirectoryComponent", "FileComponent", "URLComponent"] diff --git a/src/backend/langflow/interface/utilities/__init__.py b/src/backend/base/langflow/components/documentloaders/__init__.py similarity index 100% rename from src/backend/langflow/interface/utilities/__init__.py rename to src/backend/base/langflow/components/documentloaders/__init__.py diff --git a/src/backend/langflow/components/embeddings/AmazonBedrockEmbeddings.py b/src/backend/base/langflow/components/embeddings/AmazonBedrockEmbeddings.py similarity index 84% rename from src/backend/langflow/components/embeddings/AmazonBedrockEmbeddings.py rename to src/backend/base/langflow/components/embeddings/AmazonBedrockEmbeddings.py index 450e5ee3b..d4330d9e4 100644 --- a/src/backend/langflow/components/embeddings/AmazonBedrockEmbeddings.py +++ b/src/backend/base/langflow/components/embeddings/AmazonBedrockEmbeddings.py @@ -1,19 +1,15 @@ from typing import Optional -from langchain.embeddings import BedrockEmbeddings from langchain.embeddings.base import Embeddings -from langflow import CustomComponent +from langchain_community.embeddings import BedrockEmbeddings + +from langflow.interface.custom.custom_component import CustomComponent class AmazonBedrockEmeddingsComponent(CustomComponent): - """ - A custom component for implementing an Embeddings Model using Amazon Bedrock. - """ - display_name: str = "Amazon Bedrock Embeddings" - description: str = "Embeddings model from Amazon Bedrock." + description: str = "Generate embeddings using Amazon Bedrock models." documentation = "https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock" - beta = True def build_config(self): return { diff --git a/src/backend/langflow/components/embeddings/AzureOpenAIEmbeddings.py b/src/backend/base/langflow/components/embeddings/AzureOpenAIEmbeddings.py similarity index 90% rename from src/backend/langflow/components/embeddings/AzureOpenAIEmbeddings.py rename to src/backend/base/langflow/components/embeddings/AzureOpenAIEmbeddings.py index 09b03e17b..d8aec24cd 100644 --- a/src/backend/langflow/components/embeddings/AzureOpenAIEmbeddings.py +++ b/src/backend/base/langflow/components/embeddings/AzureOpenAIEmbeddings.py @@ -1,14 +1,15 @@ from langchain.embeddings.base import Embeddings from langchain_community.embeddings import AzureOpenAIEmbeddings -from langflow import CustomComponent +from langflow.interface.custom.custom_component import CustomComponent class AzureOpenAIEmbeddingsComponent(CustomComponent): - display_name: str = "AzureOpenAIEmbeddings" - description: str = "Embeddings model from Azure OpenAI." + display_name: str = "Azure OpenAI Embeddings" + description: str = "Generate embeddings using Azure OpenAI models." documentation: str = "https://python.langchain.com/docs/integrations/text_embedding/azureopenai" beta = False + icon = "Azure" API_VERSION_OPTIONS = [ "2022-12-01", diff --git a/src/backend/langflow/components/embeddings/CohereEmbeddings.py b/src/backend/base/langflow/components/embeddings/CohereEmbeddings.py similarity index 83% rename from src/backend/langflow/components/embeddings/CohereEmbeddings.py rename to src/backend/base/langflow/components/embeddings/CohereEmbeddings.py index d3f82b041..23d855f40 100644 --- a/src/backend/langflow/components/embeddings/CohereEmbeddings.py +++ b/src/backend/base/langflow/components/embeddings/CohereEmbeddings.py @@ -2,12 +2,12 @@ from typing import Optional from langchain_community.embeddings.cohere import CohereEmbeddings -from langflow import CustomComponent +from langflow.custom import CustomComponent class CohereEmbeddingsComponent(CustomComponent): - display_name = "CohereEmbeddings" - description = "Cohere embedding models." + display_name = "Cohere Embeddings" + description = "Generate embeddings using Cohere models." def build_config(self): return { @@ -16,6 +16,7 @@ class CohereEmbeddingsComponent(CustomComponent): "truncate": {"display_name": "Truncate", "advanced": True}, "max_retries": {"display_name": "Max Retries", "advanced": True}, "user_agent": {"display_name": "User Agent", "advanced": True}, + "request_timeout": {"display_name": "Request Timeout", "advanced": True}, } def build( diff --git a/src/backend/langflow/components/embeddings/HuggingFaceEmbeddings.py b/src/backend/base/langflow/components/embeddings/HuggingFaceEmbeddings.py similarity index 84% rename from src/backend/langflow/components/embeddings/HuggingFaceEmbeddings.py rename to src/backend/base/langflow/components/embeddings/HuggingFaceEmbeddings.py index 6f3540358..849cd9bba 100644 --- a/src/backend/langflow/components/embeddings/HuggingFaceEmbeddings.py +++ b/src/backend/base/langflow/components/embeddings/HuggingFaceEmbeddings.py @@ -1,14 +1,17 @@ -from langflow import CustomComponent -from typing import Optional, Dict +from typing import Dict, Optional + from langchain_community.embeddings.huggingface import HuggingFaceEmbeddings +from langflow.interface.custom.custom_component import CustomComponent + class HuggingFaceEmbeddingsComponent(CustomComponent): - display_name = "HuggingFaceEmbeddings" - description = "HuggingFace sentence_transformers embedding models." + display_name = "Hugging Face Embeddings" + description = "Generate embeddings using HuggingFace models." documentation = ( "https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/sentence_transformers" ) + icon = "HuggingFace" def build_config(self): return { diff --git a/src/backend/langflow/components/embeddings/HuggingFaceInferenceAPIEmbeddings.py b/src/backend/base/langflow/components/embeddings/HuggingFaceInferenceAPIEmbeddings.py similarity index 87% rename from src/backend/langflow/components/embeddings/HuggingFaceInferenceAPIEmbeddings.py rename to src/backend/base/langflow/components/embeddings/HuggingFaceInferenceAPIEmbeddings.py index acc828d7f..37a08ccc6 100644 --- a/src/backend/langflow/components/embeddings/HuggingFaceInferenceAPIEmbeddings.py +++ b/src/backend/base/langflow/components/embeddings/HuggingFaceInferenceAPIEmbeddings.py @@ -1,14 +1,16 @@ from typing import Dict, Optional from langchain_community.embeddings.huggingface import HuggingFaceInferenceAPIEmbeddings -from langflow import CustomComponent from pydantic.v1.types import SecretStr +from langflow.interface.custom.custom_component import CustomComponent + class HuggingFaceInferenceAPIEmbeddingsComponent(CustomComponent): - display_name = "HuggingFaceInferenceAPIEmbeddings" - description = "HuggingFace sentence_transformers embedding models, API version." + display_name = "Hugging Face API Embeddings" + description = "Generate embeddings using Hugging Face Inference API models." documentation = "https://github.com/huggingface/text-embeddings-inference" + icon = "HuggingFace" def build_config(self): return { diff --git a/src/backend/langflow/components/embeddings/OllamaEmbeddings.py b/src/backend/base/langflow/components/embeddings/OllamaEmbeddings.py similarity index 84% rename from src/backend/langflow/components/embeddings/OllamaEmbeddings.py rename to src/backend/base/langflow/components/embeddings/OllamaEmbeddings.py index 65c6aca3b..63ddc6fd4 100644 --- a/src/backend/langflow/components/embeddings/OllamaEmbeddings.py +++ b/src/backend/base/langflow/components/embeddings/OllamaEmbeddings.py @@ -1,19 +1,15 @@ from typing import Optional -from langflow import CustomComponent from langchain.embeddings.base import Embeddings from langchain_community.embeddings import OllamaEmbeddings +from langflow.interface.custom.custom_component import CustomComponent + class OllamaEmbeddingsComponent(CustomComponent): - """ - A custom component for implementing an Embeddings Model using Ollama. - """ - display_name: str = "Ollama Embeddings" - description: str = "Embeddings model from Ollama." + description: str = "Generate embeddings using Ollama models." documentation = "https://python.langchain.com/docs/integrations/text_embedding/ollama" - beta = True def build_config(self): return { diff --git a/src/backend/langflow/components/embeddings/OpenAIEmbeddings.py b/src/backend/base/langflow/components/embeddings/OpenAIEmbeddings.py similarity index 78% rename from src/backend/langflow/components/embeddings/OpenAIEmbeddings.py rename to src/backend/base/langflow/components/embeddings/OpenAIEmbeddings.py index ba6d634b8..f177fa1f1 100644 --- a/src/backend/langflow/components/embeddings/OpenAIEmbeddings.py +++ b/src/backend/base/langflow/components/embeddings/OpenAIEmbeddings.py @@ -1,14 +1,14 @@ -from typing import Any, Callable, Dict, List, Optional, Union +from typing import Any, Dict, List, Optional from langchain_openai.embeddings.base import OpenAIEmbeddings -from langflow import CustomComponent -from langflow.field_typing import NestedDict -from pydantic.v1.types import SecretStr + +from langflow.field_typing import Embeddings, NestedDict +from langflow.interface.custom.custom_component import CustomComponent class OpenAIEmbeddingsComponent(CustomComponent): - display_name = "OpenAIEmbeddings" - description = "OpenAI embedding models" + display_name = "OpenAI Embeddings" + description = "Generate embeddings using OpenAI models." def build_config(self): return { @@ -45,12 +45,24 @@ class OpenAIEmbeddingsComponent(CustomComponent): "model": { "display_name": "Model", "advanced": False, - "options": ["text-embedding-3-small", "text-embedding-3-large", "text-embedding-ada-002"], + "options": [ + "text-embedding-3-small", + "text-embedding-3-large", + "text-embedding-ada-002", + ], }, "model_kwargs": {"display_name": "Model Kwargs", "advanced": True}, - "openai_api_base": {"display_name": "OpenAI API Base", "password": True, "advanced": True}, + "openai_api_base": { + "display_name": "OpenAI API Base", + "password": True, + "advanced": True, + }, "openai_api_key": {"display_name": "OpenAI API Key", "password": True}, - "openai_api_type": {"display_name": "OpenAI API Type", "advanced": True, "password": True}, + "openai_api_type": { + "display_name": "OpenAI API Type", + "advanced": True, + "password": True, + }, "openai_api_version": { "display_name": "OpenAI API Version", "advanced": True, @@ -66,25 +78,28 @@ class OpenAIEmbeddingsComponent(CustomComponent): "advanced": True, }, "skip_empty": {"display_name": "Skip Empty", "advanced": True}, - "tiktoken_model_name": {"display_name": "TikToken Model Name"}, - "tikToken_enable": {"display_name": "TikToken Enable", "advanced": True}, + "tiktoken_model_name": { + "display_name": "TikToken Model Name", + "advanced": True, + }, + "tiktoken_enable": {"display_name": "TikToken Enable", "advanced": True}, } def build( self, + openai_api_key: str, default_headers: Optional[Dict[str, str]] = None, default_query: Optional[NestedDict] = {}, allowed_special: List[str] = [], disallowed_special: List[str] = ["all"], chunk_size: int = 1000, client: Optional[Any] = None, - deployment: str = "text-embedding-3-small", + deployment: str = "text-embedding-ada-002", embedding_ctx_length: int = 8191, max_retries: int = 6, - model: str = "text-embedding-3-small", + model: str = "text-embedding-ada-002", model_kwargs: NestedDict = {}, openai_api_base: Optional[str] = None, - openai_api_key: Optional[str] = "", openai_api_type: Optional[str] = None, openai_api_version: Optional[str] = None, openai_organization: Optional[str] = None, @@ -94,13 +109,11 @@ class OpenAIEmbeddingsComponent(CustomComponent): skip_empty: bool = False, tiktoken_enable: bool = True, tiktoken_model_name: Optional[str] = None, - ) -> Union[OpenAIEmbeddings, Callable]: + ) -> Embeddings: # This is to avoid errors with Vector Stores (e.g Chroma) if disallowed_special == ["all"]: disallowed_special = "all" # type: ignore - api_key = SecretStr(openai_api_key) if openai_api_key else None - return OpenAIEmbeddings( tiktoken_enabled=tiktoken_enable, default_headers=default_headers, @@ -115,7 +128,7 @@ class OpenAIEmbeddingsComponent(CustomComponent): model=model, model_kwargs=model_kwargs, base_url=openai_api_base, - api_key=api_key, + api_key=openai_api_key, openai_api_type=openai_api_type, api_version=openai_api_version, organization=openai_organization, diff --git a/src/backend/langflow/components/embeddings/VertexAIEmbeddings.py b/src/backend/base/langflow/components/embeddings/VertexAIEmbeddings.py similarity index 54% rename from src/backend/langflow/components/embeddings/VertexAIEmbeddings.py rename to src/backend/base/langflow/components/embeddings/VertexAIEmbeddings.py index 053fd6c7f..a88b403c3 100644 --- a/src/backend/langflow/components/embeddings/VertexAIEmbeddings.py +++ b/src/backend/base/langflow/components/embeddings/VertexAIEmbeddings.py @@ -1,25 +1,55 @@ -from langflow import CustomComponent -from langchain.embeddings import VertexAIEmbeddings -from typing import Optional, List +from typing import List, Optional + +from langchain_community.embeddings import VertexAIEmbeddings + +from langflow.interface.custom.custom_component import CustomComponent class VertexAIEmbeddingsComponent(CustomComponent): - display_name = "VertexAIEmbeddings" - description = "Google Cloud VertexAI embedding models." + display_name = "VertexAI Embeddings" + description = "Generate embeddings using Google Cloud VertexAI models." def build_config(self): return { - "credentials": {"display_name": "Credentials", "value": "", "file_types": [".json"], "field_type": "file"}, - "instance": {"display_name": "instance", "advanced": True, "field_type": "dict"}, - "location": {"display_name": "Location", "value": "us-central1", "advanced": True}, + "credentials": { + "display_name": "Credentials", + "value": "", + "file_types": [".json"], + "field_type": "file", + }, + "instance": { + "display_name": "instance", + "advanced": True, + "field_type": "dict", + }, + "location": { + "display_name": "Location", + "value": "us-central1", + "advanced": True, + }, "max_output_tokens": {"display_name": "Max Output Tokens", "value": 128}, - "max_retries": {"display_name": "Max Retries", "value": 6, "advanced": True}, - "model_name": {"display_name": "Model Name", "value": "textembedding-gecko"}, + "max_retries": { + "display_name": "Max Retries", + "value": 6, + "advanced": True, + }, + "model_name": { + "display_name": "Model Name", + "value": "textembedding-gecko", + }, "n": {"display_name": "N", "value": 1, "advanced": True}, "project": {"display_name": "Project", "advanced": True}, - "request_parallelism": {"display_name": "Request Parallelism", "value": 5, "advanced": True}, + "request_parallelism": { + "display_name": "Request Parallelism", + "value": 5, + "advanced": True, + }, "stop": {"display_name": "Stop", "advanced": True}, - "streaming": {"display_name": "Streaming", "value": False, "advanced": True}, + "streaming": { + "display_name": "Streaming", + "value": False, + "advanced": True, + }, "temperature": {"display_name": "Temperature", "value": 0.0}, "top_k": {"display_name": "Top K", "value": 40, "advanced": True}, "top_p": {"display_name": "Top P", "value": 0.95, "advanced": True}, diff --git a/src/backend/base/langflow/components/embeddings/__init__.py b/src/backend/base/langflow/components/embeddings/__init__.py new file mode 100644 index 000000000..f2d1bc48e --- /dev/null +++ b/src/backend/base/langflow/components/embeddings/__init__.py @@ -0,0 +1,19 @@ +from .AmazonBedrockEmbeddings import AmazonBedrockEmeddingsComponent +from .AzureOpenAIEmbeddings import AzureOpenAIEmbeddingsComponent +from .CohereEmbeddings import CohereEmbeddingsComponent +from .HuggingFaceEmbeddings import HuggingFaceEmbeddingsComponent +from .HuggingFaceInferenceAPIEmbeddings import HuggingFaceInferenceAPIEmbeddingsComponent +from .OllamaEmbeddings import OllamaEmbeddingsComponent +from .OpenAIEmbeddings import OpenAIEmbeddingsComponent +from .VertexAIEmbeddings import VertexAIEmbeddingsComponent + +__all__ = [ + "AmazonBedrockEmeddingsComponent", + "AzureOpenAIEmbeddingsComponent", + "CohereEmbeddingsComponent", + "HuggingFaceEmbeddingsComponent", + "HuggingFaceInferenceAPIEmbeddingsComponent", + "OllamaEmbeddingsComponent", + "OpenAIEmbeddingsComponent", + "VertexAIEmbeddingsComponent", +] diff --git a/src/backend/base/langflow/components/experimental/ClearMessageHistory.py b/src/backend/base/langflow/components/experimental/ClearMessageHistory.py new file mode 100644 index 000000000..3c62b7ea3 --- /dev/null +++ b/src/backend/base/langflow/components/experimental/ClearMessageHistory.py @@ -0,0 +1,26 @@ +from langflow.interface.custom.custom_component import CustomComponent +from langflow.memory import delete_messages, get_messages + + +class ClearMessageHistoryComponent(CustomComponent): + display_name = "Clear Message History" + description = "A component to clear the message history." + icon = "ClearMessageHistory" + beta: bool = True + + def build_config(self): + return { + "session_id": { + "display_name": "Session ID", + "info": "The session ID to clear the message history.", + } + } + + def build( + self, + session_id: str, + ) -> None: + delete_messages(session_id=session_id) + records = get_messages(session_id=session_id) + self.records = records + return records diff --git a/src/backend/base/langflow/components/experimental/ExtractDataFromRecord.py b/src/backend/base/langflow/components/experimental/ExtractDataFromRecord.py new file mode 100644 index 000000000..5d816f112 --- /dev/null +++ b/src/backend/base/langflow/components/experimental/ExtractDataFromRecord.py @@ -0,0 +1,45 @@ +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema import Record + + +class ExtractKeyFromRecordComponent(CustomComponent): + display_name = "Extract Key From Record" + description = "Extracts a key from a record." + beta: bool = True + + field_config = { + "record": {"display_name": "Record"}, + "keys": { + "display_name": "Keys", + "info": "The keys to extract from the record.", + "input_types": [], + }, + "silent_error": { + "display_name": "Silent Errors", + "info": "If True, errors will not be raised.", + "advanced": True, + }, + } + + def build(self, record: Record, keys: list[str], silent_error: bool = True) -> Record: + """ + Extracts the keys from a record. + + Args: + record (Record): The record from which to extract the keys. + keys (list[str]): The keys to extract from the record. + silent_error (bool): If True, errors will not be raised. + + Returns: + dict: The extracted keys. + """ + extracted_keys = {} + for key in keys: + try: + extracted_keys[key] = getattr(record, key) + except AttributeError: + if not silent_error: + raise KeyError(f"The key '{key}' does not exist in the record.") + return_record = Record(data=extracted_keys) + self.status = return_record + return return_record diff --git a/src/backend/base/langflow/components/experimental/FlowTool.py b/src/backend/base/langflow/components/experimental/FlowTool.py new file mode 100644 index 000000000..ac48a0f03 --- /dev/null +++ b/src/backend/base/langflow/components/experimental/FlowTool.py @@ -0,0 +1,86 @@ +from typing import Any, List, Optional + +from langchain_core.tools import StructuredTool +from loguru import logger + +from langflow.custom import CustomComponent +from langflow.field_typing import Tool +from langflow.graph.graph.base import Graph +from langflow.helpers.flow import build_function_and_schema +from langflow.schema.dotdict import dotdict +from langflow.schema.schema import Record + + +class FlowToolComponent(CustomComponent): + display_name = "Flow as Tool" + description = "Construct a Tool from a function that runs the loaded Flow." + field_order = ["flow_name", "name", "description", "return_direct"] + + def get_flow_names(self) -> List[str]: + flow_records = self.list_flows() + return [flow_record.data["name"] for flow_record in flow_records] + + def get_flow(self, flow_name: str) -> Optional[Record]: + """ + Retrieves a flow by its name. + + Args: + flow_name (str): The name of the flow to retrieve. + + Returns: + Optional[Text]: The flow record if found, None otherwise. + """ + flow_records = self.list_flows() + for flow_record in flow_records: + if flow_record.data["name"] == flow_name: + return flow_record + return None + + def update_build_config(self, build_config: dotdict, field_value: Any, field_name: str | None = None): + logger.debug(f"Updating build config with field value {field_value} and field name {field_name}") + if field_name == "flow_name": + build_config["flow_name"]["options"] = self.get_flow_names() + + return build_config + + def build_config(self): + return { + "flow_name": { + "display_name": "Flow Name", + "info": "The name of the flow to run.", + "options": [], + "real_time_refresh": True, + "refresh_button": True, + }, + "name": { + "display_name": "Name", + "description": "The name of the tool.", + }, + "description": { + "display_name": "Description", + "description": "The description of the tool.", + }, + "return_direct": { + "display_name": "Return Direct", + "description": "Return the result directly from the Tool.", + "advanced": True, + }, + } + + async def build(self, flow_name: str, name: str, description: str, return_direct: bool = False) -> Tool: + flow_record = self.get_flow(flow_name) + if not flow_record: + raise ValueError("Flow not found.") + graph = Graph.from_payload(flow_record.data["data"]) + dynamic_flow_function, schema = build_function_and_schema(flow_record, graph) + tool = StructuredTool.from_function( + coroutine=dynamic_flow_function, + name=name, + description=description, + return_direct=return_direct, + args_schema=schema, + ) + description_repr = repr(tool.description).strip("'") + args_str = "\n".join([f"- {arg_name}: {arg_data['description']}" for arg_name, arg_data in tool.args.items()]) + self.status = f"{description_repr}\nArguments:\n{args_str}" + return tool # type: ignore diff --git a/src/backend/base/langflow/components/experimental/ListFlows.py b/src/backend/base/langflow/components/experimental/ListFlows.py new file mode 100644 index 000000000..c7b421d15 --- /dev/null +++ b/src/backend/base/langflow/components/experimental/ListFlows.py @@ -0,0 +1,21 @@ +from typing import List + +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema import Record + + +class ListFlowsComponent(CustomComponent): + display_name = "List Flows" + description = "A component to list all available flows." + icon = "ListFlows" + beta: bool = True + + def build_config(self): + return {} + + def build( + self, + ) -> List[Record]: + flows = self.list_flows() + self.status = flows + return flows diff --git a/src/backend/base/langflow/components/experimental/Listen.py b/src/backend/base/langflow/components/experimental/Listen.py new file mode 100644 index 000000000..cab979f70 --- /dev/null +++ b/src/backend/base/langflow/components/experimental/Listen.py @@ -0,0 +1,21 @@ +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema import Record + + +class ListenComponent(CustomComponent): + display_name = "Listen" + description = "A component to listen for a notification." + beta: bool = True + + def build_config(self): + return { + "name": { + "display_name": "Name", + "info": "The name of the notification to listen for.", + }, + } + + def build(self, name: str) -> Record: + state = self.get_state(name) + self.status = state + return state diff --git a/src/backend/base/langflow/components/experimental/MergeRecords.py b/src/backend/base/langflow/components/experimental/MergeRecords.py new file mode 100644 index 000000000..60e5ffe20 --- /dev/null +++ b/src/backend/base/langflow/components/experimental/MergeRecords.py @@ -0,0 +1,36 @@ +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema import Record + + +class MergeRecordsComponent(CustomComponent): + display_name = "Merge Records" + description = "Merges records." + beta: bool = True + + field_config = { + "records": {"display_name": "Records"}, + } + + def build(self, records: list[Record]) -> Record: + if not records: + return Record() + if len(records) == 1: + return records[0] + merged_record = Record() + for record in records: + if merged_record is None: + merged_record = record + else: + merged_record += record + self.status = merged_record + return merged_record + + +if __name__ == "__main__": + records = [ + Record(data={"key1": "value1"}), + Record(data={"key2": "value2"}), + ] + component = MergeRecordsComponent() + result = component.build(records) + print(result) diff --git a/src/backend/base/langflow/components/experimental/Notify.py b/src/backend/base/langflow/components/experimental/Notify.py new file mode 100644 index 000000000..9af7f8ec6 --- /dev/null +++ b/src/backend/base/langflow/components/experimental/Notify.py @@ -0,0 +1,41 @@ +from typing import Optional + +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema import Record + + +class NotifyComponent(CustomComponent): + display_name = "Notify" + description = "A component to generate a notification to Get Notified component." + icon = "Notify" + beta: bool = True + + def build_config(self): + return { + "name": {"display_name": "Name", "info": "The name of the notification."}, + "record": {"display_name": "Record", "info": "The record to store."}, + "append": { + "display_name": "Append", + "info": "If True, the record will be appended to the notification.", + }, + } + + def build(self, name: str, record: Optional[Record] = None, append: bool = False) -> Record: + if record and not isinstance(record, Record): + if isinstance(record, str): + record = Record(text=record) + elif isinstance(record, dict): + record = Record(data=record) + else: + record = Record(text=str(record)) + elif not record: + record = Record(text="") + if record: + if append: + self.append_state(name, record) + else: + self.update_state(name, record) + else: + self.status = "No record provided." + self.status = record + return record diff --git a/src/backend/base/langflow/components/experimental/PythonFunction.py b/src/backend/base/langflow/components/experimental/PythonFunction.py new file mode 100644 index 000000000..28e902abe --- /dev/null +++ b/src/backend/base/langflow/components/experimental/PythonFunction.py @@ -0,0 +1,25 @@ +from typing import Callable + +from langflow.field_typing import Code +from langflow.interface.custom.custom_component import CustomComponent +from langflow.interface.custom.utils import get_function + + +class PythonFunctionComponent(CustomComponent): + display_name = "Python Function" + description = "Define a Python function." + icon = "Python" + + def build_config(self): + return { + "function_code": { + "display_name": "Code", + "info": "The code for the function.", + "show": True, + }, + } + + def build(self, function_code: Code) -> Callable: + self.status = function_code + func = get_function(function_code) + return func diff --git a/src/backend/base/langflow/components/experimental/RunFlow.py b/src/backend/base/langflow/components/experimental/RunFlow.py new file mode 100644 index 000000000..d3769de7a --- /dev/null +++ b/src/backend/base/langflow/components/experimental/RunFlow.py @@ -0,0 +1,66 @@ +from typing import Any, List, Optional + +from langflow.custom import CustomComponent +from langflow.field_typing import NestedDict, Text +from langflow.graph.schema import ResultData +from langflow.schema import Record, dotdict + + +class RunFlowComponent(CustomComponent): + display_name = "Run Flow" + description = "A component to run a flow." + beta: bool = True + + def get_flow_names(self) -> List[str]: + flow_records = self.list_flows() + return [flow_record.data["name"] for flow_record in flow_records] + + def update_build_config(self, build_config: dotdict, field_value: Any, field_name: str | None = None): + if field_name == "flow_name": + build_config["flow_name"]["options"] = self.get_flow_names() + + return build_config + + def build_config(self): + return { + "input_value": { + "display_name": "Input Value", + "multiline": True, + }, + "flow_name": { + "display_name": "Flow Name", + "info": "The name of the flow to run.", + "options": [], + "refresh_button": True, + }, + "tweaks": { + "display_name": "Tweaks", + "info": "Tweaks to apply to the flow.", + }, + } + + def build_records_from_result_data(self, result_data: ResultData) -> List[Record]: + messages = result_data.messages + if not messages: + return [] + records = [] + for message in messages: + message_dict = message if isinstance(message, dict) else message.model_dump() + record = Record(text=message_dict.get("text", ""), data={"result": result_data}) + records.append(record) + return records + + async def build(self, input_value: Text, flow_name: str, tweaks: NestedDict) -> List[Record]: + results: List[Optional[ResultData]] = await self.run_flow( + inputs={"input_value": input_value}, flow_name=flow_name, tweaks=tweaks + ) + if isinstance(results, list): + records = [] + for result in results: + if result: + records.extend(self.build_records_from_result_data(result)) + else: + records = self.build_records_from_result_data(results) + + self.status = records + return records diff --git a/src/backend/base/langflow/components/experimental/RunnableExecutor.py b/src/backend/base/langflow/components/experimental/RunnableExecutor.py new file mode 100644 index 000000000..0a3593a66 --- /dev/null +++ b/src/backend/base/langflow/components/experimental/RunnableExecutor.py @@ -0,0 +1,122 @@ +from langchain_core.runnables import Runnable + +from langflow.field_typing import Text +from langflow.interface.custom.custom_component import CustomComponent + + +class RunnableExecComponent(CustomComponent): + description = "Execute a runnable. It will try to guess the input and output keys." + display_name = "Runnable Executor" + beta: bool = True + field_order = [ + "input_key", + "output_key", + "input_value", + "runnable", + ] + + def build_config(self): + return { + "input_key": { + "display_name": "Input Key", + "info": "The key to use for the input.", + "advanced": True, + }, + "input_value": { + "display_name": "Inputs", + "info": "The inputs to pass to the runnable.", + }, + "runnable": { + "display_name": "Runnable", + "info": "The runnable to execute.", + "input_types": ["Chain", "AgentExecutor", "Agent", "Runnable"], + }, + "output_key": { + "display_name": "Output Key", + "info": "The key to use for the output.", + "advanced": True, + }, + } + + def get_output(self, result, input_key, output_key): + """ + Retrieves the output value from the given result dictionary based on the specified input and output keys. + + Args: + result (dict): The result dictionary containing the output value. + input_key (str): The key used to retrieve the input value from the result dictionary. + output_key (str): The key used to retrieve the output value from the result dictionary. + + Returns: + tuple: A tuple containing the output value and the status message. + + """ + possible_output_keys = ["answer", "response", "output", "result", "text"] + status = "" + result_value = None + + if output_key in result: + result_value = result.get(output_key) + elif len(result) == 2 and input_key in result: + # get the other key from the result dict + other_key = [k for k in result if k != input_key][0] + if other_key == output_key: + result_value = result.get(output_key) + else: + status += f"Warning: The output key is not '{output_key}'. The output key is '{other_key}'." + result_value = result.get(other_key) + elif len(result) == 1: + result_value = list(result.values())[0] + elif any(k in result for k in possible_output_keys): + for key in possible_output_keys: + if key in result: + result_value = result.get(key) + status += f"Output key: '{key}'." + break + if result_value is None: + result_value = result + status += f"Warning: The output key is not '{output_key}'." + else: + result_value = result + status += f"Warning: The output key is not '{output_key}'." + + return result_value, status + + def get_input_dict(self, runnable, input_key, input_value): + """ + Returns a dictionary containing the input key-value pair for the given runnable. + + Args: + runnable: The runnable object. + input_key: The key for the input value. + input_value: The value for the input key. + + Returns: + input_dict: A dictionary containing the input key-value pair. + status: A status message indicating if the input key is not in the runnable's input keys. + """ + input_dict = {} + status = "" + if hasattr(runnable, "input_keys"): + # Check if input_key is in the runnable's input_keys + if input_key in runnable.input_keys: + input_dict[input_key] = input_value + else: + input_dict = {k: input_value for k in runnable.input_keys} + status = f"Warning: The input key is not '{input_key}'. The input key is '{runnable.input_keys}'." + return input_dict, status + + def build( + self, + input_value: Text, + runnable: Runnable, + input_key: str = "input", + output_key: str = "output", + ) -> Text: + input_dict, status = self.get_input_dict(runnable, input_key, input_value) + result = runnable.invoke(input_dict) + result_value, _status = self.get_output(result, input_key, output_key) + status += _status + status += f"\n\nOutput: {result_value}\n\nRaw Output: {result}" + self.status = status + return result_value diff --git a/src/backend/base/langflow/components/experimental/SQLExecutor.py b/src/backend/base/langflow/components/experimental/SQLExecutor.py new file mode 100644 index 000000000..2289514a6 --- /dev/null +++ b/src/backend/base/langflow/components/experimental/SQLExecutor.py @@ -0,0 +1,69 @@ +from langchain_community.tools.sql_database.tool import QuerySQLDataBaseTool +from langchain_experimental.sql.base import SQLDatabase + +from langflow.field_typing import Text +from langflow.interface.custom.custom_component import CustomComponent + + +class SQLExecutorComponent(CustomComponent): + display_name = "SQL Executor" + description = "Execute SQL query." + beta: bool = True + + def build_config(self): + return { + "database_url": { + "display_name": "Database URL", + "info": "The URL of the database.", + }, + "include_columns": { + "display_name": "Include Columns", + "info": "Include columns in the result.", + }, + "passthrough": { + "display_name": "Passthrough", + "info": "If an error occurs, return the query instead of raising an exception.", + }, + "add_error": { + "display_name": "Add Error", + "info": "Add the error to the result.", + }, + } + + def clean_up_uri(self, uri: str) -> str: + if uri.startswith("postgresql://"): + uri = uri.replace("postgresql://", "postgres://") + return uri.strip() + + def build( + self, + query: str, + database_url: str, + include_columns: bool = False, + passthrough: bool = False, + add_error: bool = False, + ) -> Text: + error = None + try: + database = SQLDatabase.from_uri(database_url) + except Exception as e: + raise ValueError(f"An error occurred while connecting to the database: {e}") + try: + tool = QuerySQLDataBaseTool(db=database) + result = tool.run(query, include_columns=include_columns) + self.status = result + except Exception as e: + result = Text(e) + self.status = result + if not passthrough: + raise e + error = repr(e) + + if add_error and error is not None: + result = f"{result}\n\nError: {error}\n\nQuery: {query}" + elif error is not None: + # Then we won't add the error to the result + # but since we are in passthrough mode, we will return the query + result = query + + return result diff --git a/src/backend/base/langflow/components/experimental/SubFlow.py b/src/backend/base/langflow/components/experimental/SubFlow.py new file mode 100644 index 000000000..72e07c8e8 --- /dev/null +++ b/src/backend/base/langflow/components/experimental/SubFlow.py @@ -0,0 +1,119 @@ +from typing import Any, List, Optional + +from loguru import logger + +from langflow.custom import CustomComponent +from langflow.graph.graph.base import Graph +from langflow.graph.schema import ResultData, RunOutputs +from langflow.graph.vertex.base import Vertex +from langflow.helpers.flow import get_flow_inputs +from langflow.schema import Record +from langflow.schema.dotdict import dotdict +from langflow.template.field.base import TemplateField + + +class SubFlowComponent(CustomComponent): + display_name = "Sub Flow" + description = "Dynamically Generates a Component from a Flow. The output is a list of records with keys 'result' and 'message'." + beta: bool = True + field_order = ["flow_name"] + + def get_flow_names(self) -> List[str]: + flow_records = self.list_flows() + return [flow_record.data["name"] for flow_record in flow_records] + + def get_flow(self, flow_name: str) -> Optional[Record]: + flow_records = self.list_flows() + for flow_record in flow_records: + if flow_record.data["name"] == flow_name: + return flow_record + return None + + def update_build_config(self, build_config: dotdict, field_value: Any, field_name: str | None = None): + logger.debug(f"Updating build config with field value {field_value} and field name {field_name}") + if field_name == "flow_name": + build_config["flow_name"]["options"] = self.get_flow_names() + # Clean up the build config + for key in list(build_config.keys()): + if key not in self.field_order + ["code", "_type"]: + del build_config[key] + if field_value is not None and field_name == "flow_name": + try: + flow_record = self.get_flow(field_value) + if not flow_record: + raise ValueError(f"Flow {field_value} not found.") + graph = Graph.from_payload(flow_record.data["data"]) + # Get all inputs from the graph + inputs = get_flow_inputs(graph) + # Add inputs to the build config + build_config = self.add_inputs_to_build_config(inputs, build_config) + except Exception as e: + logger.error(f"Error getting flow {field_value}: {str(e)}") + + return build_config + + def add_inputs_to_build_config(self, inputs: List[Vertex], build_config: dotdict): + new_fields: list[TemplateField] = [] + for vertex in inputs: + field = TemplateField( + display_name=vertex.display_name, + name=vertex.id, + info=vertex.description, + field_type="str", + default=None, + ) + new_fields.append(field) + logger.debug(new_fields) + for field in new_fields: + build_config[field.name] = field.to_dict() + return build_config + + def build_config(self): + return { + "input_value": { + "display_name": "Input Value", + "multiline": True, + }, + "flow_name": { + "display_name": "Flow Name", + "info": "The name of the flow to run.", + "options": [], + "real_time_refresh": True, + "refresh_button": True, + }, + "tweaks": { + "display_name": "Tweaks", + "info": "Tweaks to apply to the flow.", + }, + } + + def build_records_from_result_data(self, result_data: ResultData) -> List[Record]: + messages = result_data.messages + if not messages: + return [] + records = [] + for message in messages: + message_dict = message if isinstance(message, dict) else message.model_dump() + record = Record(data={"result": result_data.model_dump(), "message": message_dict.get("message", "")}) + records.append(record) + return records + + async def build(self, flow_name: str, **kwargs) -> List[Record]: + tweaks = {key: {"input_value": value} for key, value in kwargs.items()} + run_outputs: List[Optional[RunOutputs]] = await self.run_flow( + tweaks=tweaks, + flow_name=flow_name, + ) + if not run_outputs: + return [] + run_output = run_outputs[0] + + records = [] + if run_output is not None: + for output in run_output.outputs: + if output: + records.extend(self.build_records_from_result_data(output)) + + self.status = records + logger.debug(records) + return records diff --git a/src/backend/base/langflow/components/experimental/__init__.py b/src/backend/base/langflow/components/experimental/__init__.py new file mode 100644 index 000000000..54ca60a3b --- /dev/null +++ b/src/backend/base/langflow/components/experimental/__init__.py @@ -0,0 +1,28 @@ +from .ClearMessageHistory import ClearMessageHistoryComponent +from .ExtractDataFromRecord import ExtractKeyFromRecordComponent +from .FlowTool import FlowToolComponent +from .ListFlows import ListFlowsComponent +from .Listen import ListenComponent +from .MergeRecords import MergeRecordsComponent +from .Notify import NotifyComponent +from .PythonFunction import PythonFunctionComponent +from .RunFlow import RunFlowComponent +from .RunnableExecutor import RunnableExecComponent +from .SQLExecutor import SQLExecutorComponent +from .SubFlow import SubFlowComponent + +__all__ = [ + "ClearMessageHistoryComponent", + "ExtractKeyFromRecordComponent", + "FlowToolComponent", + "ListFlowsComponent", + "ListenComponent", + "MergeRecordsComponent", + "NotifyComponent", + "PythonFunctionComponent", + "RunFlowComponent", + "RunnableExecComponent", + "SQLExecutorComponent", + "SubFlowComponent", + "PythonFunctionComponent", +] diff --git a/src/backend/base/langflow/components/helpers/CombineText.py b/src/backend/base/langflow/components/helpers/CombineText.py new file mode 100644 index 000000000..fcd23c188 --- /dev/null +++ b/src/backend/base/langflow/components/helpers/CombineText.py @@ -0,0 +1,29 @@ +from langflow.interface.custom.custom_component import CustomComponent +from langflow.field_typing import Text + + +class CombineTextComponent(CustomComponent): + display_name = "Combine Text" + description = "Concatenate two text sources into a single text chunk using a specified delimiter." + icon = "merge" + + def build_config(self): + return { + "text1": { + "display_name": "First Text", + "info": "The first text input to concatenate.", + }, + "text2": { + "display_name": "Second Text", + "info": "The second text input to concatenate.", + }, + "delimiter": { + "display_name": "Delimiter", + "info": "A string used to separate the two text inputs. Defaults to a whitespace.", + }, + } + + def build(self, text1: str, text2: str, delimiter: str = " ") -> Text: + combined = delimiter.join([text1, text2]) + self.status = combined + return combined diff --git a/src/backend/base/langflow/components/helpers/CreateRecord.py b/src/backend/base/langflow/components/helpers/CreateRecord.py new file mode 100644 index 000000000..a4a02e76b --- /dev/null +++ b/src/backend/base/langflow/components/helpers/CreateRecord.py @@ -0,0 +1,81 @@ +from typing import Any + +from langflow.custom import CustomComponent +from langflow.field_typing.range_spec import RangeSpec +from langflow.schema import Record +from langflow.schema.dotdict import dotdict +from langflow.template.field.base import TemplateField + + +class CreateRecordComponent(CustomComponent): + display_name = "Create Record" + description = "Dynamically create a Record with a specified number of fields." + field_order = ["number_of_fields", "text_key"] + + def update_build_config(self, build_config: dotdict, field_value: Any, field_name: str | None = None): + if field_name == "number_of_fields": + default_keys = ["code", "_type", "number_of_fields", "text_key"] + try: + field_value_int = int(field_value) + except TypeError: + return build_config + existing_fields = {} + if field_value_int > 15: + build_config["number_of_fields"]["value"] = 15 + raise ValueError("Number of fields cannot exceed 15. Try using a Component to combine two Records.") + if len(build_config) > len(default_keys) + field_value_int: + # back up the existing template fields + for key in build_config.copy(): + if key not in default_keys: + existing_fields[key] = build_config.pop(key) + + for i in range(1, field_value_int + 1): + key = f"field_{i}_key" + if key in existing_fields: + field = existing_fields[key] + build_config[key] = field + else: + field = TemplateField( + display_name=f"Field {i}", + name=key, + info=f"Key for field {i}.", + field_type="dict", + input_types=["Text", "Record"], + ) + build_config[field.name] = field.to_dict() + + build_config["number_of_fields"]["value"] = field_value_int + return build_config + + def build_config(self): + return { + "number_of_fields": { + "display_name": "Number of Fields", + "info": "Number of fields to be added to the record.", + "real_time_refresh": True, + "rangeSpec": RangeSpec(min=1, max=15, step=1, step_type="int"), + }, + "text_key": { + "display_name": "Text Key", + "info": "Key to be used as text.", + "advanced": True, + }, + } + + def build( + self, + number_of_fields: int = 0, + text_key: str = "text", + **kwargs, + ) -> Record: + data = {} + for value_dict in kwargs.values(): + if isinstance(value_dict, dict): + # Check if the value of the value_dict is a Record + value_dict = { + key: value.get_text() if isinstance(value, Record) else value for key, value in value_dict.items() + } + data.update(value_dict) + return_record = Record(data=data, text_key=text_key) + self.status = return_record + return return_record diff --git a/src/backend/base/langflow/components/helpers/CustomComponent.py b/src/backend/base/langflow/components/helpers/CustomComponent.py new file mode 100644 index 000000000..ce3d8c62c --- /dev/null +++ b/src/backend/base/langflow/components/helpers/CustomComponent.py @@ -0,0 +1,16 @@ +# from langflow.field_typing import Data +from langflow.schema import Record +from langflow.interface.custom.custom_component import CustomComponent + + +class Component(CustomComponent): + display_name = "Custom Component" + description = "Use as a template to create your own component." + documentation: str = "http://docs.langflow.org/components/custom" + icon = "custom_components" + + def build_config(self): + return {"param": {"display_name": "Parameter"}} + + def build(self, param: str) -> Record: + return Record(data=param) diff --git a/src/backend/base/langflow/components/helpers/DocumentToRecord.py b/src/backend/base/langflow/components/helpers/DocumentToRecord.py new file mode 100644 index 000000000..362c0a9c1 --- /dev/null +++ b/src/backend/base/langflow/components/helpers/DocumentToRecord.py @@ -0,0 +1,22 @@ +from typing import List + +from langchain_core.documents import Document + +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema import Record + + +class DocumentToRecordComponent(CustomComponent): + display_name = "Documents To Records" + description = "Convert LangChain Documents into Records." + + field_config = { + "documents": {"display_name": "Documents"}, + } + + def build(self, documents: List[Document]) -> List[Record]: + if isinstance(documents, Document): + documents = [documents] + records = [Record.from_document(document) for document in documents] + self.status = records + return records diff --git a/src/backend/base/langflow/components/helpers/IDGenerator.py b/src/backend/base/langflow/components/helpers/IDGenerator.py new file mode 100644 index 000000000..5778c4c22 --- /dev/null +++ b/src/backend/base/langflow/components/helpers/IDGenerator.py @@ -0,0 +1,31 @@ +import uuid +from typing import Any, Optional + +from langflow.interface.custom.custom_component import CustomComponent + + +class UUIDGeneratorComponent(CustomComponent): + documentation: str = "http://docs.langflow.org/components/custom" + display_name = "ID Generator" + description = "Generates a unique ID." + + def update_build_config( + self, + build_config: dict, + field_value: Any, + field_name: Optional[str] = None, + ): + if field_name == "unique_id": + build_config[field_name]["value"] = str(uuid.uuid4()) + return build_config + + def build_config(self): + return { + "unique_id": { + "display_name": "Value", + "real_time_refresh": True, + } + } + + def build(self, unique_id: str) -> str: + return unique_id diff --git a/src/backend/base/langflow/components/helpers/MemoryComponent.py b/src/backend/base/langflow/components/helpers/MemoryComponent.py new file mode 100644 index 000000000..670954b25 --- /dev/null +++ b/src/backend/base/langflow/components/helpers/MemoryComponent.py @@ -0,0 +1,66 @@ +from typing import Optional + +from langflow.field_typing import Text +from langflow.helpers.record import records_to_text +from langflow.interface.custom.custom_component import CustomComponent +from langflow.memory import get_messages + + +class MemoryComponent(CustomComponent): + display_name = "Chat Memory" + description = "Retrieves stored chat messages given a specific Session ID." + beta: bool = True + icon = "history" + + def build_config(self): + return { + "sender": { + "options": ["Machine", "User", "Machine and User"], + "display_name": "Sender Type", + }, + "sender_name": {"display_name": "Sender Name", "advanced": True}, + "n_messages": { + "display_name": "Number of Messages", + "info": "Number of messages to retrieve.", + }, + "session_id": { + "display_name": "Session ID", + "info": "Session ID of the chat history.", + "input_types": ["Text"], + }, + "order": { + "options": ["Ascending", "Descending"], + "display_name": "Order", + "info": "Order of the messages.", + "advanced": True, + }, + "record_template": { + "display_name": "Record Template", + "multiline": True, + "info": "Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.", + "advanced": True, + }, + } + + def build( + self, + sender: Optional[str] = "Machine and User", + sender_name: Optional[str] = None, + session_id: Optional[str] = None, + n_messages: int = 5, + order: Optional[str] = "Descending", + record_template: Optional[str] = "{sender_name}: {text}", + ) -> Text: + order = "DESC" if order == "Descending" else "ASC" + if sender == "Machine and User": + sender = None + messages = get_messages( + sender=sender, + sender_name=sender_name, + session_id=session_id, + limit=n_messages, + order=order, + ) + messages_str = records_to_text(template=record_template, records=messages) + self.status = messages_str + return messages_str diff --git a/src/backend/base/langflow/components/helpers/MessageHistory.py b/src/backend/base/langflow/components/helpers/MessageHistory.py new file mode 100644 index 000000000..0f208e6eb --- /dev/null +++ b/src/backend/base/langflow/components/helpers/MessageHistory.py @@ -0,0 +1,56 @@ +from typing import List, Optional + +from langflow.interface.custom.custom_component import CustomComponent +from langflow.memory import get_messages +from langflow.schema import Record + + +class MessageHistoryComponent(CustomComponent): + display_name = "Message History" + description = "Retrieves stored chat messages given a specific Session ID." + beta: bool = True + + def build_config(self): + return { + "sender": { + "options": ["Machine", "User", "Machine and User"], + "display_name": "Sender Type", + }, + "sender_name": {"display_name": "Sender Name", "advanced": True}, + "n_messages": { + "display_name": "Number of Messages", + "info": "Number of messages to retrieve.", + }, + "session_id": { + "display_name": "Session ID", + "info": "Session ID of the chat history.", + "input_types": ["Text"], + }, + "order": { + "options": ["Ascending", "Descending"], + "display_name": "Order", + "info": "Order of the messages.", + "advanced": True, + }, + } + + def build( + self, + sender: Optional[str] = "Machine and User", + sender_name: Optional[str] = None, + session_id: Optional[str] = None, + n_messages: int = 5, + order: Optional[str] = "Descending", + ) -> List[Record]: + order = "DESC" if order == "Descending" else "ASC" + if sender == "Machine and User": + sender = None + messages = get_messages( + sender=sender, + sender_name=sender_name, + session_id=session_id, + limit=n_messages, + order=order, + ) + self.status = messages + return messages diff --git a/src/backend/base/langflow/components/helpers/RecordsToText.py b/src/backend/base/langflow/components/helpers/RecordsToText.py new file mode 100644 index 000000000..8f4fed311 --- /dev/null +++ b/src/backend/base/langflow/components/helpers/RecordsToText.py @@ -0,0 +1,35 @@ +from langflow.field_typing import Text +from langflow.helpers.record import records_to_text +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema import Record + + +class RecordsToTextComponent(CustomComponent): + display_name = "Records To Text" + description = "Convert Records into plain text following a specified template." + + def build_config(self): + return { + "records": { + "display_name": "Records", + "info": "The records to convert to text.", + }, + "template": { + "display_name": "Template", + "info": "The template to use for formatting the records. It can contain the keys {text}, {data} or any other key in the Record.", + }, + } + + def build( + self, + records: list[Record], + template: str = "Text: {text}\nData: {data}", + ) -> Text: + if not records: + return "" + if isinstance(records, Record): + records = [records] + + result_string = records_to_text(template, records) + self.status = result_string + return result_string diff --git a/src/backend/base/langflow/components/helpers/SplitText.py b/src/backend/base/langflow/components/helpers/SplitText.py new file mode 100644 index 000000000..a141bbddc --- /dev/null +++ b/src/backend/base/langflow/components/helpers/SplitText.py @@ -0,0 +1,85 @@ +from typing import Optional + +from langchain.text_splitter import CharacterTextSplitter, RecursiveCharacterTextSplitter +from langchain_core.documents import Document + +from langflow.field_typing import Text +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema import Record +from langflow.utils.util import unescape_string + + +class SplitTextComponent(CustomComponent): + display_name: str = "Split Text" + description: str = "Split text into chunks of a specified length." + + def build_config(self): + return { + "inputs": { + "display_name": "Inputs", + "info": "Texts to split.", + "input_types": ["Record", "Text"], + }, + "separators": { + "display_name": "Separators", + "info": 'The characters to split on. Defaults to [" "].', + "is_list": True, + }, + "chunk_size": { + "display_name": "Max Chunk Size", + "info": "The maximum length (in number of characters) of each chunk.", + "field_type": "int", + "value": 1000, + }, + "chunk_overlap": { + "display_name": "Chunk Overlap", + "info": "The amount of character overlap between chunks.", + "field_type": "int", + "value": 200, + }, + "recursive": { + "display_name": "Recursive", + }, + "code": {"show": False}, + } + + def build( + self, + inputs: list[Text], + separators: Optional[list[str]] = [" "], + chunk_size: Optional[int] = 1000, + chunk_overlap: Optional[int] = 200, + recursive: bool = False, + ) -> list[Record]: + separators = [unescape_string(x) for x in separators] + + # Make sure chunk_size and chunk_overlap are ints + if isinstance(chunk_size, str): + chunk_size = int(chunk_size) + if isinstance(chunk_overlap, str): + chunk_overlap = int(chunk_overlap) + + if recursive: + splitter = RecursiveCharacterTextSplitter( + separators=separators, + chunk_size=chunk_size, + chunk_overlap=chunk_overlap, + ) + + else: + splitter = CharacterTextSplitter( + separator=separators[0], + chunk_size=chunk_size, + chunk_overlap=chunk_overlap, + ) + + documents = [] + for _input in inputs: + if isinstance(_input, Record): + documents.append(_input.to_lc_document()) + else: + documents.append(Document(page_content=_input)) + + records = self.to_records(splitter.split_documents(documents)) + self.status = records + return records diff --git a/src/backend/base/langflow/components/helpers/UpdateRecord.py b/src/backend/base/langflow/components/helpers/UpdateRecord.py new file mode 100644 index 000000000..9f165e146 --- /dev/null +++ b/src/backend/base/langflow/components/helpers/UpdateRecord.py @@ -0,0 +1,39 @@ +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema import Record + + +class UpdateRecordComponent(CustomComponent): + display_name = "Update Record" + description = "Update Record with text-based key/value pairs, similar to updating a Python dictionary." + + def build_config(self): + return { + "record": { + "display_name": "Record", + "info": "The record to update.", + }, + "new_data": { + "display_name": "New Data", + "info": "The new data to update the record with.", + "input_types": ["Text"], + }, + } + + def build( + self, + record: Record, + new_data: dict, + ) -> Record: + """ + Updates a record with new data. + + Args: + record (Record): The record to update. + new_data (dict): The new data to update the record with. + + Returns: + Record: The updated record. + """ + record.data.update(new_data) + self.status = record + return record diff --git a/src/backend/base/langflow/components/helpers/__init__.py b/src/backend/base/langflow/components/helpers/__init__.py new file mode 100644 index 000000000..af3524d8e --- /dev/null +++ b/src/backend/base/langflow/components/helpers/__init__.py @@ -0,0 +1,17 @@ +from .CreateRecord import CreateRecordComponent +from .CustomComponent import Component +from .DocumentToRecord import DocumentToRecordComponent +from .IDGenerator import UUIDGeneratorComponent +from .MessageHistory import MessageHistoryComponent +from .UpdateRecord import UpdateRecordComponent +from .RecordsToText import RecordsToTextComponent + +__all__ = [ + "Component", + "UpdateRecordComponent", + "DocumentToRecordComponent", + "UUIDGeneratorComponent", + "RecordsToTextComponent", + "CreateRecordComponent", + "MessageHistoryComponent", +] diff --git a/src/backend/base/langflow/components/inputs/ChatInput.py b/src/backend/base/langflow/components/inputs/ChatInput.py new file mode 100644 index 000000000..00eaab98c --- /dev/null +++ b/src/backend/base/langflow/components/inputs/ChatInput.py @@ -0,0 +1,37 @@ +from typing import Optional, Union + +from langflow.base.io.chat import ChatComponent +from langflow.field_typing import Text +from langflow.schema import Record + + +class ChatInput(ChatComponent): + display_name = "Chat Input" + description = "Get chat inputs from the Interaction Panel." + icon = "ChatInput" + + def build_config(self): + build_config = super().build_config() + build_config["input_value"] = { + "input_types": [], + "display_name": "Message", + "multiline": True, + } + + return build_config + + def build( + self, + sender: Optional[str] = "User", + sender_name: Optional[str] = "User", + input_value: Optional[str] = None, + session_id: Optional[str] = None, + return_record: Optional[bool] = False, + ) -> Union[Text, Record]: + return super().build( + sender=sender, + sender_name=sender_name, + input_value=input_value, + session_id=session_id, + return_record=return_record, + ) diff --git a/src/backend/base/langflow/components/inputs/Prompt.py b/src/backend/base/langflow/components/inputs/Prompt.py new file mode 100644 index 000000000..3b44a6d12 --- /dev/null +++ b/src/backend/base/langflow/components/inputs/Prompt.py @@ -0,0 +1,33 @@ +from langchain_core.prompts import PromptTemplate + +from langflow.field_typing import Prompt, TemplateField, Text +from langflow.interface.custom.custom_component import CustomComponent + + +class PromptComponent(CustomComponent): + display_name: str = "Prompt" + description: str = "Create a prompt template with dynamic variables." + icon = "prompts" + + def build_config(self): + return { + "template": TemplateField(display_name="Template"), + "code": TemplateField(advanced=True), + } + + def build( + self, + template: Prompt, + **kwargs, + ) -> Text: + from langflow.base.prompts.utils import dict_values_to_string + + prompt_template = PromptTemplate.from_template(Text(template)) + kwargs = dict_values_to_string(kwargs) + kwargs = {k: "\n".join(v) if isinstance(v, list) else v for k, v in kwargs.items()} + try: + formated_prompt = prompt_template.format(**kwargs) + except Exception as exc: + raise ValueError(f"Error formatting prompt: {exc}") from exc + self.status = f'Prompt:\n"{formated_prompt}"' + return formated_prompt diff --git a/src/backend/base/langflow/components/inputs/TextInput.py b/src/backend/base/langflow/components/inputs/TextInput.py new file mode 100644 index 000000000..5408c03b2 --- /dev/null +++ b/src/backend/base/langflow/components/inputs/TextInput.py @@ -0,0 +1,32 @@ +from typing import Optional + +from langflow.base.io.text import TextComponent +from langflow.field_typing import Text + + +class TextInput(TextComponent): + display_name = "Text Input" + description = "Get text inputs from the Interaction Panel." + icon = "type" + + def build_config(self): + return { + "input_value": { + "display_name": "Value", + "input_types": ["Record", "Text"], + "info": "Text or Record to be passed as input.", + }, + "record_template": { + "display_name": "Record Template", + "multiline": True, + "info": "Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.", + "advanced": True, + }, + } + + def build( + self, + input_value: Optional[str] = "", + record_template: Optional[str] = "", + ) -> Text: + return super().build(input_value=input_value, record_template=record_template) diff --git a/src/backend/base/langflow/components/inputs/__init__.py b/src/backend/base/langflow/components/inputs/__init__.py new file mode 100644 index 000000000..4dff479de --- /dev/null +++ b/src/backend/base/langflow/components/inputs/__init__.py @@ -0,0 +1,5 @@ +from .ChatInput import ChatInput +from .Prompt import PromptComponent +from .TextInput import TextInput + +__all__ = ["ChatInput", "PromptComponent", "TextInput"] diff --git a/src/backend/langflow/components/utilities/BingSearchAPIWrapper.py b/src/backend/base/langflow/components/langchain_utilities/BingSearchAPIWrapper.py similarity index 94% rename from src/backend/langflow/components/utilities/BingSearchAPIWrapper.py rename to src/backend/base/langflow/components/langchain_utilities/BingSearchAPIWrapper.py index b9dc4a2ef..23eebee10 100644 --- a/src/backend/langflow/components/utilities/BingSearchAPIWrapper.py +++ b/src/backend/base/langflow/components/langchain_utilities/BingSearchAPIWrapper.py @@ -1,10 +1,10 @@ -from langflow import CustomComponent - # Assuming `BingSearchAPIWrapper` is a class that exists in the context # and has the appropriate methods and attributes. # We need to make sure this class is importable from the context where this code will be running. from langchain_community.utilities.bing_search import BingSearchAPIWrapper +from langflow.interface.custom.custom_component import CustomComponent + class BingSearchAPIWrapperComponent(CustomComponent): display_name = "BingSearchAPIWrapper" diff --git a/src/backend/langflow/components/utilities/GoogleSearchAPIWrapper.py b/src/backend/base/langflow/components/langchain_utilities/GoogleSearchAPIWrapper.py similarity index 91% rename from src/backend/langflow/components/utilities/GoogleSearchAPIWrapper.py rename to src/backend/base/langflow/components/langchain_utilities/GoogleSearchAPIWrapper.py index 1d7123dc3..3f2f67faf 100644 --- a/src/backend/langflow/components/utilities/GoogleSearchAPIWrapper.py +++ b/src/backend/base/langflow/components/langchain_utilities/GoogleSearchAPIWrapper.py @@ -1,7 +1,8 @@ from typing import Callable, Union from langchain_community.utilities.google_search import GoogleSearchAPIWrapper -from langflow import CustomComponent + +from langflow.interface.custom.custom_component import CustomComponent class GoogleSearchAPIWrapperComponent(CustomComponent): diff --git a/src/backend/langflow/components/utilities/GoogleSerperAPIWrapper.py b/src/backend/base/langflow/components/langchain_utilities/GoogleSerperAPIWrapper.py similarity index 83% rename from src/backend/langflow/components/utilities/GoogleSerperAPIWrapper.py rename to src/backend/base/langflow/components/langchain_utilities/GoogleSerperAPIWrapper.py index be5efe738..e70e85cf4 100644 --- a/src/backend/langflow/components/utilities/GoogleSerperAPIWrapper.py +++ b/src/backend/base/langflow/components/langchain_utilities/GoogleSerperAPIWrapper.py @@ -3,7 +3,8 @@ from typing import Dict # Assuming the existence of GoogleSerperAPIWrapper class in the serper module # If this class does not exist, you would need to create it or import the appropriate class from another module from langchain_community.utilities.google_serper import GoogleSerperAPIWrapper -from langflow import CustomComponent + +from langflow.interface.custom.custom_component import CustomComponent class GoogleSerperAPIWrapperComponent(CustomComponent): @@ -17,20 +18,23 @@ class GoogleSerperAPIWrapperComponent(CustomComponent): "show": True, "multiline": False, "password": False, - "name": "result_key_for_type", "advanced": False, "dynamic": False, "info": "", "field_type": "dict", "list": False, - "value": {"news": "news", "places": "places", "images": "images", "search": "organic"}, + "value": { + "news": "news", + "places": "places", + "images": "images", + "search": "organic", + }, }, "serper_api_key": { "display_name": "Serper API Key", "show": True, "multiline": False, "password": True, - "name": "serper_api_key", "advanced": False, "dynamic": False, "info": "", diff --git a/src/backend/langflow/components/utilities/JSONDocumentBuilder.py b/src/backend/base/langflow/components/langchain_utilities/JSONDocumentBuilder.py similarity index 95% rename from src/backend/langflow/components/utilities/JSONDocumentBuilder.py rename to src/backend/base/langflow/components/langchain_utilities/JSONDocumentBuilder.py index 33cc73d73..df783470a 100644 --- a/src/backend/langflow/components/utilities/JSONDocumentBuilder.py +++ b/src/backend/base/langflow/components/langchain_utilities/JSONDocumentBuilder.py @@ -12,7 +12,8 @@ # - **Document:** The Document containing the JSON object. from langchain_core.documents import Document -from langflow import CustomComponent + +from langflow.interface.custom.custom_component import CustomComponent from langflow.services.database.models.base import orjson_dumps @@ -20,7 +21,6 @@ class JSONDocumentBuilder(CustomComponent): display_name: str = "JSON Document Builder" description: str = "Build a Document containing a JSON object using a key and another Document page content." output_types: list[str] = ["Document"] - beta = True documentation: str = "https://docs.langflow.org/components/utilities#json-document-builder" field_config = { diff --git a/src/backend/base/langflow/components/langchain_utilities/SQLDatabase.py b/src/backend/base/langflow/components/langchain_utilities/SQLDatabase.py new file mode 100644 index 000000000..7bbbdb870 --- /dev/null +++ b/src/backend/base/langflow/components/langchain_utilities/SQLDatabase.py @@ -0,0 +1,22 @@ +from langchain_experimental.sql.base import SQLDatabase + +from langflow.interface.custom.custom_component import CustomComponent + + +class SQLDatabaseComponent(CustomComponent): + display_name = "SQLDatabase" + description = "SQL Database" + + def build_config(self): + return { + "uri": {"display_name": "URI", "info": "URI to the database."}, + } + + def clean_up_uri(self, uri: str) -> str: + if uri.startswith("postgresql://"): + uri = uri.replace("postgresql://", "postgres://") + return uri.strip() + + def build(self, uri: str) -> SQLDatabase: + uri = self.clean_up_uri(uri) + return SQLDatabase.from_uri(uri) diff --git a/src/backend/langflow/components/tools/SearchApi.py b/src/backend/base/langflow/components/langchain_utilities/SearchApi.py similarity index 87% rename from src/backend/langflow/components/tools/SearchApi.py rename to src/backend/base/langflow/components/langchain_utilities/SearchApi.py index 53da6c741..3dcd48d9f 100644 --- a/src/backend/langflow/components/tools/SearchApi.py +++ b/src/backend/base/langflow/components/langchain_utilities/SearchApi.py @@ -1,9 +1,11 @@ -from langflow import CustomComponent -from langchain.schema import Document -from langflow.services.database.models.base import orjson_dumps -from langchain_community.utilities.searchapi import SearchApiAPIWrapper from typing import Optional +from langchain_community.utilities.searchapi import SearchApiAPIWrapper + +from langflow.custom import CustomComponent +from langflow.schema.schema import Record +from langflow.services.database.models.base import orjson_dumps + class SearchApi(CustomComponent): display_name: str = "SearchApi" @@ -35,7 +37,7 @@ class SearchApi(CustomComponent): engine: str, api_key: str, params: Optional[dict] = None, - ) -> Document: + ) -> Record: if params is None: params = {} @@ -46,6 +48,6 @@ class SearchApi(CustomComponent): result = orjson_dumps(results, indent_2=False) - document = Document(page_content=result) - - return document + record = Record(data=result) + self.status = record + return record diff --git a/src/backend/langflow/components/utilities/SearxSearchWrapper.py b/src/backend/base/langflow/components/langchain_utilities/SearxSearchWrapper.py similarity index 90% rename from src/backend/langflow/components/utilities/SearxSearchWrapper.py rename to src/backend/base/langflow/components/langchain_utilities/SearxSearchWrapper.py index b406f3882..d255f34b7 100644 --- a/src/backend/langflow/components/utilities/SearxSearchWrapper.py +++ b/src/backend/base/langflow/components/langchain_utilities/SearxSearchWrapper.py @@ -1,7 +1,9 @@ -from langflow import CustomComponent -from typing import Optional, Dict +from typing import Dict, Optional + from langchain_community.utilities.searx_search import SearxSearchWrapper +from langflow.interface.custom.custom_component import CustomComponent + class SearxSearchWrapperComponent(CustomComponent): display_name = "SearxSearchWrapper" diff --git a/src/backend/langflow/components/utilities/SerpAPIWrapper.py b/src/backend/base/langflow/components/langchain_utilities/SerpAPIWrapper.py similarity index 93% rename from src/backend/langflow/components/utilities/SerpAPIWrapper.py rename to src/backend/base/langflow/components/langchain_utilities/SerpAPIWrapper.py index 924f5628d..c64a26e79 100644 --- a/src/backend/langflow/components/utilities/SerpAPIWrapper.py +++ b/src/backend/base/langflow/components/langchain_utilities/SerpAPIWrapper.py @@ -1,7 +1,8 @@ from typing import Callable, Union from langchain_community.utilities.serpapi import SerpAPIWrapper -from langflow import CustomComponent + +from langflow.interface.custom.custom_component import CustomComponent class SerpAPIWrapperComponent(CustomComponent): diff --git a/src/backend/langflow/components/utilities/WikipediaAPIWrapper.py b/src/backend/base/langflow/components/langchain_utilities/WikipediaAPIWrapper.py similarity index 93% rename from src/backend/langflow/components/utilities/WikipediaAPIWrapper.py rename to src/backend/base/langflow/components/langchain_utilities/WikipediaAPIWrapper.py index 00820881b..144792315 100644 --- a/src/backend/langflow/components/utilities/WikipediaAPIWrapper.py +++ b/src/backend/base/langflow/components/langchain_utilities/WikipediaAPIWrapper.py @@ -1,7 +1,8 @@ from typing import Callable, Union from langchain_community.utilities.wikipedia import WikipediaAPIWrapper -from langflow import CustomComponent + +from langflow.interface.custom.custom_component import CustomComponent # Assuming WikipediaAPIWrapper is a class that needs to be imported. # The import statement is not included as it is not provided in the JSON diff --git a/src/backend/langflow/components/utilities/WolframAlphaAPIWrapper.py b/src/backend/base/langflow/components/langchain_utilities/WolframAlphaAPIWrapper.py similarity index 90% rename from src/backend/langflow/components/utilities/WolframAlphaAPIWrapper.py rename to src/backend/base/langflow/components/langchain_utilities/WolframAlphaAPIWrapper.py index 2e71a161c..bc224e83c 100644 --- a/src/backend/langflow/components/utilities/WolframAlphaAPIWrapper.py +++ b/src/backend/base/langflow/components/langchain_utilities/WolframAlphaAPIWrapper.py @@ -1,7 +1,8 @@ from typing import Callable, Union from langchain_community.utilities.wolfram_alpha import WolframAlphaAPIWrapper -from langflow import CustomComponent + +from langflow.interface.custom.custom_component import CustomComponent # Since all the fields in the JSON have show=False, we will only create a basic component # without any configurable fields. diff --git a/src/backend/langflow/interface/vector_store/__init__.py b/src/backend/base/langflow/components/memories/__init__.py similarity index 100% rename from src/backend/langflow/interface/vector_store/__init__.py rename to src/backend/base/langflow/components/memories/__init__.py diff --git a/src/backend/langflow/components/llms/AmazonBedrock.py b/src/backend/base/langflow/components/model_specs/AmazonBedrockSpecs.py similarity index 93% rename from src/backend/langflow/components/llms/AmazonBedrock.py rename to src/backend/base/langflow/components/model_specs/AmazonBedrockSpecs.py index 5b931bb94..1a18f5c08 100644 --- a/src/backend/langflow/components/llms/AmazonBedrock.py +++ b/src/backend/base/langflow/components/model_specs/AmazonBedrockSpecs.py @@ -1,13 +1,15 @@ from typing import Optional from langchain.llms.base import BaseLLM -from langchain.llms.bedrock import Bedrock -from langflow import CustomComponent +from langchain_community.llms.bedrock import Bedrock + +from langflow.interface.custom.custom_component import CustomComponent class AmazonBedrockComponent(CustomComponent): display_name: str = "Amazon Bedrock" description: str = "LLM model from Amazon Bedrock." + icon = "Amazon" def build_config(self): return { diff --git a/src/backend/langflow/components/llms/AnthropicLLM.py b/src/backend/base/langflow/components/model_specs/AnthropicLLMSpecs.py similarity index 96% rename from src/backend/langflow/components/llms/AnthropicLLM.py rename to src/backend/base/langflow/components/model_specs/AnthropicLLMSpecs.py index 94c4ed8f5..2ea78162b 100644 --- a/src/backend/langflow/components/llms/AnthropicLLM.py +++ b/src/backend/base/langflow/components/model_specs/AnthropicLLMSpecs.py @@ -1,15 +1,16 @@ from typing import Optional -from langchain_community.chat_models.anthropic import ChatAnthropic from langchain.llms.base import BaseLanguageModel +from langchain_community.chat_models.anthropic import ChatAnthropic from pydantic.v1 import SecretStr -from langflow import CustomComponent +from langflow.interface.custom.custom_component import CustomComponent class AnthropicLLM(CustomComponent): display_name: str = "AnthropicLLM" description: str = "Anthropic Chat&Completion large language models." + icon = "Anthropic" def build_config(self): return { diff --git a/src/backend/langflow/components/llms/Anthropic.py b/src/backend/base/langflow/components/model_specs/AnthropicSpecs.py similarity index 93% rename from src/backend/langflow/components/llms/Anthropic.py rename to src/backend/base/langflow/components/model_specs/AnthropicSpecs.py index c1b776617..23c284888 100644 --- a/src/backend/langflow/components/llms/Anthropic.py +++ b/src/backend/base/langflow/components/model_specs/AnthropicSpecs.py @@ -3,13 +3,14 @@ from typing import Optional from langchain_community.llms.anthropic import Anthropic from pydantic.v1 import SecretStr -from langflow import CustomComponent from langflow.field_typing import BaseLanguageModel, NestedDict +from langflow.interface.custom.custom_component import CustomComponent class AnthropicComponent(CustomComponent): display_name = "Anthropic" description = "Anthropic large language models." + icon = "Anthropic" def build_config(self): return { diff --git a/src/backend/langflow/components/llms/AzureChatOpenAI.py b/src/backend/base/langflow/components/model_specs/AzureChatOpenAISpecs.py similarity index 95% rename from src/backend/langflow/components/llms/AzureChatOpenAI.py rename to src/backend/base/langflow/components/model_specs/AzureChatOpenAISpecs.py index d43abb3dc..6f468bbed 100644 --- a/src/backend/langflow/components/llms/AzureChatOpenAI.py +++ b/src/backend/base/langflow/components/model_specs/AzureChatOpenAISpecs.py @@ -1,14 +1,17 @@ from typing import Optional -from langflow import CustomComponent + from langchain.llms.base import BaseLanguageModel from langchain_community.chat_models.azure_openai import AzureChatOpenAI +from langflow.interface.custom.custom_component import CustomComponent -class AzureChatOpenAIComponent(CustomComponent): + +class AzureChatOpenAISpecsComponent(CustomComponent): display_name: str = "AzureChatOpenAI" description: str = "LLM model from Azure OpenAI." documentation: str = "https://python.langchain.com/docs/integrations/llms/azure_openai" beta = False + icon = "Azure" AZURE_OPENAI_MODELS = [ "gpt-35-turbo", diff --git a/src/backend/langflow/components/llms/BaiduQianfanChatEndpoints.py b/src/backend/base/langflow/components/model_specs/BaiduQianfanChatEndpointsSpecs.py similarity index 98% rename from src/backend/langflow/components/llms/BaiduQianfanChatEndpoints.py rename to src/backend/base/langflow/components/model_specs/BaiduQianfanChatEndpointsSpecs.py index fd7341e15..9c39acdf6 100644 --- a/src/backend/langflow/components/llms/BaiduQianfanChatEndpoints.py +++ b/src/backend/base/langflow/components/model_specs/BaiduQianfanChatEndpointsSpecs.py @@ -1,10 +1,10 @@ from typing import Optional -from langchain_community.chat_models.baidu_qianfan_endpoint import QianfanChatEndpoint from langchain.llms.base import BaseLLM +from langchain_community.chat_models.baidu_qianfan_endpoint import QianfanChatEndpoint from pydantic.v1 import SecretStr -from langflow import CustomComponent +from langflow.interface.custom.custom_component import CustomComponent class QianfanChatEndpointComponent(CustomComponent): diff --git a/src/backend/langflow/components/llms/BaiduQianfanLLMEndpoints.py b/src/backend/base/langflow/components/model_specs/BaiduQianfanLLMEndpointsSpecs.py similarity index 97% rename from src/backend/langflow/components/llms/BaiduQianfanLLMEndpoints.py rename to src/backend/base/langflow/components/model_specs/BaiduQianfanLLMEndpointsSpecs.py index 786c4516b..acbf8ba28 100644 --- a/src/backend/langflow/components/llms/BaiduQianfanLLMEndpoints.py +++ b/src/backend/base/langflow/components/model_specs/BaiduQianfanLLMEndpointsSpecs.py @@ -1,8 +1,10 @@ from typing import Optional -from langflow import CustomComponent + from langchain.llms.baidu_qianfan_endpoint import QianfanLLMEndpoint from langchain.llms.base import BaseLLM +from langflow.interface.custom.custom_component import CustomComponent + class QianfanLLMEndpointComponent(CustomComponent): display_name: str = "QianfanLLMEndpoint" diff --git a/src/backend/langflow/components/llms/ChatAnthropic.py b/src/backend/base/langflow/components/model_specs/ChatAnthropicSpecs.py similarity index 94% rename from src/backend/langflow/components/llms/ChatAnthropic.py rename to src/backend/base/langflow/components/model_specs/ChatAnthropicSpecs.py index 02866d366..a4a37b283 100644 --- a/src/backend/langflow/components/llms/ChatAnthropic.py +++ b/src/backend/base/langflow/components/model_specs/ChatAnthropicSpecs.py @@ -1,9 +1,9 @@ from typing import Callable, Optional, Union -from langchain_anthropic import ChatAnthropic +from langchain_community.chat_models.anthropic import ChatAnthropic from pydantic.v1.types import SecretStr -from langflow import CustomComponent +from langflow.custom import CustomComponent from langflow.field_typing import BaseLanguageModel @@ -11,6 +11,7 @@ class ChatAnthropicComponent(CustomComponent): display_name = "ChatAnthropic" description = "`Anthropic` chat large language models." documentation = "https://python.langchain.com/docs/modules/model_io/models/chat/integrations/anthropic" + icon = "Anthropic" def build_config(self): return { diff --git a/src/backend/langflow/components/llms/ChatLiteLLM.py b/src/backend/base/langflow/components/model_specs/ChatLiteLLMSpecs.py similarity index 72% rename from src/backend/langflow/components/llms/ChatLiteLLM.py rename to src/backend/base/langflow/components/model_specs/ChatLiteLLMSpecs.py index f2b7f7dc3..439266fbb 100644 --- a/src/backend/langflow/components/llms/ChatLiteLLM.py +++ b/src/backend/base/langflow/components/model_specs/ChatLiteLLMSpecs.py @@ -1,9 +1,8 @@ -import os from typing import Any, Callable, Dict, Optional, Union from langchain_community.chat_models.litellm import ChatLiteLLM, ChatLiteLLMException -from langflow import CustomComponent from langflow.field_typing import BaseLanguageModel +from langflow.interface.custom.custom_component import CustomComponent class ChatLiteLLMComponent(CustomComponent): @@ -27,6 +26,18 @@ class ChatLiteLLMComponent(CustomComponent): "required": False, "password": True, }, + "provider": { + "display_name": "Provider", + "info": "The provider of the API key.", + "options": [ + "OpenAI", + "Azure", + "Anthropic", + "Replicate", + "Cohere", + "OpenRouter", + ], + }, "streaming": { "display_name": "Streaming", "field_type": "bool", @@ -96,7 +107,8 @@ class ChatLiteLLMComponent(CustomComponent): def build( self, model: str, - api_key: str, + provider: str, + api_key: Optional[str] = None, streaming: bool = True, temperature: Optional[float] = 0.7, model_kwargs: Optional[Dict[str, Any]] = {}, @@ -106,7 +118,7 @@ class ChatLiteLLMComponent(CustomComponent): max_tokens: int = 256, max_retries: int = 6, verbose: bool = False, - ) -> Union[BaseLanguageModel, Callable]: + ) -> BaseLanguageModel: try: import litellm # type: ignore @@ -116,11 +128,23 @@ class ChatLiteLLMComponent(CustomComponent): raise ChatLiteLLMException( "Could not import litellm python package. " "Please install it with `pip install litellm`" ) - if api_key: - if "perplexity" in model: - os.environ["PERPLEXITYAI_API_KEY"] = api_key - elif "replicate" in model: - os.environ["REPLICATE_API_KEY"] = api_key + provider_map = { + "OpenAI": "openai_api_key", + "Azure": "azure_api_key", + "Anthropic": "anthropic_api_key", + "Replicate": "replicate_api_key", + "Cohere": "cohere_api_key", + "OpenRouter": "openrouter_api_key", + } + # Set the API key based on the provider + api_keys: dict[str, Optional[str]] = {v: None for v in provider_map.values()} + + if variable_name := provider_map.get(provider): + api_keys[variable_name] = api_key + else: + raise ChatLiteLLMException( + f"Provider {provider} is not supported. Supported providers are: {', '.join(provider_map.keys())}" + ) LLM = ChatLiteLLM( model=model, @@ -133,5 +157,11 @@ class ChatLiteLLMComponent(CustomComponent): n=n, max_tokens=max_tokens, max_retries=max_retries, + openai_api_key=api_keys["openai_api_key"], + azure_api_key=api_keys["azure_api_key"], + anthropic_api_key=api_keys["anthropic_api_key"], + replicate_api_key=api_keys["replicate_api_key"], + cohere_api_key=api_keys["cohere_api_key"], + openrouter_api_key=api_keys["openrouter_api_key"], ) return LLM diff --git a/src/backend/langflow/components/llms/ChatOllamaEndpoint.py b/src/backend/base/langflow/components/model_specs/ChatOllamaEndpointSpecs.py similarity index 98% rename from src/backend/langflow/components/llms/ChatOllamaEndpoint.py rename to src/backend/base/langflow/components/model_specs/ChatOllamaEndpointSpecs.py index 34e9e0bd7..6afde420c 100644 --- a/src/backend/langflow/components/llms/ChatOllamaEndpoint.py +++ b/src/backend/base/langflow/components/model_specs/ChatOllamaEndpointSpecs.py @@ -5,9 +5,8 @@ from langchain_community.chat_models import ChatOllama from langchain_core.language_models.chat_models import BaseChatModel # from langchain.chat_models import ChatOllama -from langflow import CustomComponent +from langflow.interface.custom.custom_component import CustomComponent -# whe When a callback component is added to Langflow, the comment must be uncommented. # from langchain.callbacks.manager import CallbackManager diff --git a/src/backend/langflow/components/llms/ChatOpenAI.py b/src/backend/base/langflow/components/model_specs/ChatOpenAISpecs.py similarity index 90% rename from src/backend/langflow/components/llms/ChatOpenAI.py rename to src/backend/base/langflow/components/model_specs/ChatOpenAISpecs.py index 9f9d61ef8..fcaf80965 100644 --- a/src/backend/langflow/components/llms/ChatOpenAI.py +++ b/src/backend/base/langflow/components/model_specs/ChatOpenAISpecs.py @@ -3,31 +3,29 @@ from typing import Optional, Union from langchain.llms import BaseLLM from langchain_community.chat_models.openai import ChatOpenAI -from langflow import CustomComponent from langflow.field_typing import BaseLanguageModel, NestedDict +from langflow.interface.custom.custom_component import CustomComponent class ChatOpenAIComponent(CustomComponent): display_name = "ChatOpenAI" description = "`OpenAI` Chat large language models API." + icon = "OpenAI" def build_config(self): return { "max_tokens": { "display_name": "Max Tokens", - "field_type": "int", "advanced": False, "required": False, }, "model_kwargs": { "display_name": "Model Kwargs", - "field_type": "NestedDict", "advanced": True, "required": False, }, "model_name": { "display_name": "Model Name", - "field_type": "str", "advanced": False, "required": False, "options": [ @@ -41,7 +39,6 @@ class ChatOpenAIComponent(CustomComponent): }, "openai_api_base": { "display_name": "OpenAI API Base", - "field_type": "str", "advanced": False, "required": False, "info": ( @@ -51,14 +48,12 @@ class ChatOpenAIComponent(CustomComponent): }, "openai_api_key": { "display_name": "OpenAI API Key", - "field_type": "str", "advanced": False, "required": False, "password": True, }, "temperature": { "display_name": "Temperature", - "field_type": "float", "advanced": False, "required": False, "value": 0.7, diff --git a/src/backend/langflow/components/llms/ChatVertexAI.py b/src/backend/base/langflow/components/model_specs/ChatVertexAISpecs.py similarity index 96% rename from src/backend/langflow/components/llms/ChatVertexAI.py rename to src/backend/base/langflow/components/model_specs/ChatVertexAISpecs.py index 66235a1d8..fd8b5b427 100644 --- a/src/backend/langflow/components/llms/ChatVertexAI.py +++ b/src/backend/base/langflow/components/model_specs/ChatVertexAISpecs.py @@ -3,13 +3,15 @@ from typing import List, Optional, Union from langchain.llms import BaseLLM from langchain_community.chat_models.vertexai import ChatVertexAI from langchain_core.messages.base import BaseMessage -from langflow import CustomComponent + from langflow.field_typing import BaseLanguageModel +from langflow.interface.custom.custom_component import CustomComponent class ChatVertexAIComponent(CustomComponent): display_name = "ChatVertexAI" description = "`Vertex AI` Chat large language models API." + icon = "VertexAI" def build_config(self): return { diff --git a/src/backend/langflow/components/llms/Cohere.py b/src/backend/base/langflow/components/model_specs/CohereSpecs.py similarity index 91% rename from src/backend/langflow/components/llms/Cohere.py rename to src/backend/base/langflow/components/model_specs/CohereSpecs.py index 3b74fc9b4..eeda381a4 100644 --- a/src/backend/langflow/components/llms/Cohere.py +++ b/src/backend/base/langflow/components/model_specs/CohereSpecs.py @@ -1,12 +1,14 @@ from langchain_community.llms.cohere import Cohere from langchain_core.language_models.base import BaseLanguageModel -from langflow import CustomComponent + +from langflow.interface.custom.custom_component import CustomComponent class CohereComponent(CustomComponent): display_name = "Cohere" description = "Cohere large language models." documentation = "https://python.langchain.com/docs/modules/model_io/models/llms/integrations/cohere" + icon = "Cohere" def build_config(self): return { diff --git a/src/backend/base/langflow/components/model_specs/GoogleGenerativeAISpecs.py b/src/backend/base/langflow/components/model_specs/GoogleGenerativeAISpecs.py new file mode 100644 index 000000000..8a3894292 --- /dev/null +++ b/src/backend/base/langflow/components/model_specs/GoogleGenerativeAISpecs.py @@ -0,0 +1,74 @@ +from typing import Optional + +from langchain_google_genai import ChatGoogleGenerativeAI # type: ignore +from pydantic.v1.types import SecretStr + +from langflow.field_typing import BaseLanguageModel, RangeSpec +from langflow.interface.custom.custom_component import CustomComponent + + +class GoogleGenerativeAIComponent(CustomComponent): + display_name: str = "Google Generative AI" + description: str = "A component that uses Google Generative AI to generate text." + documentation: str = "http://docs.langflow.org/components/custom" + icon = "Google" + + def build_config(self): + return { + "google_api_key": { + "display_name": "Google API Key", + "info": "The Google API Key to use for the Google Generative AI.", + }, + "max_output_tokens": { + "display_name": "Max Output Tokens", + "info": "The maximum number of tokens to generate.", + }, + "temperature": { + "display_name": "Temperature", + "info": "Run inference with this temperature. Must by in the closed interval [0.0, 1.0].", + }, + "top_k": { + "display_name": "Top K", + "info": "Decode using top-k sampling: consider the set of top_k most probable tokens. Must be positive.", + "rangeSpec": RangeSpec(min=0, max=2, step=0.1), + "advanced": True, + }, + "top_p": { + "display_name": "Top P", + "info": "The maximum cumulative probability of tokens to consider when sampling.", + "advanced": True, + }, + "n": { + "display_name": "N", + "info": "Number of chat completions to generate for each prompt. Note that the API may not return the full n completions if duplicates are generated.", + "advanced": True, + }, + "model": { + "display_name": "Model", + "info": "The name of the model to use. Supported examples: gemini-pro", + "options": ["gemini-pro", "gemini-pro-vision"], + }, + "code": { + "advanced": True, + }, + } + + def build( + self, + google_api_key: str, + model: str, + max_output_tokens: Optional[int] = None, + temperature: float = 0.1, + top_k: Optional[int] = None, + top_p: Optional[float] = None, + n: Optional[int] = 1, + ) -> BaseLanguageModel: + return ChatGoogleGenerativeAI( + model=model, + max_output_tokens=max_output_tokens or None, # type: ignore + temperature=temperature, + top_k=top_k or None, + top_p=top_p or None, # type: ignore + n=n or 1, + google_api_key=SecretStr(google_api_key), + ) diff --git a/src/backend/langflow/components/llms/HuggingFaceEndpoints.py b/src/backend/base/langflow/components/model_specs/HuggingFaceEndpointsSpecs.py similarity index 93% rename from src/backend/langflow/components/llms/HuggingFaceEndpoints.py rename to src/backend/base/langflow/components/model_specs/HuggingFaceEndpointsSpecs.py index 579e3c0b3..c3e74b1bd 100644 --- a/src/backend/langflow/components/llms/HuggingFaceEndpoints.py +++ b/src/backend/base/langflow/components/model_specs/HuggingFaceEndpointsSpecs.py @@ -2,12 +2,14 @@ from typing import Optional from langchain.llms.base import BaseLLM from langchain.llms.huggingface_endpoint import HuggingFaceEndpoint -from langflow import CustomComponent + +from langflow.interface.custom.custom_component import CustomComponent class HuggingFaceEndpointsComponent(CustomComponent): display_name: str = "Hugging Face Inference API" description: str = "LLM model from Hugging Face Inference API." + icon = "HuggingFace" def build_config(self): return { diff --git a/src/backend/langflow/components/llms/OllamaLLM.py b/src/backend/base/langflow/components/model_specs/OllamaLLMSpecs.py similarity index 98% rename from src/backend/langflow/components/llms/OllamaLLM.py rename to src/backend/base/langflow/components/model_specs/OllamaLLMSpecs.py index eb5c52975..8d94467db 100644 --- a/src/backend/langflow/components/llms/OllamaLLM.py +++ b/src/backend/base/langflow/components/model_specs/OllamaLLMSpecs.py @@ -3,7 +3,7 @@ from typing import List, Optional from langchain.llms.base import BaseLLM from langchain_community.llms.ollama import Ollama -from langflow import CustomComponent +from langflow.interface.custom.custom_component import CustomComponent class OllamaLLM(CustomComponent): diff --git a/src/backend/langflow/components/llms/VertexAI.py b/src/backend/base/langflow/components/model_specs/VertexAISpecs.py similarity index 96% rename from src/backend/langflow/components/llms/VertexAI.py rename to src/backend/base/langflow/components/model_specs/VertexAISpecs.py index 008451bc8..f186f2ed0 100644 --- a/src/backend/langflow/components/llms/VertexAI.py +++ b/src/backend/base/langflow/components/model_specs/VertexAISpecs.py @@ -1,12 +1,15 @@ -from langflow import CustomComponent +from typing import Callable, Dict, Optional, Union + from langchain.llms import BaseLLM -from typing import Optional, Union, Callable, Dict from langchain_community.llms.vertexai import VertexAI +from langflow.interface.custom.custom_component import CustomComponent + class VertexAIComponent(CustomComponent): display_name = "VertexAI" description = "Google Vertex AI large language models" + icon = "VertexAI" def build_config(self): return { diff --git a/src/backend/base/langflow/components/model_specs/__init__.py b/src/backend/base/langflow/components/model_specs/__init__.py new file mode 100644 index 000000000..7bf6c2881 --- /dev/null +++ b/src/backend/base/langflow/components/model_specs/__init__.py @@ -0,0 +1,35 @@ +from .AmazonBedrockSpecs import AmazonBedrockComponent +from .AnthropicLLMSpecs import AnthropicLLM +from .AnthropicSpecs import AnthropicComponent +from .AzureChatOpenAISpecs import AzureChatOpenAISpecsComponent +from .BaiduQianfanChatEndpointsSpecs import QianfanChatEndpointComponent +from .BaiduQianfanLLMEndpointsSpecs import QianfanLLMEndpointComponent +from .ChatAnthropicSpecs import ChatAnthropicComponent +from .ChatLiteLLMSpecs import ChatLiteLLMComponent +from .ChatOllamaEndpointSpecs import ChatOllamaComponent +from .ChatOpenAISpecs import ChatOpenAIComponent +from .ChatVertexAISpecs import ChatVertexAIComponent +from .CohereSpecs import CohereComponent +from .GoogleGenerativeAISpecs import GoogleGenerativeAIComponent +from .HuggingFaceEndpointsSpecs import HuggingFaceEndpointsComponent +from .OllamaLLMSpecs import OllamaLLM +from .VertexAISpecs import VertexAIComponent + +__all__ = [ + "AmazonBedrockComponent", + "AnthropicLLM", + "AnthropicComponent", + "AzureChatOpenAISpecsComponent", + "QianfanChatEndpointComponent", + "QianfanLLMEndpointComponent", + "ChatAnthropicComponent", + "ChatLiteLLMComponent", + "ChatOllamaComponent", + "ChatOpenAIComponent", + "ChatVertexAIComponent", + "CohereComponent", + "GoogleGenerativeAIComponent", + "HuggingFaceEndpointsComponent", + "OllamaLLM", + "VertexAIComponent", +] diff --git a/src/backend/base/langflow/components/models/AmazonBedrockModel.py b/src/backend/base/langflow/components/models/AmazonBedrockModel.py new file mode 100644 index 000000000..1015f1684 --- /dev/null +++ b/src/backend/base/langflow/components/models/AmazonBedrockModel.py @@ -0,0 +1,99 @@ +from typing import Optional + +from langchain_community.chat_models.bedrock import BedrockChat + +from langflow.base.constants import STREAM_INFO_TEXT +from langflow.base.models.model import LCModelComponent +from langflow.field_typing import Text + + +class AmazonBedrockComponent(LCModelComponent): + display_name: str = "Amazon Bedrock" + description: str = "Generate text using Amazon Bedrock LLMs." + icon = "Amazon" + field_order = [ + "model_id", + "credentials_profile_name", + "region_name", + "model_kwargs", + "endpoint_url", + "cache", + "stream", + "input_value", + "system_message", + ] + + def build_config(self): + return { + "model_id": { + "display_name": "Model Id", + "options": [ + "amazon.titan-text-express-v1", + "amazon.titan-text-lite-v1", + "amazon.titan-embed-text-v1", + "amazon.titan-embed-image-v1", + "amazon.titan-image-generator-v1", + "anthropic.claude-v2", + "anthropic.claude-v2:1", + "anthropic.claude-3-sonnet-20240229-v1:0", + "anthropic.claude-3-haiku-20240307-v1:0", + "anthropic.claude-instant-v1", + "ai21.j2-mid-v1", + "ai21.j2-ultra-v1", + "cohere.command-text-v14", + "cohere.command-light-text-v14", + "cohere.embed-english-v3", + "cohere.embed-multilingual-v3", + "meta.llama2-13b-chat-v1", + "meta.llama2-70b-chat-v1", + "mistral.mistral-7b-instruct-v0:2", + "mistral.mixtral-8x7b-instruct-v0:1", + ], + }, + "credentials_profile_name": {"display_name": "Credentials Profile Name"}, + "endpoint_url": {"display_name": "Endpoint URL"}, + "region_name": {"display_name": "Region Name"}, + "model_kwargs": { + "display_name": "Model Kwargs", + "advanced": True, + }, + "cache": {"display_name": "Cache"}, + "input_value": {"display_name": "Input"}, + "system_message": { + "display_name": "System Message", + "info": "System message to pass to the model.", + "advanced": True, + }, + "stream": { + "display_name": "Stream", + "info": STREAM_INFO_TEXT, + "advanced": True, + }, + } + + def build( + self, + input_value: Text, + system_message: Optional[str] = None, + model_id: str = "anthropic.claude-instant-v1", + credentials_profile_name: Optional[str] = None, + region_name: Optional[str] = None, + model_kwargs: Optional[dict] = None, + endpoint_url: Optional[str] = None, + cache: Optional[bool] = None, + stream: bool = False, + ) -> Text: + try: + output = BedrockChat( + credentials_profile_name=credentials_profile_name, + model_id=model_id, + region_name=region_name, + model_kwargs=model_kwargs, + endpoint_url=endpoint_url, + streaming=stream, + cache=cache, + ) # type: ignore + except Exception as e: + raise ValueError("Could not connect to AmazonBedrock API.") from e + + return self.get_chat_result(output, stream, input_value, system_message) diff --git a/src/backend/base/langflow/components/models/AnthropicModel.py b/src/backend/base/langflow/components/models/AnthropicModel.py new file mode 100644 index 000000000..1e5a7aec5 --- /dev/null +++ b/src/backend/base/langflow/components/models/AnthropicModel.py @@ -0,0 +1,106 @@ +from typing import Optional + +from langchain_anthropic.chat_models import ChatAnthropic +from pydantic.v1 import SecretStr + +from langflow.base.constants import STREAM_INFO_TEXT +from langflow.base.models.model import LCModelComponent +from langflow.field_typing import Text + + +class AnthropicLLM(LCModelComponent): + display_name: str = "Anthropic" + description: str = "Generate text using Anthropic Chat&Completion LLMs." + icon = "Anthropic" + + field_order = [ + "model", + "anthropic_api_key", + "max_tokens", + "temperature", + "anthropic_api_url", + "input_value", + "system_message", + "stream", + ] + + def build_config(self): + return { + "model": { + "display_name": "Model Name", + "options": [ + "claude-3-opus-20240229", + "claude-3-sonnet-20240229", + "claude-3-haiku-20240307", + "claude-2.1", + "claude-2.0", + "claude-instant-1.2", + "claude-instant-1", + ], + "info": "https://python.langchain.com/docs/integrations/chat/anthropic", + "required": True, + "value": "claude-3-opus-20240229", + }, + "anthropic_api_key": { + "display_name": "Anthropic API Key", + "required": True, + "password": True, + "info": "Your Anthropic API key.", + }, + "max_tokens": { + "display_name": "Max Tokens", + "field_type": "int", + "advanced": True, + "value": 256, + }, + "temperature": { + "display_name": "Temperature", + "field_type": "float", + "value": 0.1, + }, + "anthropic_api_url": { + "display_name": "Anthropic API URL", + "advanced": True, + "info": "Endpoint of the Anthropic API. Defaults to 'https://api.anthropic.com' if not specified.", + }, + "code": {"show": False}, + "input_value": {"display_name": "Input"}, + "stream": { + "display_name": "Stream", + "advanced": True, + "info": STREAM_INFO_TEXT, + }, + "system_message": { + "display_name": "System Message", + "advanced": True, + "info": "System message to pass to the model.", + }, + } + + def build( + self, + model: str, + input_value: Text, + system_message: Optional[str] = None, + anthropic_api_key: Optional[str] = None, + max_tokens: Optional[int] = None, + temperature: Optional[float] = None, + anthropic_api_url: Optional[str] = None, + stream: bool = False, + ) -> Text: + # Set default API endpoint if not provided + if not anthropic_api_url: + anthropic_api_url = "https://api.anthropic.com" + + try: + output = ChatAnthropic( + model_name=model, + anthropic_api_key=(SecretStr(anthropic_api_key) if anthropic_api_key else None), + max_tokens_to_sample=max_tokens, # type: ignore + temperature=temperature, + anthropic_api_url=anthropic_api_url, + ) + except Exception as e: + raise ValueError("Could not connect to Anthropic API.") from e + + return self.get_chat_result(output, stream, input_value, system_message) diff --git a/src/backend/base/langflow/components/models/AzureOpenAIModel.py b/src/backend/base/langflow/components/models/AzureOpenAIModel.py new file mode 100644 index 000000000..9e1d32bb7 --- /dev/null +++ b/src/backend/base/langflow/components/models/AzureOpenAIModel.py @@ -0,0 +1,121 @@ +from typing import Optional + +from langchain.llms.base import BaseLanguageModel +from langchain_openai import AzureChatOpenAI + +from langflow.base.constants import STREAM_INFO_TEXT +from langflow.base.models.model import LCModelComponent +from langflow.field_typing import Text + + +class AzureChatOpenAIComponent(LCModelComponent): + display_name: str = "Azure OpenAI" + description: str = "Generate text using Azure OpenAI LLMs." + documentation: str = "https://python.langchain.com/docs/integrations/llms/azure_openai" + beta = False + icon = "Azure" + + field_order = [ + "model", + "azure_endpoint", + "azure_deployment", + "api_version", + "api_key", + "temperature", + "max_tokens", + "input_value", + "system_message", + "stream", + ] + + AZURE_OPENAI_MODELS = [ + "gpt-35-turbo", + "gpt-35-turbo-16k", + "gpt-35-turbo-instruct", + "gpt-4", + "gpt-4-32k", + "gpt-4-vision", + ] + + AZURE_OPENAI_API_VERSIONS = [ + "2023-03-15-preview", + "2023-05-15", + "2023-06-01-preview", + "2023-07-01-preview", + "2023-08-01-preview", + "2023-09-01-preview", + "2023-12-01-preview", + ] + + def build_config(self): + return { + "model": { + "display_name": "Model Name", + "value": self.AZURE_OPENAI_MODELS[0], + "options": self.AZURE_OPENAI_MODELS, + }, + "azure_endpoint": { + "display_name": "Azure Endpoint", + "info": "Your Azure endpoint, including the resource.. Example: `https://example-resource.azure.openai.com/`", + }, + "azure_deployment": { + "display_name": "Deployment Name", + }, + "api_version": { + "display_name": "API Version", + "options": self.AZURE_OPENAI_API_VERSIONS, + "value": self.AZURE_OPENAI_API_VERSIONS[-1], + "advanced": True, + }, + "api_key": {"display_name": "API Key", "password": True}, + "temperature": { + "display_name": "Temperature", + "value": 0.7, + }, + "max_tokens": { + "display_name": "Max Tokens", + "value": 1000, + "advanced": True, + "info": "Maximum number of tokens to generate.", + }, + "code": {"show": False}, + "input_value": {"display_name": "Input"}, + "stream": { + "display_name": "Stream", + "info": STREAM_INFO_TEXT, + "advanced": True, + }, + "system_message": { + "display_name": "System Message", + "info": "System message to pass to the model.", + "advanced": True, + }, + } + + def build( + self, + model: str, + azure_endpoint: str, + input_value: Text, + azure_deployment: str, + api_version: str, + api_key: str, + temperature: float, + system_message: Optional[str] = None, + max_tokens: Optional[int] = 1000, + stream: bool = False, + ) -> BaseLanguageModel: + try: + output = AzureChatOpenAI( + model=model, + azure_endpoint=azure_endpoint, + azure_deployment=azure_deployment, + api_version=api_version, + api_key=api_key, + temperature=temperature, + max_tokens=max_tokens, + ) + except Exception as e: + raise ValueError("Could not connect to AzureOpenAI API.") from e + + return self.get_chat_result(output, stream, input_value, system_message) diff --git a/src/backend/base/langflow/components/models/BaiduQianfanChatModel.py b/src/backend/base/langflow/components/models/BaiduQianfanChatModel.py new file mode 100644 index 000000000..f5e6497d0 --- /dev/null +++ b/src/backend/base/langflow/components/models/BaiduQianfanChatModel.py @@ -0,0 +1,123 @@ +from typing import Optional + +from langchain_community.chat_models.baidu_qianfan_endpoint import QianfanChatEndpoint +from pydantic.v1 import SecretStr + +from langflow.base.constants import STREAM_INFO_TEXT +from langflow.base.models.model import LCModelComponent +from langflow.field_typing import Text + + +class QianfanChatEndpointComponent(LCModelComponent): + display_name: str = "Qianfan" + description: str = "Generate text using Baidu Qianfan LLMs." + documentation: str = "https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint." + icon = "BaiduQianfan" + + field_order = [ + "model", + "qianfan_ak", + "qianfan_sk", + "top_p", + "temperature", + "penalty_score", + "endpoint", + "input_value", + "system_message", + "stream", + ] + + def build_config(self): + return { + "model": { + "display_name": "Model Name", + "options": [ + "ERNIE-Bot", + "ERNIE-Bot-turbo", + "BLOOMZ-7B", + "Llama-2-7b-chat", + "Llama-2-13b-chat", + "Llama-2-70b-chat", + "Qianfan-BLOOMZ-7B-compressed", + "Qianfan-Chinese-Llama-2-7B", + "ChatGLM2-6B-32K", + "AquilaChat-7B", + ], + "info": "https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint", + "value": "ERNIE-Bot-turbo", + }, + "qianfan_ak": { + "display_name": "Qianfan Ak", + "password": True, + "info": "which you could get from https://cloud.baidu.com/product/wenxinworkshop", + }, + "qianfan_sk": { + "display_name": "Qianfan Sk", + "password": True, + "info": "which you could get from https://cloud.baidu.com/product/wenxinworkshop", + }, + "top_p": { + "display_name": "Top p", + "field_type": "float", + "info": "Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo", + "value": 0.8, + "advanced": True, + }, + "temperature": { + "display_name": "Temperature", + "field_type": "float", + "info": "Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo", + "value": 0.95, + }, + "penalty_score": { + "display_name": "Penalty Score", + "field_type": "float", + "info": "Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo", + "value": 1.0, + "advanced": True, + }, + "endpoint": { + "display_name": "Endpoint", + "info": "Endpoint of the Qianfan LLM, required if custom model used.", + }, + "code": {"show": False}, + "input_value": {"display_name": "Input"}, + "stream": { + "display_name": "Stream", + "info": STREAM_INFO_TEXT, + "advanced": True, + }, + "system_message": { + "display_name": "System Message", + "info": "System message to pass to the model.", + "advanced": True, + }, + } + + def build( + self, + input_value: Text, + qianfan_ak: str, + qianfan_sk: str, + model: str, + top_p: Optional[float] = None, + temperature: Optional[float] = None, + penalty_score: Optional[float] = None, + endpoint: Optional[str] = None, + stream: bool = False, + system_message: Optional[str] = None, + ) -> Text: + try: + output = QianfanChatEndpoint( # type: ignore + model=model, + qianfan_ak=SecretStr(qianfan_ak) if qianfan_ak else None, + qianfan_sk=SecretStr(qianfan_sk) if qianfan_sk else None, + top_p=top_p, + temperature=temperature, + penalty_score=penalty_score, + endpoint=endpoint, + ) + except Exception as e: + raise ValueError("Could not connect to Baidu Qianfan API.") from e + + return self.get_chat_result(output, stream, input_value, system_message) diff --git a/src/backend/base/langflow/components/models/ChatLiteLLMModel.py b/src/backend/base/langflow/components/models/ChatLiteLLMModel.py new file mode 100644 index 000000000..5266c6935 --- /dev/null +++ b/src/backend/base/langflow/components/models/ChatLiteLLMModel.py @@ -0,0 +1,191 @@ +from typing import Any, Dict, Optional + +from langchain_community.chat_models.litellm import ChatLiteLLM, ChatLiteLLMException + +from langflow.base.constants import STREAM_INFO_TEXT +from langflow.base.models.model import LCModelComponent +from langflow.field_typing import BaseLanguageModel, Text + + +class ChatLiteLLMModelComponent(LCModelComponent): + display_name = "LiteLLM" + description = "`LiteLLM` collection of large language models." + documentation = "https://python.langchain.com/docs/integrations/chat/litellm" + field_order = [ + "model", + "api_key", + "provider", + "temperature", + "model_kwargs", + "top_p", + "top_k", + "n", + "max_tokens", + "max_retries", + "verbose", + "stream", + "input_value", + "system_message", + ] + + def build_config(self): + return { + "model": { + "display_name": "Model name", + "field_type": "str", + "advanced": False, + "required": True, + "info": "The name of the model to use. For example, `gpt-3.5-turbo`.", + }, + "api_key": { + "display_name": "API key", + "field_type": "str", + "advanced": False, + "required": False, + "password": True, + }, + "provider": { + "display_name": "Provider", + "info": "The provider of the API key.", + "options": [ + "OpenAI", + "Azure", + "Anthropic", + "Replicate", + "Cohere", + "OpenRouter", + ], + }, + "temperature": { + "display_name": "Temperature", + "field_type": "float", + "advanced": False, + "required": False, + "default": 0.7, + }, + "model_kwargs": { + "display_name": "Model kwargs", + "field_type": "dict", + "advanced": True, + "required": False, + "default": {}, + }, + "top_p": { + "display_name": "Top p", + "field_type": "float", + "advanced": True, + "required": False, + }, + "top_k": { + "display_name": "Top k", + "field_type": "int", + "advanced": True, + "required": False, + }, + "n": { + "display_name": "N", + "field_type": "int", + "advanced": True, + "required": False, + "info": "Number of chat completions to generate for each prompt. " + "Note that the API may not return the full n completions if duplicates are generated.", + "default": 1, + }, + "max_tokens": { + "display_name": "Max tokens", + "field_type": "int", + "advanced": False, + "required": False, + "default": 256, + "info": "The maximum number of tokens to generate for each chat completion.", + }, + "max_retries": { + "display_name": "Max retries", + "field_type": "int", + "advanced": True, + "required": False, + "default": 6, + }, + "verbose": { + "display_name": "Verbose", + "field_type": "bool", + "advanced": True, + "required": False, + "default": False, + }, + "input_value": {"display_name": "Input"}, + "stream": { + "display_name": "Stream", + "info": STREAM_INFO_TEXT, + "advanced": True, + }, + "system_message": { + "display_name": "System Message", + "info": "System message to pass to the model.", + "advanced": True, + }, + } + + def build( + self, + input_value: Text, + model: str, + provider: str, + api_key: Optional[str] = None, + stream: bool = False, + temperature: Optional[float] = 0.7, + model_kwargs: Optional[Dict[str, Any]] = {}, + top_p: Optional[float] = None, + top_k: Optional[int] = None, + n: int = 1, + max_tokens: int = 256, + max_retries: int = 6, + verbose: bool = False, + system_message: Optional[str] = None, + ) -> BaseLanguageModel: + try: + import litellm # type: ignore + + litellm.drop_params = True + litellm.set_verbose = verbose + except ImportError: + raise ChatLiteLLMException( + "Could not import litellm python package. " "Please install it with `pip install litellm`" + ) + provider_map = { + "OpenAI": "openai_api_key", + "Azure": "azure_api_key", + "Anthropic": "anthropic_api_key", + "Replicate": "replicate_api_key", + "Cohere": "cohere_api_key", + "OpenRouter": "openrouter_api_key", + } + # Set the API key based on the provider + api_keys: dict[str, Optional[str]] = {v: None for v in provider_map.values()} + + if variable_name := provider_map.get(provider): + api_keys[variable_name] = api_key + else: + raise ChatLiteLLMException( + f"Provider {provider} is not supported. Supported providers are: {', '.join(provider_map.keys())}" + ) + + output = ChatLiteLLM( + model=model, + client=None, + streaming=stream, + temperature=temperature, + model_kwargs=model_kwargs if model_kwargs is not None else {}, + top_p=top_p, + top_k=top_k, + n=n, + max_tokens=max_tokens, + max_retries=max_retries, + openai_api_key=api_keys["openai_api_key"], + azure_api_key=api_keys["azure_api_key"], + anthropic_api_key=api_keys["anthropic_api_key"], + replicate_api_key=api_keys["replicate_api_key"], + cohere_api_key=api_keys["cohere_api_key"], + openrouter_api_key=api_keys["openrouter_api_key"], + ) + return self.get_chat_result(output, stream, input_value, system_message) diff --git a/src/backend/base/langflow/components/models/CohereModel.py b/src/backend/base/langflow/components/models/CohereModel.py new file mode 100644 index 000000000..665aacc13 --- /dev/null +++ b/src/backend/base/langflow/components/models/CohereModel.py @@ -0,0 +1,73 @@ +from typing import Optional + +from langchain_community.chat_models.cohere import ChatCohere +from pydantic.v1 import SecretStr +from langflow.field_typing import Text +from langflow.base.constants import STREAM_INFO_TEXT +from langflow.base.models.model import LCModelComponent + + +class CohereComponent(LCModelComponent): + display_name = "Cohere" + description = "Generate text using Cohere LLMs." + documentation = "https://python.langchain.com/docs/modules/model_io/models/llms/integrations/cohere" + + icon = "Cohere" + + field_order = [ + "cohere_api_key", + "max_tokens", + "temperature", + "input_value", + "system_message", + "stream", + ] + + def build_config(self): + return { + "cohere_api_key": { + "display_name": "Cohere API Key", + "type": "password", + "password": True, + "required": True, + }, + "max_tokens": { + "display_name": "Max Tokens", + "advanced": True, + "default": 256, + "type": "int", + "show": True, + }, + "temperature": { + "display_name": "Temperature", + "default": 0.75, + "type": "float", + "show": True, + }, + "input_value": {"display_name": "Input"}, + "stream": { + "display_name": "Stream", + "info": STREAM_INFO_TEXT, + "advanced": True, + }, + "system_message": { + "display_name": "System Message", + "info": "System message to pass to the model.", + "advanced": True, + }, + } + + def build( + self, + cohere_api_key: str, + input_value: Text, + temperature: float = 0.75, + stream: bool = False, + system_message: Optional[str] = None, + ) -> Text: + api_key = SecretStr(cohere_api_key) + output = ChatCohere( # type: ignore + cohere_api_key=api_key, + temperature=temperature, + ) + return self.get_chat_result(output, stream, input_value, system_message) diff --git a/src/backend/base/langflow/components/models/GoogleGenerativeAIModel.py b/src/backend/base/langflow/components/models/GoogleGenerativeAIModel.py new file mode 100644 index 000000000..0c2b8eef5 --- /dev/null +++ b/src/backend/base/langflow/components/models/GoogleGenerativeAIModel.py @@ -0,0 +1,102 @@ +from typing import Optional + +from langchain_google_genai import ChatGoogleGenerativeAI +from pydantic.v1 import SecretStr +from langflow.field_typing import Text, RangeSpec +from langflow.base.constants import STREAM_INFO_TEXT +from langflow.base.models.model import LCModelComponent + + +class GoogleGenerativeAIComponent(LCModelComponent): + display_name: str = "Google Generative AI" + description: str = "Generate text using Google Generative AI." + icon = "GoogleGenerativeAI" + + field_order = [ + "google_api_key", + "model", + "max_output_tokens", + "temperature", + "top_k", + "top_p", + "n", + "input_value", + "system_message", + "stream", + ] + + def build_config(self): + return { + "google_api_key": { + "display_name": "Google API Key", + "info": "The Google API Key to use for the Google Generative AI.", + }, + "max_output_tokens": { + "display_name": "Max Output Tokens", + "info": "The maximum number of tokens to generate.", + "advanced": True, + }, + "temperature": { + "display_name": "Temperature", + "info": "Run inference with this temperature. Must by in the closed interval [0.0, 1.0].", + }, + "top_k": { + "display_name": "Top K", + "info": "Decode using top-k sampling: consider the set of top_k most probable tokens. Must be positive.", + "rangeSpec": RangeSpec(min=0, max=2, step=0.1), + "advanced": True, + }, + "top_p": { + "display_name": "Top P", + "info": "The maximum cumulative probability of tokens to consider when sampling.", + "advanced": True, + }, + "n": { + "display_name": "N", + "info": "Number of chat completions to generate for each prompt. Note that the API may not return the full n completions if duplicates are generated.", + "advanced": True, + }, + "model": { + "display_name": "Model", + "info": "The name of the model to use. Supported examples: gemini-pro", + "options": ["gemini-pro", "gemini-pro-vision"], + }, + "code": { + "advanced": True, + }, + "input_value": {"display_name": "Input", "info": "The input to the model."}, + "stream": { + "display_name": "Stream", + "info": STREAM_INFO_TEXT, + "advanced": True, + }, + "system_message": { + "display_name": "System Message", + "info": "System message to pass to the model.", + "advanced": True, + }, + } + + def build( + self, + google_api_key: str, + model: str, + input_value: Text, + max_output_tokens: Optional[int] = None, + temperature: float = 0.1, + top_k: Optional[int] = None, + top_p: Optional[float] = None, + n: Optional[int] = 1, + stream: bool = False, + system_message: Optional[str] = None, + ) -> Text: + output = ChatGoogleGenerativeAI( + model=model, + max_output_tokens=max_output_tokens or None, # type: ignore + temperature=temperature, + top_k=top_k or None, + top_p=top_p or None, # type: ignore + n=n or 1, + google_api_key=SecretStr(google_api_key), + ) + return self.get_chat_result(output, stream, input_value, system_message) diff --git a/src/backend/base/langflow/components/models/HuggingFaceModel.py b/src/backend/base/langflow/components/models/HuggingFaceModel.py new file mode 100644 index 000000000..19750ef9f --- /dev/null +++ b/src/backend/base/langflow/components/models/HuggingFaceModel.py @@ -0,0 +1,74 @@ +from typing import Optional + +from langchain_community.chat_models.huggingface import ChatHuggingFace +from langchain_community.llms.huggingface_endpoint import HuggingFaceEndpoint +from langflow.field_typing import Text +from langflow.base.constants import STREAM_INFO_TEXT +from langflow.base.models.model import LCModelComponent + + +class HuggingFaceEndpointsComponent(LCModelComponent): + display_name: str = "Hugging Face API" + description: str = "Generate text using Hugging Face Inference APIs." + icon = "HuggingFace" + + field_order = [ + "endpoint_url", + "task", + "huggingfacehub_api_token", + "model_kwargs", + "input_value", + "system_message", + "stream", + ] + + def build_config(self): + return { + "endpoint_url": {"display_name": "Endpoint URL", "password": True}, + "task": { + "display_name": "Task", + "options": ["text2text-generation", "text-generation", "summarization"], + }, + "huggingfacehub_api_token": {"display_name": "API token", "password": True}, + "model_kwargs": { + "display_name": "Model Keyword Arguments", + "field_type": "code", + "advanced": True, + }, + "code": {"show": False}, + "input_value": {"display_name": "Input"}, + "stream": { + "display_name": "Stream", + "info": STREAM_INFO_TEXT, + "advanced": True, + }, + "system_message": { + "display_name": "System Message", + "info": "System message to pass to the model.", + "advanced": True, + }, + } + + def build( + self, + input_value: Text, + endpoint_url: str, + model: Optional[str] = None, + task: str = "text2text-generation", + huggingfacehub_api_token: Optional[str] = None, + model_kwargs: Optional[dict] = None, + stream: bool = False, + system_message: Optional[str] = None, + ) -> Text: + try: + llm = HuggingFaceEndpoint( # type: ignore + endpoint_url=endpoint_url, + task=task, + huggingfacehub_api_token=huggingfacehub_api_token, + model_kwargs=model_kwargs or {}, + model=model or "", + ) + except Exception as e: + raise ValueError("Could not connect to HuggingFace Endpoints API.") from e + output = ChatHuggingFace(llm=llm) + return self.get_chat_result(output, stream, input_value, system_message) diff --git a/src/backend/base/langflow/components/models/OllamaModel.py b/src/backend/base/langflow/components/models/OllamaModel.py new file mode 100644 index 000000000..41d75ba3e --- /dev/null +++ b/src/backend/base/langflow/components/models/OllamaModel.py @@ -0,0 +1,300 @@ +from typing import Any, Dict, List, Optional + +# from langchain_community.chat_models import ChatOllama +from langchain_community.chat_models import ChatOllama + +from langflow.base.constants import STREAM_INFO_TEXT +from langflow.base.models.model import LCModelComponent + +# from langchain.chat_models import ChatOllama +from langflow.field_typing import Text + +# whe When a callback component is added to Langflow, the comment must be uncommented. +# from langchain.callbacks.manager import CallbackManager + + +class ChatOllamaComponent(LCModelComponent): + display_name = "Ollama" + description = "Generate text using Ollama Local LLMs." + icon = "Ollama" + + field_order = [ + "base_url", + "model", + "temperature", + "cache", + "callback_manager", + "callbacks", + "format", + "metadata", + "mirostat", + "mirostat_eta", + "mirostat_tau", + "num_ctx", + "num_gpu", + "num_thread", + "repeat_last_n", + "repeat_penalty", + "tfs_z", + "timeout", + "top_k", + "top_p", + "verbose", + "tags", + "stop", + "system", + "template", + "input_value", + "system_message", + "stream", + ] + + def build_config(self) -> dict: + return { + "base_url": { + "display_name": "Base URL", + "info": "Endpoint of the Ollama API. Defaults to 'http://localhost:11434' if not specified.", + "advanced": True, + }, + "model": { + "display_name": "Model Name", + "value": "llama2", + "info": "Refer to https://ollama.ai/library for more models.", + }, + "temperature": { + "display_name": "Temperature", + "field_type": "float", + "value": 0.8, + "info": "Controls the creativity of model responses.", + }, + "cache": { + "display_name": "Cache", + "field_type": "bool", + "info": "Enable or disable caching.", + "advanced": True, + "value": False, + }, + ### When a callback component is added to Langflow, the comment must be uncommented. ### + # "callback_manager": { + # "display_name": "Callback Manager", + # "info": "Optional callback manager for additional functionality.", + # "advanced": True, + # }, + # "callbacks": { + # "display_name": "Callbacks", + # "info": "Callbacks to execute during model runtime.", + # "advanced": True, + # }, + ######################################################################################## + "format": { + "display_name": "Format", + "field_type": "str", + "info": "Specify the format of the output (e.g., json).", + "advanced": True, + }, + "metadata": { + "display_name": "Metadata", + "info": "Metadata to add to the run trace.", + "advanced": True, + }, + "mirostat": { + "display_name": "Mirostat", + "options": ["Disabled", "Mirostat", "Mirostat 2.0"], + "info": "Enable/disable Mirostat sampling for controlling perplexity.", + "value": "Disabled", + "advanced": True, + }, + "mirostat_eta": { + "display_name": "Mirostat Eta", + "field_type": "float", + "info": "Learning rate for Mirostat algorithm. (Default: 0.1)", + "advanced": True, + }, + "mirostat_tau": { + "display_name": "Mirostat Tau", + "field_type": "float", + "info": "Controls the balance between coherence and diversity of the output. (Default: 5.0)", + "advanced": True, + }, + "num_ctx": { + "display_name": "Context Window Size", + "field_type": "int", + "info": "Size of the context window for generating tokens. (Default: 2048)", + "advanced": True, + }, + "num_gpu": { + "display_name": "Number of GPUs", + "field_type": "int", + "info": "Number of GPUs to use for computation. (Default: 1 on macOS, 0 to disable)", + "advanced": True, + }, + "num_thread": { + "display_name": "Number of Threads", + "field_type": "int", + "info": "Number of threads to use during computation. (Default: detected for optimal performance)", + "advanced": True, + }, + "repeat_last_n": { + "display_name": "Repeat Last N", + "field_type": "int", + "info": "How far back the model looks to prevent repetition. (Default: 64, 0 = disabled, -1 = num_ctx)", + "advanced": True, + }, + "repeat_penalty": { + "display_name": "Repeat Penalty", + "field_type": "float", + "info": "Penalty for repetitions in generated text. (Default: 1.1)", + "advanced": True, + }, + "tfs_z": { + "display_name": "TFS Z", + "field_type": "float", + "info": "Tail free sampling value. (Default: 1)", + "advanced": True, + }, + "timeout": { + "display_name": "Timeout", + "field_type": "int", + "info": "Timeout for the request stream.", + "advanced": True, + }, + "top_k": { + "display_name": "Top K", + "field_type": "int", + "info": "Limits token selection to top K. (Default: 40)", + "advanced": True, + }, + "top_p": { + "display_name": "Top P", + "field_type": "float", + "info": "Works together with top-k. (Default: 0.9)", + "advanced": True, + }, + "verbose": { + "display_name": "Verbose", + "field_type": "bool", + "info": "Whether to print out response text.", + }, + "tags": { + "display_name": "Tags", + "field_type": "list", + "info": "Tags to add to the run trace.", + "advanced": True, + }, + "stop": { + "display_name": "Stop Tokens", + "field_type": "list", + "info": "List of tokens to signal the model to stop generating text.", + "advanced": True, + }, + "system": { + "display_name": "System", + "field_type": "str", + "info": "System to use for generating text.", + "advanced": True, + }, + "template": { + "display_name": "Template", + "field_type": "str", + "info": "Template to use for generating text.", + "advanced": True, + }, + "input_value": {"display_name": "Input"}, + "stream": { + "display_name": "Stream", + "info": STREAM_INFO_TEXT, + }, + "system_message": { + "display_name": "System Message", + "info": "System message to pass to the model.", + "advanced": True, + }, + } + + def build( + self, + base_url: Optional[str], + model: str, + input_value: Text, + mirostat: Optional[str], + mirostat_eta: Optional[float] = None, + mirostat_tau: Optional[float] = None, + ### When a callback component is added to Langflow, the comment must be uncommented.### + # callback_manager: Optional[CallbackManager] = None, + # callbacks: Optional[List[Callbacks]] = None, + ####################################################################################### + repeat_last_n: Optional[int] = None, + verbose: Optional[bool] = None, + cache: Optional[bool] = None, + num_ctx: Optional[int] = None, + num_gpu: Optional[int] = None, + format: Optional[str] = None, + metadata: Optional[Dict[str, Any]] = None, + num_thread: Optional[int] = None, + repeat_penalty: Optional[float] = None, + stop: Optional[List[str]] = None, + system: Optional[str] = None, + tags: Optional[List[str]] = None, + temperature: Optional[float] = None, + template: Optional[str] = None, + tfs_z: Optional[float] = None, + timeout: Optional[int] = None, + top_k: Optional[int] = None, + top_p: Optional[int] = None, + stream: bool = False, + system_message: Optional[str] = None, + ) -> Text: + if not base_url: + base_url = "http://localhost:11434" + + # Mapping mirostat settings to their corresponding values + mirostat_options = {"Mirostat": 1, "Mirostat 2.0": 2} + + # Default to 0 for 'Disabled' + mirostat_value = mirostat_options.get(mirostat, 0) # type: ignore + + # Set mirostat_eta and mirostat_tau to None if mirostat is disabled + if mirostat_value == 0: + mirostat_eta = None + mirostat_tau = None + + # Mapping system settings to their corresponding values + llm_params = { + "base_url": base_url, + "cache": cache, + "model": model, + "mirostat": mirostat_value, + "format": format, + "metadata": metadata, + "tags": tags, + ## When a callback component is added to Langflow, the comment must be uncommented.## + # "callback_manager": callback_manager, + # "callbacks": callbacks, + ##################################################################################### + "mirostat_eta": mirostat_eta, + "mirostat_tau": mirostat_tau, + "num_ctx": num_ctx, + "num_gpu": num_gpu, + "num_thread": num_thread, + "repeat_last_n": repeat_last_n, + "repeat_penalty": repeat_penalty, + "temperature": temperature, + "stop": stop, + "system": system, + "template": template, + "tfs_z": tfs_z, + "timeout": timeout, + "top_k": top_k, + "top_p": top_p, + "verbose": verbose, + } + + # None Value remove + llm_params = {k: v for k, v in llm_params.items() if v is not None} + + try: + output = ChatOllama(**llm_params) # type: ignore + except Exception as e: + raise ValueError("Could not initialize Ollama LLM.") from e + + return self.get_chat_result(output, stream, input_value, system_message) diff --git a/src/backend/base/langflow/components/models/OpenAIModel.py b/src/backend/base/langflow/components/models/OpenAIModel.py new file mode 100644 index 000000000..678151064 --- /dev/null +++ b/src/backend/base/langflow/components/models/OpenAIModel.py @@ -0,0 +1,106 @@ +from typing import Optional + +from langchain_openai import ChatOpenAI + +from langflow.base.constants import STREAM_INFO_TEXT +from langflow.base.models.model import LCModelComponent +from langflow.field_typing import NestedDict, Text + + +class OpenAIModelComponent(LCModelComponent): + display_name = "OpenAI" + description = "Generates text using OpenAI LLMs." + icon = "OpenAI" + + field_order = [ + "max_tokens", + "model_kwargs", + "model_name", + "openai_api_base", + "openai_api_key", + "temperature", + "input_value", + "system_message", + "stream", + ] + + def build_config(self): + return { + "input_value": {"display_name": "Input"}, + "max_tokens": { + "display_name": "Max Tokens", + "advanced": True, + }, + "model_kwargs": { + "display_name": "Model Kwargs", + "advanced": True, + }, + "model_name": { + "display_name": "Model Name", + "advanced": False, + "options": [ + "gpt-4-turbo-preview", + "gpt-3.5-turbo", + "gpt-4-0125-preview", + "gpt-4-1106-preview", + "gpt-4-vision-preview", + "gpt-3.5-turbo-0125", + "gpt-3.5-turbo-1106", + ], + "value": "gpt-4-turbo-preview", + }, + "openai_api_base": { + "display_name": "OpenAI API Base", + "advanced": True, + "info": ( + "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\n" + "You can change this to use other APIs like JinaChat, LocalAI and Prem." + ), + }, + "openai_api_key": { + "display_name": "OpenAI API Key", + "info": "The OpenAI API Key to use for the OpenAI model.", + "advanced": False, + "password": True, + }, + "temperature": { + "display_name": "Temperature", + "advanced": False, + "value": 0.1, + }, + "stream": { + "display_name": "Stream", + "info": STREAM_INFO_TEXT, + "advanced": True, + }, + "system_message": { + "display_name": "System Message", + "info": "System message to pass to the model.", + "advanced": True, + }, + } + + def build( + self, + input_value: Text, + openai_api_key: str, + temperature: float, + model_name: str, + max_tokens: Optional[int] = 256, + model_kwargs: NestedDict = {}, + openai_api_base: Optional[str] = None, + stream: bool = False, + system_message: Optional[str] = None, + ) -> Text: + if not openai_api_base: + openai_api_base = "https://api.openai.com/v1" + output = ChatOpenAI( + max_tokens=max_tokens, + model_kwargs=model_kwargs, + model=model_name, + base_url=openai_api_base, + api_key=openai_api_key, + temperature=temperature, + ) + + return self.get_chat_result(output, stream, input_value, system_message) diff --git a/src/backend/base/langflow/components/models/VertexAiModel.py b/src/backend/base/langflow/components/models/VertexAiModel.py new file mode 100644 index 000000000..ff520e0d1 --- /dev/null +++ b/src/backend/base/langflow/components/models/VertexAiModel.py @@ -0,0 +1,126 @@ +from typing import List, Optional + +from langchain_core.messages.base import BaseMessage + +from langflow.base.constants import STREAM_INFO_TEXT +from langflow.base.models.model import LCModelComponent +from langflow.field_typing import Text + + +class ChatVertexAIComponent(LCModelComponent): + display_name = "Vertex AI" + description = "Generate text using Vertex AI LLMs." + icon = "VertexAI" + + field_order = [ + "credentials", + "project", + "examples", + "location", + "max_output_tokens", + "model_name", + "temperature", + "top_k", + "top_p", + "verbose", + "input_value", + "system_message", + "stream", + ] + + def build_config(self): + return { + "credentials": { + "display_name": "Credentials", + "field_type": "file", + "file_types": [".json"], + "file_path": None, + }, + "examples": { + "display_name": "Examples", + "multiline": True, + }, + "location": { + "display_name": "Location", + "value": "us-central1", + }, + "max_output_tokens": { + "display_name": "Max Output Tokens", + "value": 128, + "advanced": True, + }, + "model_name": { + "display_name": "Model Name", + "value": "chat-bison", + }, + "project": { + "display_name": "Project", + }, + "temperature": { + "display_name": "Temperature", + "value": 0.0, + }, + "top_k": { + "display_name": "Top K", + "value": 40, + "advanced": True, + }, + "top_p": { + "display_name": "Top P", + "value": 0.95, + "advanced": True, + }, + "verbose": { + "display_name": "Verbose", + "value": False, + "advanced": True, + }, + "input_value": {"display_name": "Input"}, + "stream": { + "display_name": "Stream", + "info": STREAM_INFO_TEXT, + "advanced": True, + }, + "system_message": { + "display_name": "System Message", + "info": "System message to pass to the model.", + "advanced": True, + }, + } + + def build( + self, + input_value: Text, + credentials: Optional[str], + project: str, + examples: Optional[List[BaseMessage]] = [], + location: str = "us-central1", + max_output_tokens: int = 128, + model_name: str = "chat-bison", + temperature: float = 0.0, + top_k: int = 40, + top_p: float = 0.95, + verbose: bool = False, + stream: bool = False, + system_message: Optional[str] = None, + ) -> Text: + try: + from langchain_google_vertexai import ChatVertexAI # type: ignore + except ImportError: + raise ImportError( + "To use the ChatVertexAI model, you need to install the langchain-google-vertexai package." + ) + output = ChatVertexAI( + credentials=credentials, + examples=examples, + location=location, + max_output_tokens=max_output_tokens, + model_name=model_name, + project=project, + temperature=temperature, + top_k=top_k, + top_p=top_p, + verbose=verbose, + ) + + return self.get_chat_result(output, stream, input_value, system_message) diff --git a/src/backend/base/langflow/components/models/__init__.py b/src/backend/base/langflow/components/models/__init__.py new file mode 100644 index 000000000..9db6caa26 --- /dev/null +++ b/src/backend/base/langflow/components/models/__init__.py @@ -0,0 +1,26 @@ +from .AmazonBedrockModel import AmazonBedrockComponent +from .AnthropicModel import AnthropicLLM +from .AzureOpenAIModel import AzureChatOpenAIComponent +from .BaiduQianfanChatModel import QianfanChatEndpointComponent +from .ChatLiteLLMModel import ChatLiteLLMModelComponent +from .CohereModel import CohereComponent +from .GoogleGenerativeAIModel import GoogleGenerativeAIComponent +from .HuggingFaceModel import HuggingFaceEndpointsComponent +from .OllamaModel import ChatOllamaComponent +from .OpenAIModel import OpenAIModelComponent +from .VertexAiModel import ChatVertexAIComponent + +__all__ = [ + "ChatLiteLLMModelComponent", + "AmazonBedrockComponent", + "AnthropicLLM", + "AzureChatOpenAIComponent", + "QianfanChatEndpointComponent", + "CohereComponent", + "GoogleGenerativeAIComponent", + "HuggingFaceEndpointsComponent", + "ChatOllamaComponent", + "OpenAIModelComponent", + "ChatVertexAIComponent", + "base", +] diff --git a/src/backend/base/langflow/components/outputs/ChatOutput.py b/src/backend/base/langflow/components/outputs/ChatOutput.py new file mode 100644 index 000000000..9ca162c4c --- /dev/null +++ b/src/backend/base/langflow/components/outputs/ChatOutput.py @@ -0,0 +1,29 @@ +from typing import Optional, Union + +from langflow.base.io.chat import ChatComponent +from langflow.field_typing import Text +from langflow.schema import Record + + +class ChatOutput(ChatComponent): + display_name = "Chat Output" + description = "Display a chat message in the Interaction Panel." + icon = "ChatOutput" + + def build( + self, + sender: Optional[str] = "Machine", + sender_name: Optional[str] = "AI", + input_value: Optional[str] = None, + session_id: Optional[str] = None, + return_record: Optional[bool] = False, + record_template: Optional[str] = "{text}", + ) -> Union[Text, Record]: + return super().build( + sender=sender, + sender_name=sender_name, + input_value=input_value, + session_id=session_id, + return_record=return_record, + record_template=record_template, + ) diff --git a/src/backend/base/langflow/components/outputs/TextOutput.py b/src/backend/base/langflow/components/outputs/TextOutput.py new file mode 100644 index 000000000..fe2d8d145 --- /dev/null +++ b/src/backend/base/langflow/components/outputs/TextOutput.py @@ -0,0 +1,28 @@ +from typing import Optional + +from langflow.base.io.text import TextComponent +from langflow.field_typing import Text + + +class TextOutput(TextComponent): + display_name = "Text Output" + description = "Display a text output in the Interaction Panel." + icon = "type" + + def build_config(self): + return { + "input_value": { + "display_name": "Value", + "input_types": ["Record", "Text"], + "info": "Text or Record to be passed as output.", + }, + "record_template": { + "display_name": "Record Template", + "multiline": True, + "info": "Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.", + "advanced": True, + }, + } + + def build(self, input_value: Optional[Text] = "", record_template: str = "") -> Text: + return super().build(input_value=input_value, record_template=record_template) diff --git a/src/backend/base/langflow/components/outputs/__init__.py b/src/backend/base/langflow/components/outputs/__init__.py new file mode 100644 index 000000000..cf395bb86 --- /dev/null +++ b/src/backend/base/langflow/components/outputs/__init__.py @@ -0,0 +1,4 @@ +from .ChatOutput import ChatOutput +from .TextOutput import TextOutput + +__all__ = ["ChatOutput", "TextOutput"] diff --git a/src/backend/langflow/components/retrievers/AmazonKendra.py b/src/backend/base/langflow/components/retrievers/AmazonKendra.py similarity index 91% rename from src/backend/langflow/components/retrievers/AmazonKendra.py rename to src/backend/base/langflow/components/retrievers/AmazonKendra.py index 827945a51..6584f6545 100644 --- a/src/backend/langflow/components/retrievers/AmazonKendra.py +++ b/src/backend/base/langflow/components/retrievers/AmazonKendra.py @@ -1,12 +1,15 @@ from typing import Optional -from langflow import CustomComponent -from langchain.retrievers import AmazonKendraRetriever + from langchain.schema import BaseRetriever +from langchain_community.retrievers import AmazonKendraRetriever + +from langflow.interface.custom.custom_component import CustomComponent class AmazonKendraRetrieverComponent(CustomComponent): display_name: str = "Amazon Kendra Retriever" description: str = "Retriever that uses the Amazon Kendra API." + icon = "Amazon" def build_config(self): return { diff --git a/src/backend/langflow/components/retrievers/MetalRetriever.py b/src/backend/base/langflow/components/retrievers/MetalRetriever.py similarity index 88% rename from src/backend/langflow/components/retrievers/MetalRetriever.py rename to src/backend/base/langflow/components/retrievers/MetalRetriever.py index 88393f26d..c5c56a397 100644 --- a/src/backend/langflow/components/retrievers/MetalRetriever.py +++ b/src/backend/base/langflow/components/retrievers/MetalRetriever.py @@ -1,9 +1,11 @@ from typing import Optional -from langflow import CustomComponent -from langchain.retrievers import MetalRetriever + from langchain.schema import BaseRetriever +from langchain_community.retrievers import MetalRetriever from metal_sdk.metal import Metal # type: ignore +from langflow.interface.custom.custom_component import CustomComponent + class MetalRetrieverComponent(CustomComponent): display_name: str = "Metal Retriever" diff --git a/src/backend/langflow/components/retrievers/MultiQueryRetriever.py b/src/backend/base/langflow/components/retrievers/MultiQueryRetriever.py similarity index 96% rename from src/backend/langflow/components/retrievers/MultiQueryRetriever.py rename to src/backend/base/langflow/components/retrievers/MultiQueryRetriever.py index d2c12d7a5..0dec1c028 100644 --- a/src/backend/langflow/components/retrievers/MultiQueryRetriever.py +++ b/src/backend/base/langflow/components/retrievers/MultiQueryRetriever.py @@ -1,8 +1,9 @@ from typing import Callable, Optional, Union from langchain.retrievers import MultiQueryRetriever -from langflow import CustomComponent + from langflow.field_typing import BaseLLM, BaseRetriever, PromptTemplate +from langflow.interface.custom.custom_component import CustomComponent class MultiQueryRetrieverComponent(CustomComponent): diff --git a/src/backend/langflow/components/retrievers/VectaraSelfQueryRetriver.py b/src/backend/base/langflow/components/retrievers/VectaraSelfQueryRetriver.py similarity index 96% rename from src/backend/langflow/components/retrievers/VectaraSelfQueryRetriver.py rename to src/backend/base/langflow/components/retrievers/VectaraSelfQueryRetriver.py index 26afd765c..759021487 100644 --- a/src/backend/langflow/components/retrievers/VectaraSelfQueryRetriver.py +++ b/src/backend/base/langflow/components/retrievers/VectaraSelfQueryRetriver.py @@ -1,11 +1,13 @@ -from typing import List -from langflow import CustomComponent import json +from typing import List + +from langchain.base_language import BaseLanguageModel +from langchain.chains.query_constructor.base import AttributeInfo +from langchain.retrievers.self_query.base import SelfQueryRetriever from langchain.schema import BaseRetriever from langchain.schema.vectorstore import VectorStore -from langchain.base_language import BaseLanguageModel -from langchain.retrievers.self_query.base import SelfQueryRetriever -from langchain.chains.query_constructor.base import AttributeInfo + +from langflow.interface.custom.custom_component import CustomComponent class VectaraSelfQueryRetriverComponent(CustomComponent): @@ -16,7 +18,7 @@ class VectaraSelfQueryRetriverComponent(CustomComponent): display_name: str = "Vectara Self Query Retriever for Vectara Vector Store" description: str = "Implementation of Vectara Self Query Retriever" documentation = "https://python.langchain.com/docs/integrations/retrievers/self_query/vectara_self_query" - beta = True + icon = "Vectara" field_config = { "code": {"show": True}, diff --git a/src/backend/langflow/components/retrievers/VectorStoreRetriever.py b/src/backend/base/langflow/components/retrievers/VectorStoreRetriever.py similarity index 87% rename from src/backend/langflow/components/retrievers/VectorStoreRetriever.py rename to src/backend/base/langflow/components/retrievers/VectorStoreRetriever.py index 576b02e69..43f1aab71 100644 --- a/src/backend/langflow/components/retrievers/VectorStoreRetriever.py +++ b/src/backend/base/langflow/components/retrievers/VectorStoreRetriever.py @@ -1,7 +1,7 @@ from langchain_core.vectorstores import VectorStoreRetriever -from langflow import CustomComponent from langflow.field_typing import VectorStore +from langflow.interface.custom.custom_component import CustomComponent class VectoStoreRetrieverComponent(CustomComponent): diff --git a/src/backend/base/langflow/components/retrievers/__init__.py b/src/backend/base/langflow/components/retrievers/__init__.py new file mode 100644 index 000000000..35030bc5e --- /dev/null +++ b/src/backend/base/langflow/components/retrievers/__init__.py @@ -0,0 +1,13 @@ +from .AmazonKendra import AmazonKendraRetrieverComponent +from .MetalRetriever import MetalRetrieverComponent +from .MultiQueryRetriever import MultiQueryRetrieverComponent +from .VectaraSelfQueryRetriver import VectaraSelfQueryRetriverComponent +from .VectorStoreRetriever import VectoStoreRetrieverComponent + +__all__ = [ + "AmazonKendraRetrieverComponent", + "MetalRetrieverComponent", + "MultiQueryRetrieverComponent", + "VectaraSelfQueryRetriverComponent", + "VectoStoreRetrieverComponent", +] diff --git a/src/backend/langflow/components/textsplitters/CharacterTextSplitter.py b/src/backend/base/langflow/components/textsplitters/CharacterTextSplitter.py similarity index 54% rename from src/backend/langflow/components/textsplitters/CharacterTextSplitter.py rename to src/backend/base/langflow/components/textsplitters/CharacterTextSplitter.py index 1bfd2d2e3..2a0f3686f 100644 --- a/src/backend/langflow/components/textsplitters/CharacterTextSplitter.py +++ b/src/backend/base/langflow/components/textsplitters/CharacterTextSplitter.py @@ -1,8 +1,10 @@ from typing import List from langchain.text_splitter import CharacterTextSplitter -from langchain_core.documents.base import Document -from langflow import CustomComponent + +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema.schema import Record +from langflow.utils.util import unescape_string class CharacterTextSplitterComponent(CustomComponent): @@ -11,7 +13,7 @@ class CharacterTextSplitterComponent(CustomComponent): def build_config(self): return { - "documents": {"display_name": "Documents"}, + "inputs": {"display_name": "Input", "input_types": ["Document", "Record"]}, "chunk_overlap": {"display_name": "Chunk Overlap", "default": 200}, "chunk_size": {"display_name": "Chunk Size", "default": 1000}, "separator": {"display_name": "Separator", "default": "\n"}, @@ -19,15 +21,24 @@ class CharacterTextSplitterComponent(CustomComponent): def build( self, - documents: List[Document], + inputs: List[Record], chunk_overlap: int = 200, chunk_size: int = 1000, separator: str = "\n", - ) -> List[Document]: + ) -> List[Record]: + # separator may come escaped from the frontend + separator = unescape_string(separator) + documents = [] + for _input in inputs: + if isinstance(_input, Record): + documents.append(_input.to_lc_document()) + else: + documents.append(_input) docs = CharacterTextSplitter( chunk_overlap=chunk_overlap, chunk_size=chunk_size, separator=separator, ).split_documents(documents) - self.status = docs - return docs + records = self.to_records(docs) + self.status = records + return records diff --git a/src/backend/langflow/components/textsplitters/LanguageRecursiveTextSplitter.py b/src/backend/base/langflow/components/textsplitters/LanguageRecursiveTextSplitter.py similarity index 81% rename from src/backend/langflow/components/textsplitters/LanguageRecursiveTextSplitter.py rename to src/backend/base/langflow/components/textsplitters/LanguageRecursiveTextSplitter.py index d1494f4d0..1a4ae24a1 100644 --- a/src/backend/langflow/components/textsplitters/LanguageRecursiveTextSplitter.py +++ b/src/backend/base/langflow/components/textsplitters/LanguageRecursiveTextSplitter.py @@ -1,9 +1,9 @@ -from typing import Optional +from typing import List, Optional from langchain.text_splitter import Language -from langchain_core.documents import Document -from langflow import CustomComponent +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema.schema import Record class LanguageRecursiveTextSplitterComponent(CustomComponent): @@ -14,10 +14,7 @@ class LanguageRecursiveTextSplitterComponent(CustomComponent): def build_config(self): options = [x.value for x in Language] return { - "documents": { - "display_name": "Documents", - "info": "The documents to split.", - }, + "inputs": {"display_name": "Input", "input_types": ["Document", "Record"]}, "separator_type": { "display_name": "Separator Type", "info": "The type of separator to use.", @@ -47,11 +44,11 @@ class LanguageRecursiveTextSplitterComponent(CustomComponent): def build( self, - documents: list[Document], + inputs: List[Record], chunk_size: Optional[int] = 1000, chunk_overlap: Optional[int] = 200, separator_type: str = "Python", - ) -> list[Document]: + ) -> list[Record]: """ Split text into chunks of a specified length. @@ -77,6 +74,12 @@ class LanguageRecursiveTextSplitterComponent(CustomComponent): chunk_size=chunk_size, chunk_overlap=chunk_overlap, ) - + documents = [] + for _input in inputs: + if isinstance(_input, Record): + documents.append(_input.to_lc_document()) + else: + documents.append(_input) docs = splitter.split_documents(documents) - return docs + records = self.to_records(docs) + return records diff --git a/src/backend/langflow/components/textsplitters/RecursiveCharacterTextSplitter.py b/src/backend/base/langflow/components/textsplitters/RecursiveCharacterTextSplitter.py similarity index 75% rename from src/backend/langflow/components/textsplitters/RecursiveCharacterTextSplitter.py rename to src/backend/base/langflow/components/textsplitters/RecursiveCharacterTextSplitter.py index d07ae3ebe..1ceaa8bd6 100644 --- a/src/backend/langflow/components/textsplitters/RecursiveCharacterTextSplitter.py +++ b/src/backend/base/langflow/components/textsplitters/RecursiveCharacterTextSplitter.py @@ -1,10 +1,11 @@ from typing import Optional +from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_core.documents import Document -from langflow import CustomComponent -from langflow.utils.util import build_loader_repr_from_documents -from langchain.text_splitter import RecursiveCharacterTextSplitter +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema import Record +from langflow.utils.util import build_loader_repr_from_records, unescape_string class RecursiveCharacterTextSplitterComponent(CustomComponent): @@ -14,9 +15,10 @@ class RecursiveCharacterTextSplitterComponent(CustomComponent): def build_config(self): return { - "documents": { - "display_name": "Documents", - "info": "The documents to split.", + "inputs": { + "display_name": "Input", + "info": "The texts to split.", + "input_types": ["Document", "Record"], }, "separators": { "display_name": "Separators", @@ -40,11 +42,11 @@ class RecursiveCharacterTextSplitterComponent(CustomComponent): def build( self, - documents: list[Document], + inputs: list[Document], separators: Optional[list[str]] = None, chunk_size: Optional[int] = 1000, chunk_overlap: Optional[int] = 200, - ) -> list[Document]: + ) -> list[Record]: """ Split text into chunks of a specified length. @@ -63,7 +65,7 @@ class RecursiveCharacterTextSplitterComponent(CustomComponent): elif separators: # check if the separators list has escaped characters # if there are escaped characters, unescape them - separators = [x.encode().decode("unicode-escape") for x in separators] + separators = [unescape_string(x) for x in separators] # Make sure chunk_size and chunk_overlap are ints if isinstance(chunk_size, str): @@ -75,7 +77,13 @@ class RecursiveCharacterTextSplitterComponent(CustomComponent): chunk_size=chunk_size, chunk_overlap=chunk_overlap, ) - + documents = [] + for _input in inputs: + if isinstance(_input, Record): + documents.append(_input.to_lc_document()) + else: + documents.append(_input) docs = splitter.split_documents(documents) - self.repr_value = build_loader_repr_from_documents(docs) - return docs + records = self.to_records(docs) + self.repr_value = build_loader_repr_from_records(records) + return records diff --git a/src/backend/base/langflow/components/textsplitters/__init__.py b/src/backend/base/langflow/components/textsplitters/__init__.py new file mode 100644 index 000000000..eb2d6af13 --- /dev/null +++ b/src/backend/base/langflow/components/textsplitters/__init__.py @@ -0,0 +1,9 @@ +from .CharacterTextSplitter import CharacterTextSplitterComponent +from .LanguageRecursiveTextSplitter import LanguageRecursiveTextSplitterComponent +from .RecursiveCharacterTextSplitter import RecursiveCharacterTextSplitterComponent + +__all__ = [ + "CharacterTextSplitterComponent", + "LanguageRecursiveTextSplitterComponent", + "RecursiveCharacterTextSplitterComponent", +] diff --git a/src/backend/langflow/components/toolkits/JsonToolkit.py b/src/backend/base/langflow/components/toolkits/JsonToolkit.py similarity index 87% rename from src/backend/langflow/components/toolkits/JsonToolkit.py rename to src/backend/base/langflow/components/toolkits/JsonToolkit.py index ec9e49621..72fe17cde 100644 --- a/src/backend/langflow/components/toolkits/JsonToolkit.py +++ b/src/backend/base/langflow/components/toolkits/JsonToolkit.py @@ -1,6 +1,7 @@ -from langflow import CustomComponent -from langchain_community.tools.json.tool import JsonSpec from langchain_community.agent_toolkits.json.toolkit import JsonToolkit +from langchain_community.tools.json.tool import JsonSpec + +from langflow.interface.custom.custom_component import CustomComponent class JsonToolkitComponent(CustomComponent): diff --git a/src/backend/langflow/components/toolkits/Metaphor.py b/src/backend/base/langflow/components/toolkits/Metaphor.py similarity index 96% rename from src/backend/langflow/components/toolkits/Metaphor.py rename to src/backend/base/langflow/components/toolkits/Metaphor.py index 0f9f23334..14962924f 100644 --- a/src/backend/langflow/components/toolkits/Metaphor.py +++ b/src/backend/base/langflow/components/toolkits/Metaphor.py @@ -5,7 +5,7 @@ from langchain.agents.agent_toolkits.base import BaseToolkit from langchain.tools import Tool from metaphor_python import Metaphor # type: ignore -from langflow import CustomComponent +from langflow.interface.custom.custom_component import CustomComponent class MetaphorToolkit(CustomComponent): diff --git a/src/backend/langflow/components/toolkits/OpenAPIToolkit.py b/src/backend/base/langflow/components/toolkits/OpenAPIToolkit.py similarity index 91% rename from src/backend/langflow/components/toolkits/OpenAPIToolkit.py rename to src/backend/base/langflow/components/toolkits/OpenAPIToolkit.py index fc8780454..b29feb291 100644 --- a/src/backend/langflow/components/toolkits/OpenAPIToolkit.py +++ b/src/backend/base/langflow/components/toolkits/OpenAPIToolkit.py @@ -1,7 +1,8 @@ from langchain_community.agent_toolkits.openapi.toolkit import BaseToolkit, OpenAPIToolkit from langchain_community.utilities.requests import TextRequestsWrapper -from langflow import CustomComponent + from langflow.field_typing import AgentExecutor +from langflow.interface.custom.custom_component import CustomComponent class OpenAPIToolkitComponent(CustomComponent): diff --git a/src/backend/langflow/components/toolkits/VectorStoreInfo.py b/src/backend/base/langflow/components/toolkits/VectorStoreInfo.py similarity index 91% rename from src/backend/langflow/components/toolkits/VectorStoreInfo.py rename to src/backend/base/langflow/components/toolkits/VectorStoreInfo.py index ec2323bfd..1775d816a 100644 --- a/src/backend/langflow/components/toolkits/VectorStoreInfo.py +++ b/src/backend/base/langflow/components/toolkits/VectorStoreInfo.py @@ -3,7 +3,7 @@ from typing import Callable, Union from langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreInfo from langchain_community.vectorstores import VectorStore -from langflow import CustomComponent +from langflow.interface.custom.custom_component import CustomComponent class VectorStoreInfoComponent(CustomComponent): diff --git a/src/backend/langflow/components/toolkits/VectorStoreRouterToolkit.py b/src/backend/base/langflow/components/toolkits/VectorStoreRouterToolkit.py similarity index 84% rename from src/backend/langflow/components/toolkits/VectorStoreRouterToolkit.py rename to src/backend/base/langflow/components/toolkits/VectorStoreRouterToolkit.py index ed8797044..13ec1656f 100644 --- a/src/backend/langflow/components/toolkits/VectorStoreRouterToolkit.py +++ b/src/backend/base/langflow/components/toolkits/VectorStoreRouterToolkit.py @@ -1,8 +1,9 @@ -from langflow import CustomComponent from typing import List, Union -from langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreRouterToolkit -from langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreInfo + +from langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreInfo, VectorStoreRouterToolkit + from langflow.field_typing import BaseLanguageModel, Tool +from langflow.interface.custom.custom_component import CustomComponent class VectorStoreRouterToolkitComponent(CustomComponent): diff --git a/src/backend/langflow/components/toolkits/VectorStoreToolkit.py b/src/backend/base/langflow/components/toolkits/VectorStoreToolkit.py similarity index 72% rename from src/backend/langflow/components/toolkits/VectorStoreToolkit.py rename to src/backend/base/langflow/components/toolkits/VectorStoreToolkit.py index 38b9c9171..8436ba58e 100644 --- a/src/backend/langflow/components/toolkits/VectorStoreToolkit.py +++ b/src/backend/base/langflow/components/toolkits/VectorStoreToolkit.py @@ -1,14 +1,10 @@ -from langflow import CustomComponent -from langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreToolkit -from langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreInfo -from langflow.field_typing import ( - BaseLanguageModel, -) -from langflow.field_typing import ( - Tool, -) from typing import Union +from langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreInfo, VectorStoreToolkit + +from langflow.field_typing import BaseLanguageModel, Tool +from langflow.interface.custom.custom_component import CustomComponent + class VectorStoreToolkitComponent(CustomComponent): display_name = "VectorStoreToolkit" diff --git a/src/backend/base/langflow/components/toolkits/__init__.py b/src/backend/base/langflow/components/toolkits/__init__.py new file mode 100644 index 000000000..189b43159 --- /dev/null +++ b/src/backend/base/langflow/components/toolkits/__init__.py @@ -0,0 +1,15 @@ +from .JsonToolkit import JsonToolkitComponent +from .Metaphor import MetaphorToolkit +from .OpenAPIToolkit import OpenAPIToolkitComponent +from .VectorStoreInfo import VectorStoreInfoComponent +from .VectorStoreRouterToolkit import VectorStoreRouterToolkitComponent +from .VectorStoreToolkit import VectorStoreToolkitComponent + +__all__ = [ + "JsonToolkitComponent", + "MetaphorToolkit", + "OpenAPIToolkitComponent", + "VectorStoreInfoComponent", + "VectorStoreRouterToolkitComponent", + "VectorStoreToolkitComponent", +] diff --git a/src/backend/langflow/components/tools/RetrieverTool.py b/src/backend/base/langflow/components/tools/RetrieverTool.py similarity index 92% rename from src/backend/langflow/components/tools/RetrieverTool.py rename to src/backend/base/langflow/components/tools/RetrieverTool.py index 5a598dbe2..914ba3941 100644 --- a/src/backend/langflow/components/tools/RetrieverTool.py +++ b/src/backend/base/langflow/components/tools/RetrieverTool.py @@ -1,7 +1,7 @@ from langchain.tools.retriever import create_retriever_tool -from langflow import CustomComponent from langflow.field_typing import BaseRetriever, Tool +from langflow.interface.custom.custom_component import CustomComponent class RetrieverToolComponent(CustomComponent): diff --git a/src/backend/base/langflow/components/tools/SearchAPITool.py b/src/backend/base/langflow/components/tools/SearchAPITool.py new file mode 100644 index 000000000..e0658c8c8 --- /dev/null +++ b/src/backend/base/langflow/components/tools/SearchAPITool.py @@ -0,0 +1,37 @@ +from langchain_community.tools.searchapi import SearchAPIRun +from langchain_community.utilities.searchapi import SearchApiAPIWrapper + +from langflow.custom import CustomComponent +from langflow.field_typing import Tool + + +class SearchApiToolComponent(CustomComponent): + display_name: str = "SearchApi Tool" + description: str = "Real-time search engine results API." + documentation: str = "https://www.searchapi.io/docs/google" + field_config = { + "engine": { + "display_name": "Engine", + "field_type": "str", + "info": "The search engine to use.", + }, + "api_key": { + "display_name": "API Key", + "field_type": "str", + "required": True, + "password": True, + "info": "The API key to use SearchApi.", + }, + } + + def build( + self, + engine: str, + api_key: str, + ) -> Tool: + search_api_wrapper = SearchApiAPIWrapper(engine=engine, searchapi_api_key=api_key) + + tool = SearchAPIRun(api_wrapper=search_api_wrapper) + + self.status = tool + return tool # type: ignore diff --git a/src/backend/base/langflow/components/tools/SearchApi.py b/src/backend/base/langflow/components/tools/SearchApi.py new file mode 100644 index 000000000..3dcd48d9f --- /dev/null +++ b/src/backend/base/langflow/components/tools/SearchApi.py @@ -0,0 +1,53 @@ +from typing import Optional + +from langchain_community.utilities.searchapi import SearchApiAPIWrapper + +from langflow.custom import CustomComponent +from langflow.schema.schema import Record +from langflow.services.database.models.base import orjson_dumps + + +class SearchApi(CustomComponent): + display_name: str = "SearchApi" + description: str = "Real-time search engine results API." + output_types: list[str] = ["Document"] + documentation: str = "https://www.searchapi.io/docs/google" + field_config = { + "engine": { + "display_name": "Engine", + "field_type": "str", + "info": "The search engine to use.", + }, + "params": { + "display_name": "Parameters", + "info": "The parameters to send with the request.", + }, + "code": {"show": False}, + "api_key": { + "display_name": "API Key", + "field_type": "str", + "required": True, + "password": True, + "info": "The API key to use SearchApi.", + }, + } + + def build( + self, + engine: str, + api_key: str, + params: Optional[dict] = None, + ) -> Record: + if params is None: + params = {} + + search_api_wrapper = SearchApiAPIWrapper(engine=engine, searchapi_api_key=api_key) + + q = params.pop("q", "SearchApi Langflow") + results = search_api_wrapper.results(q, **params) + + result = orjson_dumps(results, indent_2=False) + + record = Record(data=result) + self.status = record + return record diff --git a/src/backend/base/langflow/components/tools/__init__.py b/src/backend/base/langflow/components/tools/__init__.py new file mode 100644 index 000000000..27072c109 --- /dev/null +++ b/src/backend/base/langflow/components/tools/__init__.py @@ -0,0 +1,5 @@ +from .RetrieverTool import RetrieverToolComponent +from .SearchAPITool import SearchApiToolComponent +from .SearchApi import SearchApi + +__all__ = ["RetrieverToolComponent", "SearchApiToolComponent", "SearchApi"] diff --git a/src/backend/base/langflow/components/vectorsearch/AstraDBSearch.py b/src/backend/base/langflow/components/vectorsearch/AstraDBSearch.py new file mode 100644 index 000000000..83ed42daf --- /dev/null +++ b/src/backend/base/langflow/components/vectorsearch/AstraDBSearch.py @@ -0,0 +1,148 @@ +from typing import List, Optional + +from langflow.components.vectorstores.AstraDB import AstraDBVectorStoreComponent +from langflow.components.vectorstores.base.model import LCVectorStoreComponent +from langflow.field_typing import Embeddings, Text +from langflow.schema import Record + + +class AstraDBSearchComponent(LCVectorStoreComponent): + display_name = "Astra DB Search" + description = "Searches an existing Astra DB Vector Store." + icon = "AstraDB" + field_order = ["token", "api_endpoint", "collection_name", "input_value", "embedding"] + + def build_config(self): + return { + "search_type": { + "display_name": "Search Type", + "options": ["Similarity", "MMR"], + }, + "input_value": { + "display_name": "Input Value", + "info": "Input value to search", + }, + "embedding": {"display_name": "Embedding", "info": "Embedding to use"}, + "collection_name": { + "display_name": "Collection Name", + "info": "The name of the collection within Astra DB where the vectors will be stored.", + }, + "token": { + "display_name": "Token", + "info": "Authentication token for accessing Astra DB.", + "password": True, + }, + "api_endpoint": { + "display_name": "API Endpoint", + "info": "API endpoint URL for the Astra DB service.", + }, + "namespace": { + "display_name": "Namespace", + "info": "Optional namespace within Astra DB to use for the collection.", + "advanced": True, + }, + "metric": { + "display_name": "Metric", + "info": "Optional distance metric for vector comparisons in the vector store.", + "advanced": True, + }, + "batch_size": { + "display_name": "Batch Size", + "info": "Optional number of records to process in a single batch.", + "advanced": True, + }, + "bulk_insert_batch_concurrency": { + "display_name": "Bulk Insert Batch Concurrency", + "info": "Optional concurrency level for bulk insert operations.", + "advanced": True, + }, + "bulk_insert_overwrite_concurrency": { + "display_name": "Bulk Insert Overwrite Concurrency", + "info": "Optional concurrency level for bulk insert operations that overwrite existing records.", + "advanced": True, + }, + "bulk_delete_concurrency": { + "display_name": "Bulk Delete Concurrency", + "info": "Optional concurrency level for bulk delete operations.", + "advanced": True, + }, + "setup_mode": { + "display_name": "Setup Mode", + "info": "Configuration mode for setting up the vector store, with options like “Sync”, “Async”, or “Off”.", + "options": ["Sync", "Async", "Off"], + "advanced": True, + }, + "pre_delete_collection": { + "display_name": "Pre Delete Collection", + "info": "Boolean flag to determine whether to delete the collection before creating a new one.", + "advanced": True, + }, + "metadata_indexing_include": { + "display_name": "Metadata Indexing Include", + "info": "Optional list of metadata fields to include in the indexing.", + "advanced": True, + }, + "metadata_indexing_exclude": { + "display_name": "Metadata Indexing Exclude", + "info": "Optional list of metadata fields to exclude from the indexing.", + "advanced": True, + }, + "collection_indexing_policy": { + "display_name": "Collection Indexing Policy", + "info": "Optional dictionary defining the indexing policy for the collection.", + "advanced": True, + }, + "number_of_results": { + "display_name": "Number of Results", + "info": "Number of results to return.", + "advanced": True, + }, + } + + def build( + self, + embedding: Embeddings, + collection_name: str, + input_value: Text, + token: str, + api_endpoint: str, + search_type: str = "Similarity", + number_of_results: int = 4, + namespace: Optional[str] = None, + metric: Optional[str] = None, + batch_size: Optional[int] = None, + bulk_insert_batch_concurrency: Optional[int] = None, + bulk_insert_overwrite_concurrency: Optional[int] = None, + bulk_delete_concurrency: Optional[int] = None, + setup_mode: str = "Sync", + pre_delete_collection: bool = False, + metadata_indexing_include: Optional[List[str]] = None, + metadata_indexing_exclude: Optional[List[str]] = None, + collection_indexing_policy: Optional[dict] = None, + ) -> List[Record]: + vector_store = AstraDBVectorStoreComponent().build( + embedding=embedding, + collection_name=collection_name, + token=token, + api_endpoint=api_endpoint, + namespace=namespace, + metric=metric, + batch_size=batch_size, + bulk_insert_batch_concurrency=bulk_insert_batch_concurrency, + bulk_insert_overwrite_concurrency=bulk_insert_overwrite_concurrency, + bulk_delete_concurrency=bulk_delete_concurrency, + setup_mode=setup_mode, + pre_delete_collection=pre_delete_collection, + metadata_indexing_include=metadata_indexing_include, + metadata_indexing_exclude=metadata_indexing_exclude, + collection_indexing_policy=collection_indexing_policy, + ) + try: + return self.search_with_vector_store(input_value, search_type, vector_store, k=number_of_results) + except KeyError as e: + if "content" in str(e): + raise ValueError( + "You should ingest data through Langflow (or LangChain) to query it in Langflow. Your collection does not contain a field name 'content'." + ) + else: + raise e diff --git a/src/backend/base/langflow/components/vectorsearch/ChromaSearch.py b/src/backend/base/langflow/components/vectorsearch/ChromaSearch.py new file mode 100644 index 000000000..3e4b7880d --- /dev/null +++ b/src/backend/base/langflow/components/vectorsearch/ChromaSearch.py @@ -0,0 +1,111 @@ +from typing import List, Optional + +import chromadb # type: ignore +from langchain_community.vectorstores.chroma import Chroma + +from langflow.components.vectorstores.base.model import LCVectorStoreComponent +from langflow.field_typing import Embeddings, Text +from langflow.schema import Record + + +class ChromaSearchComponent(LCVectorStoreComponent): + display_name: str = "Chroma Search" + description: str = "Search a Chroma collection for similar documents." + icon = "Chroma" + + def build_config(self): + """ + Builds the configuration for the component. + + Returns: + - dict: A dictionary containing the configuration options for the component. + """ + return { + "input_value": {"display_name": "Input"}, + "search_type": { + "display_name": "Search Type", + "options": ["Similarity", "MMR"], + }, + "collection_name": {"display_name": "Collection Name", "value": "langflow"}, + # "persist": {"display_name": "Persist"}, + "index_directory": {"display_name": "Index Directory"}, + "code": {"show": False, "display_name": "Code"}, + "embedding": { + "display_name": "Embedding", + "info": "Embedding model to vectorize inputs (make sure to use same as index)", + }, + "chroma_server_cors_allow_origins": { + "display_name": "Server CORS Allow Origins", + "advanced": True, + }, + "chroma_server_host": {"display_name": "Server Host", "advanced": True}, + "chroma_server_port": {"display_name": "Server Port", "advanced": True}, + "chroma_server_grpc_port": { + "display_name": "Server gRPC Port", + "advanced": True, + }, + "chroma_server_ssl_enabled": { + "display_name": "Server SSL Enabled", + "advanced": True, + }, + "number_of_results": { + "display_name": "Number of Results", + "info": "Number of results to return.", + "advanced": True, + }, + } + + def build( + self, + input_value: Text, + search_type: str, + collection_name: str, + embedding: Embeddings, + chroma_server_ssl_enabled: bool, + number_of_results: int = 4, + index_directory: Optional[str] = None, + chroma_server_cors_allow_origins: Optional[str] = None, + chroma_server_host: Optional[str] = None, + chroma_server_port: Optional[int] = None, + chroma_server_grpc_port: Optional[int] = None, + ) -> List[Record]: + """ + Builds the Vector Store or BaseRetriever object. + + Args: + - collection_name (str): The name of the collection. + - persist_directory (Optional[str]): The directory to persist the Vector Store to. + - chroma_server_ssl_enabled (bool): Whether to enable SSL for the Chroma server. + - persist (bool): Whether to persist the Vector Store or not. + - embedding (Optional[Embeddings]): The embeddings to use for the Vector Store. + - documents (Optional[Document]): The documents to use for the Vector Store. + - chroma_server_cors_allow_origins (Optional[str]): The CORS allow origins for the Chroma server. + - chroma_server_host (Optional[str]): The host for the Chroma server. + - chroma_server_port (Optional[int]): The port for the Chroma server. + - chroma_server_grpc_port (Optional[int]): The gRPC port for the Chroma server. + + Returns: + - Union[VectorStore, BaseRetriever]: The Vector Store or BaseRetriever object. + """ + + # Chroma settings + chroma_settings = None + + if chroma_server_host is not None: + chroma_settings = chromadb.config.Settings( + chroma_server_cors_allow_origins=chroma_server_cors_allow_origins or None, + chroma_server_host=chroma_server_host, + chroma_server_port=chroma_server_port or None, + chroma_server_grpc_port=chroma_server_grpc_port or None, + chroma_server_ssl_enabled=chroma_server_ssl_enabled, + ) + if index_directory: + index_directory = self.resolve_path(index_directory) + vector_store = Chroma( + embedding_function=embedding, + collection_name=collection_name, + persist_directory=index_directory, + client_settings=chroma_settings, + ) + + return self.search_with_vector_store(input_value, search_type, vector_store, k=number_of_results) diff --git a/src/backend/base/langflow/components/vectorsearch/FAISSSearch.py b/src/backend/base/langflow/components/vectorsearch/FAISSSearch.py new file mode 100644 index 000000000..d68f455cc --- /dev/null +++ b/src/backend/base/langflow/components/vectorsearch/FAISSSearch.py @@ -0,0 +1,48 @@ +from typing import List + +from langchain_community.vectorstores.faiss import FAISS + +from langflow.components.vectorstores.base.model import LCVectorStoreComponent +from langflow.field_typing import Embeddings, Text +from langflow.schema import Record + + +class FAISSSearchComponent(LCVectorStoreComponent): + display_name = "FAISS Search" + description = "Search a FAISS Vector Store for similar documents." + documentation = "https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/faiss" + + def build_config(self): + return { + "embedding": {"display_name": "Embedding"}, + "folder_path": { + "display_name": "Folder Path", + "info": "Path to save the FAISS index. It will be relative to where Langflow is running.", + }, + "input_value": {"display_name": "Input"}, + "index_name": {"display_name": "Index Name"}, + "number_of_results": { + "display_name": "Number of Results", + "info": "Number of results to return.", + "advanced": True, + }, + } + + def build( + self, + input_value: Text, + embedding: Embeddings, + folder_path: str, + number_of_results: int = 4, + index_name: str = "langflow_index", + ) -> List[Record]: + if not folder_path: + raise ValueError("Folder path is required to save the FAISS index.") + path = self.resolve_path(folder_path) + vector_store = FAISS.load_local(folder_path=Text(path), embeddings=embedding, index_name=index_name) + if not vector_store: + raise ValueError("Failed to load the FAISS index.") + + return self.search_with_vector_store( + vector_store=vector_store, input_value=input_value, search_type="similarity", k=number_of_results + ) diff --git a/src/backend/base/langflow/components/vectorsearch/MongoDBAtlasVectorSearch.py b/src/backend/base/langflow/components/vectorsearch/MongoDBAtlasVectorSearch.py new file mode 100644 index 000000000..0ecde1688 --- /dev/null +++ b/src/backend/base/langflow/components/vectorsearch/MongoDBAtlasVectorSearch.py @@ -0,0 +1,57 @@ +from typing import List, Optional + +from langflow.components.vectorstores.base.model import LCVectorStoreComponent +from langflow.components.vectorstores.MongoDBAtlasVector import MongoDBAtlasComponent +from langflow.field_typing import Embeddings, NestedDict, Text +from langflow.schema import Record + + +class MongoDBAtlasSearchComponent(LCVectorStoreComponent): + display_name = "MongoDB Atlas Search" + description = "Search a MongoDB Atlas Vector Store for similar documents." + + def build_config(self): + return { + "search_type": { + "display_name": "Search Type", + "options": ["Similarity", "MMR"], + }, + "input_value": {"display_name": "Input"}, + "embedding": {"display_name": "Embedding"}, + "collection_name": {"display_name": "Collection Name"}, + "db_name": {"display_name": "Database Name"}, + "index_name": {"display_name": "Index Name"}, + "mongodb_atlas_cluster_uri": {"display_name": "MongoDB Atlas Cluster URI"}, + "search_kwargs": {"display_name": "Search Kwargs", "advanced": True}, + "number_of_results": { + "display_name": "Number of Results", + "info": "Number of results to return.", + "advanced": True, + }, + } + + def build( # type: ignore[override] + self, + input_value: Text, + search_type: str, + embedding: Embeddings, + number_of_results: int = 4, + collection_name: str = "", + db_name: str = "", + index_name: str = "", + mongodb_atlas_cluster_uri: str = "", + search_kwargs: Optional[NestedDict] = None, + ) -> List[Record]: + search_kwargs = search_kwargs or {} + vector_store = MongoDBAtlasComponent().build( + mongodb_atlas_cluster_uri=mongodb_atlas_cluster_uri, + collection_name=collection_name, + db_name=db_name, + embedding=embedding, + index_name=index_name, + ) + if not vector_store: + raise ValueError("Failed to create MongoDB Atlas Vector Store") + return self.search_with_vector_store( + vector_store=vector_store, input_value=input_value, search_type=search_type, k=number_of_results + ) diff --git a/src/backend/base/langflow/components/vectorsearch/PineconeSearch.py b/src/backend/base/langflow/components/vectorsearch/PineconeSearch.py new file mode 100644 index 000000000..96ba35743 --- /dev/null +++ b/src/backend/base/langflow/components/vectorsearch/PineconeSearch.py @@ -0,0 +1,76 @@ +from typing import List, Optional + +from langflow.components.vectorstores.base.model import LCVectorStoreComponent +from langflow.components.vectorstores.Pinecone import PineconeComponent +from langflow.field_typing import Embeddings, Text +from langflow.schema import Record + + +class PineconeSearchComponent(PineconeComponent, LCVectorStoreComponent): + display_name = "Pinecone Search" + description = "Search a Pinecone Vector Store for similar documents." + icon = "Pinecone" + + def build_config(self): + return { + "search_type": { + "display_name": "Search Type", + "options": ["Similarity", "MMR"], + }, + "input_value": {"display_name": "Input"}, + "embedding": {"display_name": "Embedding"}, + "index_name": {"display_name": "Index Name"}, + "namespace": {"display_name": "Namespace"}, + "pinecone_api_key": { + "display_name": "Pinecone API Key", + "default": "", + "password": True, + "required": True, + }, + "pinecone_env": { + "display_name": "Pinecone Environment", + "default": "", + "required": True, + }, + "search_kwargs": {"display_name": "Search Kwargs", "default": "{}"}, + "pool_threads": { + "display_name": "Pool Threads", + "default": 1, + "advanced": True, + }, + "number_of_results": { + "display_name": "Number of Results", + "info": "Number of results to return.", + "advanced": True, + }, + } + + def build( # type: ignore[override] + self, + input_value: Text, + embedding: Embeddings, + pinecone_env: str, + text_key: str = "text", + number_of_results: int = 4, + pool_threads: int = 4, + index_name: Optional[str] = None, + pinecone_api_key: Optional[str] = None, + namespace: Optional[str] = "default", + search_type: str = "similarity", + ) -> List[Record]: # type: ignore[override] + vector_store = super().build( + embedding=embedding, + pinecone_env=pinecone_env, + inputs=[], + text_key=text_key, + pool_threads=pool_threads, + index_name=index_name, + pinecone_api_key=pinecone_api_key, + namespace=namespace, + ) + if not vector_store: + raise ValueError("Failed to load the Pinecone index.") + + return self.search_with_vector_store( + vector_store=vector_store, input_value=input_value, search_type=search_type, k=number_of_results + ) diff --git a/src/backend/base/langflow/components/vectorsearch/QdrantSearch.py b/src/backend/base/langflow/components/vectorsearch/QdrantSearch.py new file mode 100644 index 000000000..8fcc5d761 --- /dev/null +++ b/src/backend/base/langflow/components/vectorsearch/QdrantSearch.py @@ -0,0 +1,98 @@ +from typing import List, Optional + +from langflow.components.vectorstores.base.model import LCVectorStoreComponent +from langflow.components.vectorstores.Qdrant import QdrantComponent +from langflow.field_typing import Embeddings, NestedDict, Text +from langflow.schema import Record + + +class QdrantSearchComponent(QdrantComponent, LCVectorStoreComponent): + display_name = "Qdrant Search" + description = "Construct Qdrant wrapper from a list of texts." + icon = "Qdrant" + + def build_config(self): + return { + "search_type": { + "display_name": "Search Type", + "options": ["Similarity", "MMR"], + }, + "input_value": {"display_name": "Input"}, + "embedding": {"display_name": "Embedding"}, + "api_key": {"display_name": "API Key", "password": True, "advanced": True}, + "collection_name": {"display_name": "Collection Name"}, + "content_payload_key": { + "display_name": "Content Payload Key", + "advanced": True, + }, + "distance_func": {"display_name": "Distance Function", "advanced": True}, + "grpc_port": {"display_name": "gRPC Port", "advanced": True}, + "host": {"display_name": "Host", "advanced": True}, + "https": {"display_name": "HTTPS", "advanced": True}, + "location": {"display_name": "Location", "advanced": True}, + "metadata_payload_key": { + "display_name": "Metadata Payload Key", + "advanced": True, + }, + "path": {"display_name": "Path", "advanced": True}, + "port": {"display_name": "Port", "advanced": True}, + "prefer_grpc": {"display_name": "Prefer gRPC", "advanced": True}, + "prefix": {"display_name": "Prefix", "advanced": True}, + "search_kwargs": {"display_name": "Search Kwargs", "advanced": True}, + "timeout": {"display_name": "Timeout", "advanced": True}, + "url": {"display_name": "URL", "advanced": True}, + "number_of_results": { + "display_name": "Number of Results", + "info": "Number of results to return.", + "advanced": True, + }, + } + + def build( # type: ignore[override] + self, + input_value: Text, + embedding: Embeddings, + collection_name: str, + number_of_results: int = 4, + search_type: str = "similarity", + api_key: Optional[str] = None, + content_payload_key: str = "page_content", + distance_func: str = "Cosine", + grpc_port: int = 6334, + https: bool = False, + host: Optional[str] = None, + location: Optional[str] = None, + metadata_payload_key: str = "metadata", + path: Optional[str] = None, + port: Optional[int] = 6333, + prefer_grpc: bool = False, + prefix: Optional[str] = None, + search_kwargs: Optional[NestedDict] = None, + timeout: Optional[int] = None, + url: Optional[str] = None, + ) -> List[Record]: # type: ignore[override] + vector_store = super().build( + embedding=embedding, + collection_name=collection_name, + api_key=api_key, + content_payload_key=content_payload_key, + distance_func=distance_func, + grpc_port=grpc_port, + https=https, + host=host, + location=location, + metadata_payload_key=metadata_payload_key, + path=path, + port=port, + prefer_grpc=prefer_grpc, + prefix=prefix, + search_kwargs=search_kwargs, + timeout=timeout, + url=url, + ) + if not vector_store: + raise ValueError("Failed to load the Qdrant index.") + + return self.search_with_vector_store( + vector_store=vector_store, input_value=input_value, search_type=search_type, k=number_of_results + ) diff --git a/src/backend/base/langflow/components/vectorsearch/RedisSearch.py b/src/backend/base/langflow/components/vectorsearch/RedisSearch.py new file mode 100644 index 000000000..25e71c64b --- /dev/null +++ b/src/backend/base/langflow/components/vectorsearch/RedisSearch.py @@ -0,0 +1,82 @@ +from typing import List, Optional + +from langchain.embeddings.base import Embeddings + +from langflow.components.vectorstores.base.model import LCVectorStoreComponent +from langflow.components.vectorstores.Redis import RedisComponent +from langflow.field_typing import Text +from langflow.schema import Record + + +class RedisSearchComponent(RedisComponent, LCVectorStoreComponent): + """ + A custom component for implementing a Vector Store using Redis. + """ + + display_name: str = "Redis Search" + description: str = "Search a Redis Vector Store for similar documents." + documentation = "https://python.langchain.com/docs/integrations/vectorstores/redis" + + def build_config(self): + """ + Builds the configuration for the component. + + Returns: + - dict: A dictionary containing the configuration options for the component. + """ + return { + "search_type": { + "display_name": "Search Type", + "options": ["Similarity", "MMR"], + }, + "input_value": {"display_name": "Input"}, + "index_name": {"display_name": "Index Name", "value": "your_index"}, + "code": {"show": False, "display_name": "Code"}, + "embedding": {"display_name": "Embedding"}, + "schema": {"display_name": "Schema", "file_types": [".yaml"]}, + "redis_server_url": { + "display_name": "Redis Server Connection String", + "advanced": False, + }, + "redis_index_name": {"display_name": "Redis Index", "advanced": False}, + "number_of_results": { + "display_name": "Number of Results", + "info": "Number of results to return.", + "advanced": True, + }, + } + + def build( # type: ignore[override] + self, + input_value: Text, + search_type: str, + embedding: Embeddings, + redis_server_url: str, + redis_index_name: str, + number_of_results: int = 4, + schema: Optional[str] = None, + ) -> List[Record]: + """ + Builds the Vector Store or BaseRetriever object. + + Args: + - embedding (Embeddings): The embeddings to use for the Vector Store. + - documents (Optional[Document]): The documents to use for the Vector Store. + - redis_index_name (str): The name of the Redis index. + - redis_server_url (str): The URL for the Redis server. + + Returns: + - VectorStore: The Vector Store object. + """ + vector_store = super().build( + embedding=embedding, + redis_server_url=redis_server_url, + redis_index_name=redis_index_name, + schema=schema, + ) + if not vector_store: + raise ValueError("Failed to load the Redis index.") + + return self.search_with_vector_store( + input_value=input_value, search_type=search_type, vector_store=vector_store, k=number_of_results + ) diff --git a/src/backend/base/langflow/components/vectorsearch/SupabaseVectorStoreSearch.py b/src/backend/base/langflow/components/vectorsearch/SupabaseVectorStoreSearch.py new file mode 100644 index 000000000..aef1c13b7 --- /dev/null +++ b/src/backend/base/langflow/components/vectorsearch/SupabaseVectorStoreSearch.py @@ -0,0 +1,54 @@ +from typing import List + +from langchain_community.vectorstores.supabase import SupabaseVectorStore +from supabase.client import Client, create_client + +from langflow.components.vectorstores.base.model import LCVectorStoreComponent +from langflow.field_typing import Embeddings, Text +from langflow.schema import Record + + +class SupabaseSearchComponent(LCVectorStoreComponent): + display_name = "Supabase Search" + description = "Search a Supabase Vector Store for similar documents." + icon = "Supabase" + + def build_config(self): + return { + "search_type": { + "display_name": "Search Type", + "options": ["Similarity", "MMR"], + }, + "input_value": {"display_name": "Input"}, + "embedding": {"display_name": "Embedding"}, + "query_name": {"display_name": "Query Name"}, + "search_kwargs": {"display_name": "Search Kwargs", "advanced": True}, + "supabase_service_key": {"display_name": "Supabase Service Key"}, + "supabase_url": {"display_name": "Supabase URL"}, + "table_name": {"display_name": "Table Name", "advanced": True}, + "number_of_results": { + "display_name": "Number of Results", + "info": "Number of results to return.", + "advanced": True, + }, + } + + def build( + self, + input_value: Text, + search_type: str, + embedding: Embeddings, + number_of_results: int = 4, + query_name: str = "", + supabase_service_key: str = "", + supabase_url: str = "", + table_name: str = "", + ) -> List[Record]: + supabase: Client = create_client(supabase_url, supabase_key=supabase_service_key) + vector_store = SupabaseVectorStore( + client=supabase, + embedding=embedding, + table_name=table_name, + query_name=query_name, + ) + return self.search_with_vector_store(input_value, search_type, vector_store, k=number_of_results) diff --git a/src/backend/base/langflow/components/vectorsearch/VectaraSearch.py b/src/backend/base/langflow/components/vectorsearch/VectaraSearch.py new file mode 100644 index 000000000..459054f67 --- /dev/null +++ b/src/backend/base/langflow/components/vectorsearch/VectaraSearch.py @@ -0,0 +1,66 @@ +from typing import List + +from langchain_community.vectorstores.vectara import Vectara + +from langflow.components.vectorstores.base.model import LCVectorStoreComponent +from langflow.components.vectorstores.Vectara import VectaraComponent +from langflow.field_typing import Text +from langflow.schema import Record + + +class VectaraSearchComponent(VectaraComponent, LCVectorStoreComponent): + display_name: str = "Vectara Search" + description: str = "Search a Vectara Vector Store for similar documents." + documentation = "https://python.langchain.com/docs/integrations/vectorstores/vectara" + icon = "Vectara" + + field_config = { + "search_type": { + "display_name": "Search Type", + "options": ["Similarity", "MMR"], + }, + "input_value": {"display_name": "Input"}, + "vectara_customer_id": { + "display_name": "Vectara Customer ID", + }, + "vectara_corpus_id": { + "display_name": "Vectara Corpus ID", + }, + "vectara_api_key": { + "display_name": "Vectara API Key", + "password": True, + }, + "files_url": { + "display_name": "Files Url", + "info": "Make vectara object using url of files (optional)", + }, + "number_of_results": { + "display_name": "Number of Results", + "info": "Number of results to return.", + "advanced": True, + }, + } + + def build( # type: ignore[override] + self, + input_value: Text, + search_type: str, + vectara_customer_id: str, + vectara_corpus_id: str, + vectara_api_key: str, + number_of_results: int = 4, + ) -> List[Record]: + source = "Langflow" + vector_store = Vectara( + vectara_customer_id=vectara_customer_id, + vectara_corpus_id=vectara_corpus_id, + vectara_api_key=vectara_api_key, + source=source, + ) + + if not vector_store: + raise ValueError("Failed to create Vectara Vector Store") + + return self.search_with_vector_store( + vector_store=vector_store, input_value=input_value, search_type=search_type, k=number_of_results + ) diff --git a/src/backend/base/langflow/components/vectorsearch/WeaviateSearch.py b/src/backend/base/langflow/components/vectorsearch/WeaviateSearch.py new file mode 100644 index 000000000..f47538f2e --- /dev/null +++ b/src/backend/base/langflow/components/vectorsearch/WeaviateSearch.py @@ -0,0 +1,86 @@ +from typing import List, Optional + +from langchain.embeddings.base import Embeddings + +from langflow.components.vectorstores.base.model import LCVectorStoreComponent +from langflow.components.vectorstores.Weaviate import WeaviateVectorStoreComponent +from langflow.field_typing import Text +from langflow.schema import Record + + +class WeaviateSearchVectorStore(WeaviateVectorStoreComponent, LCVectorStoreComponent): + display_name: str = "Weaviate Search" + description: str = "Search a Weaviate Vector Store for similar documents." + documentation = "https://python.langchain.com/docs/integrations/vectorstores/weaviate" + icon = "Weaviate" + + field_config = { + "search_type": { + "display_name": "Search Type", + "options": ["Similarity", "MMR"], + }, + "input_value": {"display_name": "Input"}, + "url": {"display_name": "Weaviate URL", "value": "http://localhost:8080"}, + "api_key": { + "display_name": "API Key", + "password": True, + "required": False, + }, + "index_name": { + "display_name": "Index name", + "required": False, + }, + "text_key": { + "display_name": "Text Key", + "required": False, + "advanced": True, + "value": "text", + }, + "embedding": {"display_name": "Embedding"}, + "attributes": { + "display_name": "Attributes", + "required": False, + "is_list": True, + "field_type": "str", + "advanced": True, + }, + "search_by_text": { + "display_name": "Search By Text", + "field_type": "bool", + "advanced": True, + }, + "number_of_results": { + "display_name": "Number of Results", + "info": "Number of results to return.", + "advanced": True, + }, + } + + def build( # type: ignore[override] + self, + input_value: Text, + search_type: str, + url: str, + number_of_results: int = 4, + search_by_text: bool = False, + api_key: Optional[str] = None, + index_name: Optional[str] = None, + text_key: str = "text", + embedding: Optional[Embeddings] = None, + attributes: Optional[list] = None, + ) -> List[Record]: + vector_store = super().build( + url=url, + api_key=api_key, + index_name=index_name, + text_key=text_key, + embedding=embedding, + attributes=attributes, + search_by_text=search_by_text, + ) + if not vector_store: + raise ValueError("Failed to load the Weaviate index.") + + return self.search_with_vector_store( + vector_store=vector_store, input_value=input_value, search_type=search_type, k=number_of_results + ) diff --git a/src/backend/base/langflow/components/vectorsearch/__init__.py b/src/backend/base/langflow/components/vectorsearch/__init__.py new file mode 100644 index 000000000..28ea85fce --- /dev/null +++ b/src/backend/base/langflow/components/vectorsearch/__init__.py @@ -0,0 +1,25 @@ +from .AstraDBSearch import AstraDBSearchComponent +from .ChromaSearch import ChromaSearchComponent +from .FAISSSearch import FAISSSearchComponent +from .MongoDBAtlasVectorSearch import MongoDBAtlasSearchComponent +from .PineconeSearch import PineconeSearchComponent +from .QdrantSearch import QdrantSearchComponent +from .RedisSearch import RedisSearchComponent +from .SupabaseVectorStoreSearch import SupabaseSearchComponent +from .VectaraSearch import VectaraSearchComponent +from .WeaviateSearch import WeaviateSearchVectorStore +from .pgvectorSearch import PGVectorSearchComponent + +__all__ = [ + "AstraDBSearchComponent", + "ChromaSearchComponent", + "FAISSSearchComponent", + "MongoDBAtlasSearchComponent", + "PineconeSearchComponent", + "QdrantSearchComponent", + "RedisSearchComponent", + "SupabaseSearchComponent", + "VectaraSearchComponent", + "WeaviateSearchVectorStore", + "PGVectorSearchComponent", +] diff --git a/src/backend/base/langflow/components/vectorsearch/pgvectorSearch.py b/src/backend/base/langflow/components/vectorsearch/pgvectorSearch.py new file mode 100644 index 000000000..9b074b5f6 --- /dev/null +++ b/src/backend/base/langflow/components/vectorsearch/pgvectorSearch.py @@ -0,0 +1,74 @@ +from typing import List + +from langchain.embeddings.base import Embeddings + +from langflow.components.vectorstores.base.model import LCVectorStoreComponent +from langflow.components.vectorstores.pgvector import PGVectorComponent +from langflow.field_typing import Text +from langflow.schema import Record + + +class PGVectorSearchComponent(PGVectorComponent, LCVectorStoreComponent): + display_name: str = "PGVector Search" + description: str = "Search a PGVector Store for similar documents." + documentation = "https://python.langchain.com/docs/integrations/vectorstores/pgvector" + + def build_config(self): + """ + Builds the configuration for the component. + + Returns: + - dict: A dictionary containing the configuration options for the component. + """ + return { + "code": {"show": False}, + "embedding": {"display_name": "Embedding"}, + "search_type": { + "display_name": "Search Type", + "options": ["Similarity", "MMR"], + }, + "pg_server_url": { + "display_name": "PostgreSQL Server Connection String", + "advanced": False, + }, + "collection_name": {"display_name": "Table", "advanced": False}, + "input_value": {"display_name": "Input"}, + "number_of_results": { + "display_name": "Number of Results", + "info": "Number of results to return.", + "advanced": True, + }, + } + + def build( # type: ignore[override] + self, + input_value: Text, + embedding: Embeddings, + search_type: str, + pg_server_url: str, + collection_name: str, + number_of_results: int = 4, + ) -> List[Record]: + """ + Builds the Vector Store or BaseRetriever object. + + Args: + - input_value (str): The input value to search for. + - embedding (Embeddings): The embeddings to use for the Vector Store. + - collection_name (str): The name of the PG table. + - pg_server_url (str): The URL for the PG server. + + Returns: + - VectorStore: The Vector Store object. + """ + try: + vector_store = super().build( + embedding=embedding, + pg_server_url=pg_server_url, + collection_name=collection_name, + ) + except Exception as e: + raise RuntimeError(f"Failed to build PGVector: {e}") + return self.search_with_vector_store( + input_value=input_value, search_type=search_type, vector_store=vector_store, k=number_of_results + ) diff --git a/src/backend/base/langflow/components/vectorstores/AstraDB.py b/src/backend/base/langflow/components/vectorstores/AstraDB.py new file mode 100644 index 000000000..460d1f6db --- /dev/null +++ b/src/backend/base/langflow/components/vectorstores/AstraDB.py @@ -0,0 +1,158 @@ +from typing import List, Optional + +from langchain_astradb import AstraDBVectorStore +from langchain_astradb.utils.astradb import SetupMode + +from langflow.custom import CustomComponent +from langflow.field_typing import Embeddings, VectorStore +from langflow.schema import Record + + +class AstraDBVectorStoreComponent(CustomComponent): + display_name = "Astra DB" + description = "Builds or loads an Astra DB Vector Store." + icon = "AstraDB" + field_order = ["token", "api_endpoint", "collection_name", "inputs", "embedding"] + + def build_config(self): + return { + "inputs": { + "display_name": "Inputs", + "info": "Optional list of records to be processed and stored in the vector store.", + }, + "embedding": {"display_name": "Embedding", "info": "Embedding to use"}, + "collection_name": { + "display_name": "Collection Name", + "info": "The name of the collection within Astra DB where the vectors will be stored.", + }, + "token": { + "display_name": "Token", + "info": "Authentication token for accessing Astra DB.", + "password": True, + }, + "api_endpoint": { + "display_name": "API Endpoint", + "info": "API endpoint URL for the Astra DB service.", + }, + "namespace": { + "display_name": "Namespace", + "info": "Optional namespace within Astra DB to use for the collection.", + "advanced": True, + }, + "metric": { + "display_name": "Metric", + "info": "Optional distance metric for vector comparisons in the vector store.", + "advanced": True, + }, + "batch_size": { + "display_name": "Batch Size", + "info": "Optional number of records to process in a single batch.", + "advanced": True, + }, + "bulk_insert_batch_concurrency": { + "display_name": "Bulk Insert Batch Concurrency", + "info": "Optional concurrency level for bulk insert operations.", + "advanced": True, + }, + "bulk_insert_overwrite_concurrency": { + "display_name": "Bulk Insert Overwrite Concurrency", + "info": "Optional concurrency level for bulk insert operations that overwrite existing records.", + "advanced": True, + }, + "bulk_delete_concurrency": { + "display_name": "Bulk Delete Concurrency", + "info": "Optional concurrency level for bulk delete operations.", + "advanced": True, + }, + "setup_mode": { + "display_name": "Setup Mode", + "info": "Configuration mode for setting up the vector store, with options like “Sync”, “Async”, or “Off”.", + "options": ["Sync", "Async", "Off"], + "advanced": True, + }, + "pre_delete_collection": { + "display_name": "Pre Delete Collection", + "info": "Boolean flag to determine whether to delete the collection before creating a new one.", + "advanced": True, + }, + "metadata_indexing_include": { + "display_name": "Metadata Indexing Include", + "info": "Optional list of metadata fields to include in the indexing.", + "advanced": True, + }, + "metadata_indexing_exclude": { + "display_name": "Metadata Indexing Exclude", + "info": "Optional list of metadata fields to exclude from the indexing.", + "advanced": True, + }, + "collection_indexing_policy": { + "display_name": "Collection Indexing Policy", + "info": "Optional dictionary defining the indexing policy for the collection.", + "advanced": True, + }, + } + + def build( + self, + embedding: Embeddings, + token: str, + api_endpoint: str, + collection_name: str, + inputs: Optional[List[Record]] = None, + namespace: Optional[str] = None, + metric: Optional[str] = None, + batch_size: Optional[int] = None, + bulk_insert_batch_concurrency: Optional[int] = None, + bulk_insert_overwrite_concurrency: Optional[int] = None, + bulk_delete_concurrency: Optional[int] = None, + setup_mode: str = "Async", + pre_delete_collection: bool = False, + metadata_indexing_include: Optional[List[str]] = None, + metadata_indexing_exclude: Optional[List[str]] = None, + collection_indexing_policy: Optional[dict] = None, + ) -> VectorStore: + try: + setup_mode_value = SetupMode[setup_mode.upper()] + except KeyError: + raise ValueError(f"Invalid setup mode: {setup_mode}") + if inputs: + documents = [_input.to_lc_document() for _input in inputs] + + vector_store = AstraDBVectorStore.from_documents( + documents=documents, + embedding=embedding, + collection_name=collection_name, + token=token, + api_endpoint=api_endpoint, + namespace=namespace, + metric=metric, + batch_size=batch_size, + bulk_insert_batch_concurrency=bulk_insert_batch_concurrency, + bulk_insert_overwrite_concurrency=bulk_insert_overwrite_concurrency, + bulk_delete_concurrency=bulk_delete_concurrency, + setup_mode=setup_mode_value, + pre_delete_collection=pre_delete_collection, + metadata_indexing_include=metadata_indexing_include, + metadata_indexing_exclude=metadata_indexing_exclude, + collection_indexing_policy=collection_indexing_policy, + ) + else: + vector_store = AstraDBVectorStore( + embedding=embedding, + collection_name=collection_name, + token=token, + api_endpoint=api_endpoint, + namespace=namespace, + metric=metric, + batch_size=batch_size, + bulk_insert_batch_concurrency=bulk_insert_batch_concurrency, + bulk_insert_overwrite_concurrency=bulk_insert_overwrite_concurrency, + bulk_delete_concurrency=bulk_delete_concurrency, + setup_mode=setup_mode_value, + pre_delete_collection=pre_delete_collection, + metadata_indexing_include=metadata_indexing_include, + metadata_indexing_exclude=metadata_indexing_exclude, + collection_indexing_policy=collection_indexing_policy, + ) + + return vector_store diff --git a/src/backend/langflow/components/vectorstores/Chroma.py b/src/backend/base/langflow/components/vectorstores/Chroma.py similarity index 75% rename from src/backend/langflow/components/vectorstores/Chroma.py rename to src/backend/base/langflow/components/vectorstores/Chroma.py index 6eb8fedd6..8fe2f54a9 100644 --- a/src/backend/langflow/components/vectorstores/Chroma.py +++ b/src/backend/base/langflow/components/vectorstores/Chroma.py @@ -2,10 +2,12 @@ from typing import List, Optional, Union import chromadb # type: ignore from langchain.embeddings.base import Embeddings -from langchain.schema import BaseRetriever, Document +from langchain.schema import BaseRetriever from langchain_community.vectorstores import VectorStore from langchain_community.vectorstores.chroma import Chroma -from langflow import CustomComponent + +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema.schema import Record class ChromaComponent(CustomComponent): @@ -16,7 +18,7 @@ class ChromaComponent(CustomComponent): display_name: str = "Chroma" description: str = "Implementation of Vector Store using Chroma" documentation = "https://python.langchain.com/docs/integrations/vectorstores/chroma" - beta: bool = True + icon = "Chroma" def build_config(self): """ @@ -27,10 +29,9 @@ class ChromaComponent(CustomComponent): """ return { "collection_name": {"display_name": "Collection Name", "value": "langflow"}, - "persist": {"display_name": "Persist"}, - "persist_directory": {"display_name": "Persist Directory"}, + "index_directory": {"display_name": "Persist Directory"}, "code": {"advanced": True, "display_name": "Code"}, - "documents": {"display_name": "Documents", "is_list": True}, + "inputs": {"display_name": "Input", "input_types": ["Document", "Record"]}, "embedding": {"display_name": "Embedding"}, "chroma_server_cors_allow_origins": { "display_name": "Server CORS Allow Origins", @@ -51,11 +52,10 @@ class ChromaComponent(CustomComponent): def build( self, collection_name: str, - persist: bool, embedding: Embeddings, chroma_server_ssl_enabled: bool, - persist_directory: Optional[str] = None, - documents: Optional[List[Document]] = None, + index_directory: Optional[str] = None, + inputs: Optional[List[Record]] = None, chroma_server_cors_allow_origins: Optional[str] = None, chroma_server_host: Optional[str] = None, chroma_server_port: Optional[int] = None, @@ -66,9 +66,8 @@ class ChromaComponent(CustomComponent): Args: - collection_name (str): The name of the collection. - - persist_directory (Optional[str]): The directory to persist the Vector Store to. + - index_directory (Optional[str]): The directory to persist the Vector Store to. - chroma_server_ssl_enabled (bool): Whether to enable SSL for the Chroma server. - - persist (bool): Whether to persist the Vector Store or not. - embedding (Optional[Embeddings]): The embeddings to use for the Vector Store. - documents (Optional[Document]): The documents to use for the Vector Store. - chroma_server_cors_allow_origins (Optional[str]): The CORS allow origins for the Chroma server. @@ -93,15 +92,31 @@ class ChromaComponent(CustomComponent): ) # If documents, then we need to create a Chroma instance using .from_documents + + # Check index_directory and expand it if it is a relative path + if index_directory is not None: + index_directory = self.resolve_path(index_directory) + + documents = [] + for _input in inputs or []: + if isinstance(_input, Record): + documents.append(_input.to_lc_document()) + else: + documents.append(_input) if documents is not None and embedding is not None: if len(documents) == 0: raise ValueError("If documents are provided, there must be at least one document.") - return Chroma.from_documents( + chroma = Chroma.from_documents( documents=documents, # type: ignore - persist_directory=persist_directory if persist else None, + persist_directory=index_directory, collection_name=collection_name, embedding=embedding, client_settings=chroma_settings, ) - - return Chroma(persist_directory=persist_directory, client_settings=chroma_settings) + else: + chroma = Chroma( + persist_directory=index_directory, + client_settings=chroma_settings, + embedding_function=embedding, + ) + return chroma diff --git a/src/backend/base/langflow/components/vectorstores/FAISS.py b/src/backend/base/langflow/components/vectorstores/FAISS.py new file mode 100644 index 000000000..ea9ee1c4d --- /dev/null +++ b/src/backend/base/langflow/components/vectorstores/FAISS.py @@ -0,0 +1,46 @@ +from typing import List, Text, Union + +from langchain.schema import BaseRetriever +from langchain_community.vectorstores import VectorStore +from langchain_community.vectorstores.faiss import FAISS + +from langflow.field_typing import Embeddings +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema.schema import Record + + +class FAISSComponent(CustomComponent): + display_name = "FAISS" + description = "Ingest documents into FAISS Vector Store." + documentation = "https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/faiss" + + def build_config(self): + return { + "inputs": {"display_name": "Input", "input_types": ["Document", "Record"]}, + "embedding": {"display_name": "Embedding"}, + "folder_path": { + "display_name": "Folder Path", + "info": "Path to save the FAISS index. It will be relative to where Langflow is running.", + }, + "index_name": {"display_name": "Index Name"}, + } + + def build( + self, + embedding: Embeddings, + inputs: List[Record], + folder_path: str, + index_name: str = "langflow_index", + ) -> Union[VectorStore, FAISS, BaseRetriever]: + documents = [] + for _input in inputs or []: + if isinstance(_input, Record): + documents.append(_input.to_lc_document()) + else: + documents.append(_input) + vector_store = FAISS.from_documents(documents=documents, embedding=embedding) + if not folder_path: + raise ValueError("Folder path is required to save the FAISS index.") + path = self.resolve_path(folder_path) + vector_store.save_local(Text(path), index_name) + return vector_store diff --git a/src/backend/base/langflow/components/vectorstores/MongoDBAtlasVector.py b/src/backend/base/langflow/components/vectorstores/MongoDBAtlasVector.py new file mode 100644 index 000000000..5a12488e4 --- /dev/null +++ b/src/backend/base/langflow/components/vectorstores/MongoDBAtlasVector.py @@ -0,0 +1,67 @@ +from typing import List, Optional + +from langchain_community.vectorstores.mongodb_atlas import MongoDBAtlasVectorSearch +from langflow.field_typing import Embeddings, NestedDict +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema.schema import Record + + +class MongoDBAtlasComponent(CustomComponent): + display_name = "MongoDB Atlas" + description = "Construct a `MongoDB Atlas Vector Search` vector store from raw documents." + icon = "MongoDB" + + def build_config(self): + return { + "inputs": {"display_name": "Input", "input_types": ["Document", "Record"]}, + "embedding": {"display_name": "Embedding"}, + "collection_name": {"display_name": "Collection Name"}, + "db_name": {"display_name": "Database Name"}, + "index_name": {"display_name": "Index Name"}, + "mongodb_atlas_cluster_uri": {"display_name": "MongoDB Atlas Cluster URI"}, + "search_kwargs": {"display_name": "Search Kwargs", "advanced": True}, + } + + def build( + self, + embedding: Embeddings, + inputs: Optional[List[Record]] = None, + collection_name: str = "", + db_name: str = "", + index_name: str = "", + mongodb_atlas_cluster_uri: str = "", + search_kwargs: Optional[NestedDict] = None, + ) -> MongoDBAtlasVectorSearch: + search_kwargs = search_kwargs or {} + try: + from pymongo import MongoClient + except ImportError: + raise ImportError("Please install pymongo to use MongoDB Atlas Vector Store") + try: + mongo_client: MongoClient = MongoClient(mongodb_atlas_cluster_uri) + collection = mongo_client[db_name][collection_name] + except Exception as e: + raise ValueError(f"Failed to connect to MongoDB Atlas: {e}") + documents = [] + for _input in inputs or []: + if isinstance(_input, Record): + documents.append(_input.to_lc_document()) + else: + documents.append(_input) + if documents: + vector_store = MongoDBAtlasVectorSearch.from_documents( + documents=documents, + embedding=embedding, + collection=collection, + db_name=db_name, + index_name=index_name, + mongodb_atlas_cluster_uri=mongodb_atlas_cluster_uri, + search_kwargs=search_kwargs, + ) + else: + vector_store = MongoDBAtlasVectorSearch( + embedding=embedding, + collection=collection, + index_name=index_name, + ) + return vector_store diff --git a/src/backend/langflow/components/vectorstores/Pinecone.py b/src/backend/base/langflow/components/vectorstores/Pinecone.py similarity index 65% rename from src/backend/langflow/components/vectorstores/Pinecone.py rename to src/backend/base/langflow/components/vectorstores/Pinecone.py index 147af1df8..e4d6de3aa 100644 --- a/src/backend/langflow/components/vectorstores/Pinecone.py +++ b/src/backend/base/langflow/components/vectorstores/Pinecone.py @@ -5,31 +5,47 @@ import pinecone # type: ignore from langchain.schema import BaseRetriever from langchain_community.vectorstores import VectorStore from langchain_community.vectorstores.pinecone import Pinecone -from langflow import CustomComponent -from langflow.field_typing import Document, Embeddings + +from langflow.field_typing import Embeddings +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema.schema import Record class PineconeComponent(CustomComponent): display_name = "Pinecone" description = "Construct Pinecone wrapper from raw documents." + icon = "Pinecone" def build_config(self): return { - "documents": {"display_name": "Documents"}, + "inputs": {"display_name": "Input", "input_types": ["Document", "Record"]}, "embedding": {"display_name": "Embedding"}, "index_name": {"display_name": "Index Name"}, "namespace": {"display_name": "Namespace"}, - "pinecone_api_key": {"display_name": "Pinecone API Key", "default": "", "password": True, "required": True}, - "pinecone_env": {"display_name": "Pinecone Environment", "default": "", "required": True}, + "pinecone_api_key": { + "display_name": "Pinecone API Key", + "default": "", + "password": True, + "required": True, + }, + "pinecone_env": { + "display_name": "Pinecone Environment", + "default": "", + "required": True, + }, "search_kwargs": {"display_name": "Search Kwargs", "default": "{}"}, - "pool_threads": {"display_name": "Pool Threads", "default": 1, "advanced": True}, + "pool_threads": { + "display_name": "Pool Threads", + "default": 1, + "advanced": True, + }, } def build( self, embedding: Embeddings, pinecone_env: str, - documents: List[Document], + inputs: Optional[List[Record]] = None, text_key: str = "text", pool_threads: int = 4, index_name: Optional[str] = None, @@ -44,6 +60,12 @@ class PineconeComponent(CustomComponent): pinecone.init(api_key=pinecone_api_key, environment=pinecone_env) # type: ignore if not index_name: raise ValueError("Index Name is required.") + documents = [] + for _input in inputs or []: + if isinstance(_input, Record): + documents.append(_input.to_lc_document()) + else: + documents.append(_input) if documents: return Pinecone.from_documents( documents=documents, diff --git a/src/backend/langflow/components/vectorstores/Qdrant.py b/src/backend/base/langflow/components/vectorstores/Qdrant.py similarity index 82% rename from src/backend/langflow/components/vectorstores/Qdrant.py rename to src/backend/base/langflow/components/vectorstores/Qdrant.py index 6d68cdd55..61f8e14af 100644 --- a/src/backend/langflow/components/vectorstores/Qdrant.py +++ b/src/backend/base/langflow/components/vectorstores/Qdrant.py @@ -3,27 +3,36 @@ from typing import Optional, Union from langchain.schema import BaseRetriever from langchain_community.vectorstores import VectorStore from langchain_community.vectorstores.qdrant import Qdrant -from langflow import CustomComponent -from langflow.field_typing import Document, Embeddings, NestedDict + +from langflow.field_typing import Embeddings, NestedDict +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema.schema import Record class QdrantComponent(CustomComponent): display_name = "Qdrant" description = "Construct Qdrant wrapper from a list of texts." + icon = "Qdrant" def build_config(self): return { - "documents": {"display_name": "Documents"}, + "inputs": {"display_name": "Input", "input_types": ["Document", "Record"]}, "embedding": {"display_name": "Embedding"}, "api_key": {"display_name": "API Key", "password": True, "advanced": True}, "collection_name": {"display_name": "Collection Name"}, - "content_payload_key": {"display_name": "Content Payload Key", "advanced": True}, + "content_payload_key": { + "display_name": "Content Payload Key", + "advanced": True, + }, "distance_func": {"display_name": "Distance Function", "advanced": True}, "grpc_port": {"display_name": "gRPC Port", "advanced": True}, "host": {"display_name": "Host", "advanced": True}, "https": {"display_name": "HTTPS", "advanced": True}, "location": {"display_name": "Location", "advanced": True}, - "metadata_payload_key": {"display_name": "Metadata Payload Key", "advanced": True}, + "metadata_payload_key": { + "display_name": "Metadata Payload Key", + "advanced": True, + }, "path": {"display_name": "Path", "advanced": True}, "port": {"display_name": "Port", "advanced": True}, "prefer_grpc": {"display_name": "Prefer gRPC", "advanced": True}, @@ -37,7 +46,7 @@ class QdrantComponent(CustomComponent): self, embedding: Embeddings, collection_name: str, - documents: Optional[Document] = None, + inputs: Optional[Record] = None, api_key: Optional[str] = None, content_payload_key: str = "page_content", distance_func: str = "Cosine", @@ -54,6 +63,12 @@ class QdrantComponent(CustomComponent): timeout: Optional[int] = None, url: Optional[str] = None, ) -> Union[VectorStore, Qdrant, BaseRetriever]: + documents = [] + for _input in inputs or []: + if isinstance(_input, Record): + documents.append(_input.to_lc_document()) + else: + documents.append(_input) if documents is None: from qdrant_client import QdrantClient diff --git a/src/backend/langflow/components/vectorstores/Redis.py b/src/backend/base/langflow/components/vectorstores/Redis.py similarity index 84% rename from src/backend/langflow/components/vectorstores/Redis.py rename to src/backend/base/langflow/components/vectorstores/Redis.py index b2d7e4542..ea1046037 100644 --- a/src/backend/langflow/components/vectorstores/Redis.py +++ b/src/backend/base/langflow/components/vectorstores/Redis.py @@ -3,9 +3,10 @@ from typing import Optional, Union from langchain.embeddings.base import Embeddings from langchain_community.vectorstores import VectorStore from langchain_community.vectorstores.redis import Redis -from langchain_core.documents import Document from langchain_core.retrievers import BaseRetriever -from langflow import CustomComponent + +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema.schema import Record class RedisComponent(CustomComponent): @@ -16,7 +17,6 @@ class RedisComponent(CustomComponent): display_name: str = "Redis" description: str = "Implementation of Vector Store using Redis" documentation = "https://python.langchain.com/docs/integrations/vectorstores/redis" - beta = True def build_config(self): """ @@ -28,7 +28,7 @@ class RedisComponent(CustomComponent): return { "index_name": {"display_name": "Index Name", "value": "your_index"}, "code": {"show": False, "display_name": "Code"}, - "documents": {"display_name": "Documents", "is_list": True}, + "inputs": {"display_name": "Input", "input_types": ["Document", "Record"]}, "embedding": {"display_name": "Embedding"}, "schema": {"display_name": "Schema", "file_types": [".yaml"]}, "redis_server_url": { @@ -44,7 +44,7 @@ class RedisComponent(CustomComponent): redis_server_url: str, redis_index_name: str, schema: Optional[str] = None, - documents: Optional[Document] = None, + inputs: Optional[Record] = None, ) -> Union[VectorStore, BaseRetriever]: """ Builds the Vector Store or BaseRetriever object. @@ -58,7 +58,13 @@ class RedisComponent(CustomComponent): Returns: - VectorStore: The Vector Store object. """ - if documents is None: + documents = [] + for _input in inputs or []: + if isinstance(_input, Record): + documents.append(_input.to_lc_document()) + else: + documents.append(_input) + if not documents: if schema is None: raise ValueError("If no documents are provided, a schema must be provided.") redis_vs = Redis.from_existing_index( diff --git a/src/backend/langflow/components/vectorstores/SupabaseVectorStore.py b/src/backend/base/langflow/components/vectorstores/SupabaseVectorStore.py similarity index 72% rename from src/backend/langflow/components/vectorstores/SupabaseVectorStore.py rename to src/backend/base/langflow/components/vectorstores/SupabaseVectorStore.py index 2ec6dfabc..876742117 100644 --- a/src/backend/langflow/components/vectorstores/SupabaseVectorStore.py +++ b/src/backend/base/langflow/components/vectorstores/SupabaseVectorStore.py @@ -1,12 +1,14 @@ -from typing import List, Union +from typing import List, Optional, Union from langchain.schema import BaseRetriever from langchain_community.vectorstores import VectorStore from langchain_community.vectorstores.supabase import SupabaseVectorStore -from langflow import CustomComponent -from langflow.field_typing import Document, Embeddings, NestedDict from supabase.client import Client, create_client +from langflow.field_typing import Embeddings, NestedDict +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema.schema import Record + class SupabaseComponent(CustomComponent): display_name = "Supabase" @@ -14,7 +16,7 @@ class SupabaseComponent(CustomComponent): def build_config(self): return { - "documents": {"display_name": "Documents"}, + "inputs": {"display_name": "Input", "input_types": ["Document", "Record"]}, "embedding": {"display_name": "Embedding"}, "query_name": {"display_name": "Query Name"}, "search_kwargs": {"display_name": "Search Kwargs", "advanced": True}, @@ -26,7 +28,7 @@ class SupabaseComponent(CustomComponent): def build( self, embedding: Embeddings, - documents: List[Document], + inputs: Optional[List[Record]] = None, query_name: str = "", search_kwargs: NestedDict = {}, supabase_service_key: str = "", @@ -34,6 +36,12 @@ class SupabaseComponent(CustomComponent): table_name: str = "", ) -> Union[VectorStore, SupabaseVectorStore, BaseRetriever]: supabase: Client = create_client(supabase_url, supabase_key=supabase_service_key) + documents = [] + for _input in inputs or []: + if isinstance(_input, Record): + documents.append(_input.to_lc_document()) + else: + documents.append(_input) return SupabaseVectorStore.from_documents( documents=documents, embedding=embedding, diff --git a/src/backend/langflow/components/vectorstores/Vectara.py b/src/backend/base/langflow/components/vectorstores/Vectara.py similarity index 78% rename from src/backend/langflow/components/vectorstores/Vectara.py rename to src/backend/base/langflow/components/vectorstores/Vectara.py index 31615fe7f..5c087875f 100644 --- a/src/backend/langflow/components/vectorstores/Vectara.py +++ b/src/backend/base/langflow/components/vectorstores/Vectara.py @@ -6,15 +6,17 @@ from typing import List, Optional, Union from langchain_community.embeddings import FakeEmbeddings from langchain_community.vectorstores.vectara import Vectara from langchain_core.vectorstores import VectorStore -from langflow import CustomComponent -from langflow.field_typing import BaseRetriever, Document + +from langflow.field_typing import BaseRetriever +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema.schema import Record class VectaraComponent(CustomComponent): display_name: str = "Vectara" description: str = "Implementation of Vector Store using Vectara" documentation = "https://python.langchain.com/docs/integrations/vectorstores/vectara" - beta = True + icon = "Vectara" field_config = { "vectara_customer_id": { "display_name": "Vectara Customer ID", @@ -26,7 +28,11 @@ class VectaraComponent(CustomComponent): "display_name": "Vectara API Key", "password": True, }, - "documents": {"display_name": "Documents", "info": "If provided, will be upserted to corpus (optional)"}, + "inputs": { + "display_name": "Input", + "input_types": ["Document", "Record"], + "info": "If provided, will be upserted to corpus (optional)", + }, "files_url": { "display_name": "Files Url", "info": "Make vectara object using url of files (optional)", @@ -39,11 +45,18 @@ class VectaraComponent(CustomComponent): vectara_corpus_id: str, vectara_api_key: str, files_url: Optional[List[str]] = None, - documents: Optional[Document] = None, + inputs: Optional[Record] = None, ) -> Union[VectorStore, BaseRetriever]: source = "Langflow" - if documents is not None: + documents = [] + for _input in inputs or []: + if isinstance(_input, Record): + documents.append(_input.to_lc_document()) + else: + documents.append(_input) + + if documents: return Vectara.from_documents( documents=documents, # type: ignore embedding=FakeEmbeddings(size=768), diff --git a/src/backend/langflow/components/vectorstores/Weaviate.py b/src/backend/base/langflow/components/vectorstores/Weaviate.py similarity index 73% rename from src/backend/langflow/components/vectorstores/Weaviate.py rename to src/backend/base/langflow/components/vectorstores/Weaviate.py index 9b4967c36..3362a3fca 100644 --- a/src/backend/langflow/components/vectorstores/Weaviate.py +++ b/src/backend/base/langflow/components/vectorstores/Weaviate.py @@ -2,17 +2,17 @@ from typing import Optional, Union import weaviate # type: ignore from langchain.embeddings.base import Embeddings -from langchain.schema import BaseRetriever, Document +from langchain.schema import BaseRetriever from langchain_community.vectorstores import VectorStore, Weaviate -from langflow import CustomComponent +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema.schema import Record -class WeaviateVectorStore(CustomComponent): +class WeaviateVectorStoreComponent(CustomComponent): display_name: str = "Weaviate" description: str = "Implementation of Vector Store using Weaviate" documentation = "https://python.langchain.com/docs/integrations/vectorstores/weaviate" - beta = True field_config = { "url": {"display_name": "Weaviate URL", "value": "http://localhost:8080"}, "api_key": { @@ -24,8 +24,13 @@ class WeaviateVectorStore(CustomComponent): "display_name": "Index name", "required": False, }, - "text_key": {"display_name": "Text Key", "required": False, "advanced": True, "value": "text"}, - "documents": {"display_name": "Documents", "is_list": True}, + "text_key": { + "display_name": "Text Key", + "required": False, + "advanced": True, + "value": "text", + }, + "inputs": {"display_name": "Input", "input_types": ["Document", "Record"]}, "embedding": {"display_name": "Embedding"}, "attributes": { "display_name": "Attributes", @@ -34,7 +39,11 @@ class WeaviateVectorStore(CustomComponent): "field_type": "str", "advanced": True, }, - "search_by_text": {"display_name": "Search By Text", "field_type": "bool", "advanced": True}, + "search_by_text": { + "display_name": "Search By Text", + "field_type": "bool", + "advanced": True, + }, "code": {"show": False}, } @@ -46,7 +55,7 @@ class WeaviateVectorStore(CustomComponent): index_name: Optional[str] = None, text_key: str = "text", embedding: Optional[Embeddings] = None, - documents: Optional[Document] = None, + inputs: Optional[Record] = None, attributes: Optional[list] = None, ) -> Union[VectorStore, BaseRetriever]: if api_key: @@ -69,8 +78,14 @@ class WeaviateVectorStore(CustomComponent): return pascal_case_word index_name = _to_pascal_case(index_name) if index_name else None + documents = [] + for _input in inputs or []: + if isinstance(_input, Record): + documents.append(_input.to_lc_document()) + else: + documents.append(_input) - if documents is not None and embedding is not None: + if documents and embedding is not None: return Weaviate.from_documents( client=client, index_name=index_name, diff --git a/src/backend/base/langflow/components/vectorstores/__init__.py b/src/backend/base/langflow/components/vectorstores/__init__.py new file mode 100644 index 000000000..48e1bf9c7 --- /dev/null +++ b/src/backend/base/langflow/components/vectorstores/__init__.py @@ -0,0 +1,26 @@ +from .AstraDB import AstraDBVectorStoreComponent +from .Chroma import ChromaComponent +from .FAISS import FAISSComponent +from .MongoDBAtlasVector import MongoDBAtlasComponent +from .Pinecone import PineconeComponent +from .Qdrant import QdrantComponent +from .Redis import RedisComponent +from .SupabaseVectorStore import SupabaseComponent +from .Vectara import VectaraComponent +from .Weaviate import WeaviateVectorStoreComponent +from .pgvector import PGVectorComponent + +__all__ = [ + "AstraDBVectorStoreComponent", + "ChromaComponent", + "FAISSComponent", + "MongoDBAtlasComponent", + "PineconeComponent", + "QdrantComponent", + "RedisComponent", + "SupabaseComponent", + "VectaraComponent", + "WeaviateVectorStoreComponent", + "base", + "PGVectorComponent", +] diff --git a/src/backend/base/langflow/components/vectorstores/base/__init__.py b/src/backend/base/langflow/components/vectorstores/base/__init__.py new file mode 100644 index 000000000..93e42c4aa --- /dev/null +++ b/src/backend/base/langflow/components/vectorstores/base/__init__.py @@ -0,0 +1,3 @@ +from .model import LCVectorStoreComponent + +__all__ = ["LCVectorStoreComponent"] diff --git a/src/backend/base/langflow/components/vectorstores/base/model.py b/src/backend/base/langflow/components/vectorstores/base/model.py new file mode 100644 index 000000000..668c5eff2 --- /dev/null +++ b/src/backend/base/langflow/components/vectorstores/base/model.py @@ -0,0 +1,47 @@ +from typing import List, Union + +from langchain_core.documents import Document +from langchain_core.retrievers import BaseRetriever +from langchain_core.vectorstores import VectorStore + +from langflow.field_typing import Text +from langflow.helpers.record import docs_to_records +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema import Record + + +class LCVectorStoreComponent(CustomComponent): + display_name: str = "LC Vector Store" + description: str = "Search a LC Vector Store for similar documents." + + def search_with_vector_store( + self, + input_value: Text, + search_type: str, + vector_store: Union[VectorStore, BaseRetriever], + k=10, + **kwargs, + ) -> List[Record]: + """ + Search for records in the vector store based on the input value and search type. + + Args: + input_value (Text): The input value to search for. + search_type (str): The type of search to perform. + vector_store (VectorStore): The vector store to search in. + + Returns: + List[Record]: A list of records matching the search criteria. + + Raises: + ValueError: If invalid inputs are provided. + """ + + docs: List[Document] = [] + if input_value and isinstance(input_value, str) and hasattr(vector_store, "search"): + docs = vector_store.search(query=input_value, search_type=search_type.lower(), k=k, **kwargs) + else: + raise ValueError("Invalid inputs provided.") + records = docs_to_records(docs) + self.status = records + return records diff --git a/src/backend/langflow/components/vectorstores/pgvector.py b/src/backend/base/langflow/components/vectorstores/pgvector.py similarity index 84% rename from src/backend/langflow/components/vectorstores/pgvector.py rename to src/backend/base/langflow/components/vectorstores/pgvector.py index 2baf6dae6..b061b22ac 100644 --- a/src/backend/langflow/components/vectorstores/pgvector.py +++ b/src/backend/base/langflow/components/vectorstores/pgvector.py @@ -3,9 +3,10 @@ from typing import Optional, Union from langchain.embeddings.base import Embeddings from langchain_community.vectorstores import VectorStore from langchain_community.vectorstores.pgvector import PGVector -from langchain_core.documents import Document from langchain_core.retrievers import BaseRetriever -from langflow import CustomComponent + +from langflow.interface.custom.custom_component import CustomComponent +from langflow.schema.schema import Record class PGVectorComponent(CustomComponent): @@ -26,7 +27,7 @@ class PGVectorComponent(CustomComponent): """ return { "code": {"show": False}, - "documents": {"display_name": "Documents", "is_list": True}, + "inputs": {"display_name": "Input", "input_types": ["Document", "Record"]}, "embedding": {"display_name": "Embedding"}, "pg_server_url": { "display_name": "PostgreSQL Server Connection String", @@ -40,7 +41,7 @@ class PGVectorComponent(CustomComponent): embedding: Embeddings, pg_server_url: str, collection_name: str, - documents: Optional[Document] = None, + inputs: Optional[Record] = None, ) -> Union[VectorStore, BaseRetriever]: """ Builds the Vector Store or BaseRetriever object. @@ -55,6 +56,12 @@ class PGVectorComponent(CustomComponent): - VectorStore: The Vector Store object. """ + documents = [] + for _input in inputs or []: + if isinstance(_input, Record): + documents.append(_input.to_lc_document()) + else: + documents.append(_input) try: if documents is None: vector_store = PGVector.from_existing_index( diff --git a/src/backend/langflow/config.yaml b/src/backend/base/langflow/config.yaml similarity index 74% rename from src/backend/langflow/config.yaml rename to src/backend/base/langflow/config.yaml index 5ec4f3aaa..102cb9016 100644 --- a/src/backend/langflow/config.yaml +++ b/src/backend/base/langflow/config.yaml @@ -11,31 +11,6 @@ agents: documentation: "" SQLAgent: documentation: "" -chains: - # LLMChain: - # documentation: "https://python.langchain.com/docs/modules/chains/foundational/llm_chain" - LLMMathChain: - documentation: "https://python.langchain.com/docs/modules/chains/additional/llm_math" - LLMCheckerChain: - documentation: "https://python.langchain.com/docs/modules/chains/additional/llm_checker" - # ConversationChain: - # documentation: "" - SeriesCharacterChain: - documentation: "" - MidJourneyPromptChain: - documentation: "" - TimeTravelGuideChain: - documentation: "" - SQLDatabaseChain: - documentation: "" - RetrievalQA: - documentation: "https://python.langchain.com/docs/modules/chains/popular/vector_db_qa" - RetrievalQAWithSourcesChain: - documentation: "" - ConversationalRetrievalChain: - documentation: "https://python.langchain.com/docs/modules/chains/popular/chat_vector_db" - CombineDocsChain: - documentation: "" documentloaders: AirbyteJSONLoader: documentation: "https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/airbyte_json" @@ -109,32 +84,6 @@ embeddings: OllamaEmbeddings: documentation: "https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/ollama" -llms: - OpenAI: - documentation: "https://python.langchain.com/docs/modules/model_io/models/llms/integrations/openai" - ChatOpenAI: - documentation: "https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai" - LlamaCpp: - documentation: "https://python.langchain.com/docs/modules/model_io/models/llms/integrations/llamacpp" - CTransformers: - documentation: "https://python.langchain.com/docs/modules/model_io/models/llms/integrations/ctransformers" - Cohere: - documentation: "https://python.langchain.com/docs/modules/model_io/models/llms/integrations/cohere" - Anthropic: - documentation: "" - ChatAnthropic: - documentation: "https://python.langchain.com/docs/modules/model_io/models/chat/integrations/anthropic" - HuggingFaceHub: - documentation: "https://python.langchain.com/docs/modules/model_io/models/llms/integrations/huggingface_hub" - VertexAI: - documentation: "https://python.langchain.com/docs/modules/model_io/models/llms/integrations/google_vertex_ai_palm" - ### - # There's a bug in this component deactivating until we get it sorted: _language_models.py", line 804, in send_message - # is_blocked=safety_attributes.get("blocked", False), - # AttributeError: 'list' object has no attribute 'get' - ChatVertexAI: - documentation: "https://python.langchain.com/docs/modules/model_io/models/chat/integrations/google_vertex_ai_palm" - ### memories: # https://github.com/supabase-community/supabase-py/issues/482 # ZepChatMessageHistory: @@ -269,24 +218,7 @@ retrievers: # https://github.com/supabase-community/supabase-py/issues/482 # ZepRetriever: # documentation: "https://python.langchain.com/docs/modules/data_connection/retrievers/integrations/zep_memorystore" -vectorstores: - # Chroma: - # documentation: "https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/chroma" - Qdrant: - documentation: "https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/qdrant" - FAISS: - documentation: "https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/faiss" - Pinecone: - documentation: "https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/pinecone" - ElasticsearchStore: - documentation: "https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/elasticsearch" - SupabaseVectorStore: - documentation: "https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/supabase" - MongoDBAtlasVectorSearch: - documentation: "https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/mongodb_atlas" - # Requires docarray >=0.32.0 but langchain-serve requires jina 3.15.2 which doesn't support docarray >=0.32.0 - # DocArrayInMemorySearch: - # documentation: "https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/docarray_in_memory" + wrappers: RequestsWrapper: documentation: "" diff --git a/src/backend/langflow/interface/wrappers/__init__.py b/src/backend/base/langflow/core/__init__.py similarity index 100% rename from src/backend/langflow/interface/wrappers/__init__.py rename to src/backend/base/langflow/core/__init__.py diff --git a/src/backend/langflow/core/celery_app.py b/src/backend/base/langflow/core/celery_app.py similarity index 100% rename from src/backend/langflow/core/celery_app.py rename to src/backend/base/langflow/core/celery_app.py diff --git a/src/backend/langflow/core/celeryconfig.py b/src/backend/base/langflow/core/celeryconfig.py similarity index 100% rename from src/backend/langflow/core/celeryconfig.py rename to src/backend/base/langflow/core/celeryconfig.py diff --git a/src/backend/langflow/components/__init__.py b/src/backend/base/langflow/custom.py similarity index 62% rename from src/backend/langflow/components/__init__.py rename to src/backend/base/langflow/custom.py index 765042210..ebe4c04e8 100644 --- a/src/backend/langflow/components/__init__.py +++ b/src/backend/base/langflow/custom.py @@ -1,4 +1 @@ -from langflow.interface.custom.custom_component import CustomComponent - - -__all__ = ["CustomComponent"] +from langflow.interface.custom.custom_component import CustomComponent # noqa: F401 diff --git a/src/backend/langflow/field_typing/__init__.py b/src/backend/base/langflow/field_typing/__init__.py similarity index 97% rename from src/backend/langflow/field_typing/__init__.py rename to src/backend/base/langflow/field_typing/__init__.py index 46ea20111..15ce03693 100644 --- a/src/backend/langflow/field_typing/__init__.py +++ b/src/backend/base/langflow/field_typing/__init__.py @@ -13,6 +13,7 @@ from .constants import ( Callable, Chain, ChatPromptTemplate, + Code, Data, Document, Embeddings, @@ -20,6 +21,7 @@ from .constants import ( Object, Prompt, PromptTemplate, + Text, TextSplitter, Tool, VectorStore, @@ -64,6 +66,7 @@ __all__ = [ "TextSplitter", "Document", "AgentExecutor", + "Text", "Object", "Callable", "BasePromptTemplate", @@ -71,4 +74,5 @@ __all__ = [ "Prompt", "RangeSpec", "TemplateField", + "Code", ] diff --git a/src/backend/langflow/field_typing/constants.py b/src/backend/base/langflow/field_typing/constants.py similarity index 95% rename from src/backend/langflow/field_typing/constants.py rename to src/backend/base/langflow/field_typing/constants.py index 6680aceab..2e8fd4b3b 100644 --- a/src/backend/langflow/field_typing/constants.py +++ b/src/backend/base/langflow/field_typing/constants.py @@ -1,4 +1,4 @@ -from typing import Callable, Dict, Union +from typing import Callable, Dict, Text, Union from langchain.agents.agent import AgentExecutor from langchain.chains.base import Chain @@ -30,6 +30,10 @@ class Prompt: pass +class Code: + pass + + LANGCHAIN_BASE_TYPES = { "Chain": Chain, "AgentExecutor": AgentExecutor, @@ -54,6 +58,7 @@ CUSTOM_COMPONENT_SUPPORTED_TYPES = { **LANGCHAIN_BASE_TYPES, "NestedDict": NestedDict, "Data": Data, + "Text": Text, "Object": Object, "Callable": Callable, "Prompt": Prompt, diff --git a/src/backend/base/langflow/field_typing/range_spec.py b/src/backend/base/langflow/field_typing/range_spec.py new file mode 100644 index 000000000..78ed2e435 --- /dev/null +++ b/src/backend/base/langflow/field_typing/range_spec.py @@ -0,0 +1,30 @@ +from typing import Literal + +from pydantic import BaseModel, field_validator + + +class RangeSpec(BaseModel): + step_type: Literal["int", "float"] = "float" + min: float = -1.0 + max: float = 1.0 + step: float = 0.1 + + @field_validator("max") + @classmethod + def max_must_be_greater_than_min(cls, v, values, **kwargs): + if "min" in values.data and v <= values.data["min"]: + raise ValueError("Max must be greater than min") + return v + + @field_validator("step") + @classmethod + def step_must_be_positive(cls, v, values, **kwargs): + if v <= 0: + raise ValueError("Step must be positive") + if values.data["step_type"] == "int" and isinstance(v, float) and not v.is_integer(): + raise ValueError("When step_type is int, step must be an integer") + return v + + @classmethod + def set_step_type(cls, step_type: Literal["int", "float"], range_spec: "RangeSpec") -> "RangeSpec": + return cls(min=range_spec.min, max=range_spec.max, step=range_spec.step, step_type=step_type) diff --git a/src/backend/langflow/graph/__init__.py b/src/backend/base/langflow/graph/__init__.py similarity index 93% rename from src/backend/langflow/graph/__init__.py rename to src/backend/base/langflow/graph/__init__.py index e63b9dcc0..e80dcaa5f 100644 --- a/src/backend/langflow/graph/__init__.py +++ b/src/backend/base/langflow/graph/__init__.py @@ -4,17 +4,18 @@ from langflow.graph.vertex.base import Vertex from langflow.graph.vertex.types import ( AgentVertex, ChainVertex, + CustomComponentVertex, DocumentLoaderVertex, EmbeddingVertex, LLMVertex, MemoryVertex, PromptVertex, + RetrieverVertex, TextSplitterVertex, - ToolVertex, ToolkitVertex, + ToolVertex, VectorStoreVertex, WrapperVertex, - RetrieverVertex, ) __all__ = [ @@ -34,4 +35,5 @@ __all__ = [ "VectorStoreVertex", "WrapperVertex", "RetrieverVertex", + "CustomComponentVertex", ] diff --git a/src/backend/langflow/processing/__init__.py b/src/backend/base/langflow/graph/edge/__init__.py similarity index 100% rename from src/backend/langflow/processing/__init__.py rename to src/backend/base/langflow/graph/edge/__init__.py diff --git a/src/backend/langflow/graph/edge/base.py b/src/backend/base/langflow/graph/edge/base.py similarity index 54% rename from src/backend/langflow/graph/edge/base.py rename to src/backend/base/langflow/graph/edge/base.py index 399638e18..ba7fe05e8 100644 --- a/src/backend/langflow/graph/edge/base.py +++ b/src/backend/base/langflow/graph/edge/base.py @@ -1,8 +1,13 @@ -from typing import TYPE_CHECKING, List, Optional +from typing import TYPE_CHECKING, Any, List, Optional from loguru import logger from pydantic import BaseModel, Field +from langflow.graph.edge.utils import build_clean_params +from langflow.schema.schema import INPUT_FIELD_NAME +from langflow.services.deps import get_monitor_service +from langflow.services.monitor.utils import log_message + if TYPE_CHECKING: from langflow.graph.vertex.base import Vertex @@ -93,5 +98,85 @@ class Edge: def __hash__(self) -> int: return hash(self.__repr__()) - def __eq__(self, __value: object) -> bool: - return self.__repr__() == __value.__repr__() if isinstance(__value, Edge) else False + def __eq__(self, __o: object) -> bool: + if not isinstance(__o, Edge): + return False + return ( + self._source_handle == __o._source_handle + and self._target_handle == __o._target_handle + and self.target_param == __o.target_param + ) + + +class ContractEdge(Edge): + def __init__(self, source: "Vertex", target: "Vertex", raw_edge: dict): + super().__init__(source, target, raw_edge) + self.is_fulfilled = False # Whether the contract has been fulfilled. + self.result: Any = None + + async def honor(self, source: "Vertex", target: "Vertex") -> None: + """ + Fulfills the contract by setting the result of the source vertex to the target vertex's parameter. + If the edge is runnable, the source vertex is run with the message text and the target vertex's + root_field param is set to the + result. If the edge is not runnable, the target vertex's parameter is set to the result. + :param message: The message object to be processed if the edge is runnable. + """ + if self.is_fulfilled: + return + + if not source._built: + # The system should be read-only, so we should not be building vertices + # that are not already built. + raise ValueError(f"Source vertex {source.id} is not built.") + + if self.matched_type == "Text": + self.result = source._built_result + else: + self.result = source._built_object + + target.params[self.target_param] = self.result + self.is_fulfilled = True + + async def get_result_from_source(self, source: "Vertex", target: "Vertex"): + # Fulfill the contract if it has not been fulfilled. + if not self.is_fulfilled: + await self.honor(source, target) + + log_transaction(self, source, target, "success") + # If the target vertex is a power component we log messages + if target.vertex_type == "ChatOutput" and ( + isinstance(target.params.get(INPUT_FIELD_NAME), str) + or isinstance(target.params.get(INPUT_FIELD_NAME), dict) + ): + if target.params.get("message") == "": + return self.result + await log_message( + sender=target.params.get("sender", ""), + sender_name=target.params.get("sender_name", ""), + message=target.params.get(INPUT_FIELD_NAME, {}), + session_id=target.params.get("session_id", ""), + artifacts=target.artifacts, + ) + return self.result + + def __repr__(self) -> str: + return f"{self.source_id} -[{self.target_param}]-> {self.target_id}" + + +def log_transaction(edge: ContractEdge, source: "Vertex", target: "Vertex", status, error=None): + try: + monitor_service = get_monitor_service() + clean_params = build_clean_params(target) + data = { + "source": source.vertex_type, + "target": target.vertex_type, + "target_args": clean_params, + "timestamp": monitor_service.get_timestamp(), + "status": status, + "error": error, + } + monitor_service.add_row(table_name="transactions", data=data) + except Exception as e: + logger.error(f"Error logging transaction: {e}") + logger.error(f"Error logging transaction: {e}") diff --git a/src/backend/base/langflow/graph/edge/schema.py b/src/backend/base/langflow/graph/edge/schema.py new file mode 100644 index 000000000..ea691beae --- /dev/null +++ b/src/backend/base/langflow/graph/edge/schema.py @@ -0,0 +1,34 @@ +from typing import Any, List +from pydantic import BaseModel + + +class ResultPair(BaseModel): + result: Any + extra: Any + + +class Payload(BaseModel): + result_pairs: List[ResultPair] = [] + + def __iter__(self): + return iter(self.result_pairs) + + def add_result_pair(self, result: Any, extra: Any = None) -> None: + self.result_pairs.append(ResultPair(result=result, extra=extra)) + + def get_last_result_pair(self) -> ResultPair: + return self.result_pairs[-1] + + # format all but the last result pair + # into a string + def format(self, sep: str = "\n") -> str: + # Result: the result + # Extra: the extra if it exists don't show if it doesn't + return sep.join( + [ + f"Result: {result_pair.result}\nExtra: {result_pair.extra}" + if result_pair.extra is not None + else f"Result: {result_pair.result}" + for result_pair in self.result_pairs[:-1] + ] + ) diff --git a/src/backend/base/langflow/graph/edge/utils.py b/src/backend/base/langflow/graph/edge/utils.py new file mode 100644 index 000000000..0f69e4b2d --- /dev/null +++ b/src/backend/base/langflow/graph/edge/utils.py @@ -0,0 +1,19 @@ +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from langflow.graph.vertex.base import Vertex + + +def build_clean_params(target: "Vertex") -> dict: + """ + Cleans the parameters of the target vertex. + """ + # Removes all keys that the values aren't python types like str, int, bool, etc. + params = { + key: value for key, value in target.params.items() if isinstance(value, (str, int, bool, float, list, dict)) + } + # if it is a list we need to check if the contents are python types + for key, value in params.items(): + if isinstance(value, list): + params[key] = [item for item in value if isinstance(item, (str, int, bool, float, list, dict))] + return params diff --git a/src/backend/langflow/services/auth/__init__.py b/src/backend/base/langflow/graph/graph/__init__.py similarity index 100% rename from src/backend/langflow/services/auth/__init__.py rename to src/backend/base/langflow/graph/graph/__init__.py diff --git a/src/backend/base/langflow/graph/graph/base.py b/src/backend/base/langflow/graph/graph/base.py new file mode 100644 index 000000000..8261d0b8c --- /dev/null +++ b/src/backend/base/langflow/graph/graph/base.py @@ -0,0 +1,1220 @@ +import asyncio +from collections import defaultdict, deque +from itertools import chain +from typing import TYPE_CHECKING, Callable, Coroutine, Dict, Generator, List, Optional, Type, Union + +from loguru import logger + +from langflow.graph.edge.base import ContractEdge +from langflow.graph.graph.constants import lazy_load_vertex_dict +from langflow.graph.graph.runnable_vertices_manager import RunnableVerticesManager +from langflow.graph.graph.state_manager import GraphStateManager +from langflow.graph.graph.utils import process_flow +from langflow.graph.schema import InterfaceComponentTypes, RunOutputs +from langflow.graph.vertex.base import Vertex +from langflow.graph.vertex.types import ChatVertex, FileToolVertex, LLMVertex, RoutingVertex, StateVertex, ToolkitVertex +from langflow.interface.tools.constants import FILE_TOOLS +from langflow.schema import Record +from langflow.schema.schema import INPUT_FIELD_NAME, InputType + +if TYPE_CHECKING: + from langflow.graph.schema import ResultData + + +class Graph: + """A class representing a graph of vertices and edges.""" + + def __init__( + self, + nodes: List[Dict], + edges: List[Dict[str, str]], + flow_id: Optional[str] = None, + ) -> None: + """ + Initializes a new instance of the Graph class. + + Args: + nodes (List[Dict]): A list of dictionaries representing the vertices of the graph. + edges (List[Dict[str, str]]): A list of dictionaries representing the edges of the graph. + flow_id (Optional[str], optional): The ID of the flow. Defaults to None. + """ + self._vertices = nodes + self._edges = edges + self.raw_graph_data = {"nodes": nodes, "edges": edges} + self._runs = 0 + self._updates = 0 + self.flow_id = flow_id + self._is_input_vertices: List[str] = [] + self._is_output_vertices: List[str] = [] + self._is_state_vertices: List[str] = [] + self._has_session_id_vertices: List[str] = [] + self._sorted_vertices_layers: List[List[str]] = [] + self._run_id = "" + + self.top_level_vertices = [] + for vertex in self._vertices: + if vertex_id := vertex.get("id"): + self.top_level_vertices.append(vertex_id) + self._graph_data = process_flow(self.raw_graph_data) + + self._vertices = self._graph_data["nodes"] + self._edges = self._graph_data["edges"] + self.inactivated_vertices: set = set() + self.activated_vertices: List[str] = [] + self.vertices_layers: List[List[str]] = [] + self.vertices_to_run: set[str] = set() + self.stop_vertex: Optional[str] = None + + self.inactive_vertices: set = set() + self.edges: List[ContractEdge] = [] + self.vertices: List[Vertex] = [] + self.run_manager = RunnableVerticesManager() + self._build_graph() + self.build_graph_maps() + self.define_vertices_lists() + self.state_manager = GraphStateManager() + + def get_state(self, name: str) -> Optional[Record]: + """ + Returns the state of the graph with the given name. + + Args: + name (str): The name of the state. + + Returns: + Optional[Record]: The state record, or None if the state does not exist. + """ + return self.state_manager.get_state(name, run_id=self._run_id) + + def update_state(self, name: str, record: Union[str, Record], caller: Optional[str] = None) -> None: + """ + Updates the state of the graph with the given name. + + Args: + name (str): The name of the state. + record (Union[str, Record]): The new state record. + caller (Optional[str], optional): The ID of the vertex that is updating the state. Defaults to None. + """ + if caller: + # If there is a caller which is a vertex_id, I want to activate + # all StateVertex in self.vertices that are not the caller + # essentially notifying all the other vertices that the state has changed + # This also has to activate their successors + self.activate_state_vertices(name, caller) + + self.state_manager.update_state(name, record, run_id=self._run_id) + + def activate_state_vertices(self, name: str, caller: str): + """ + Activates the state vertices in the graph with the given name and caller. + + Args: + name (str): The name of the state. + caller (str): The ID of the vertex that is updating the state. + """ + vertices_ids = [] + for vertex_id in self._is_state_vertices: + if vertex_id == caller: + continue + vertex = self.get_vertex(vertex_id) + if ( + isinstance(vertex._raw_params["name"], str) + and name in vertex._raw_params["name"] + and vertex_id != caller + and isinstance(vertex, StateVertex) + ): + vertices_ids.append(vertex_id) + successors = self.get_all_successors(vertex, flat=True) + self.vertices_to_run.update(list(map(lambda x: x.id, successors))) + self.activated_vertices = vertices_ids + self.vertices_to_run.update(vertices_ids) + + def reset_activated_vertices(self): + """ + Resets the activated vertices in the graph. + """ + self.activated_vertices = [] + + def append_state(self, name: str, record: Union[str, Record], caller: Optional[str] = None) -> None: + """ + Appends the state of the graph with the given name. + + Args: + name (str): The name of the state. + record (Union[str, Record]): The state record to append. + caller (Optional[str], optional): The ID of the vertex that is updating the state. Defaults to None. + """ + if caller: + self.activate_state_vertices(name, caller) + + self.state_manager.append_state(name, record, run_id=self._run_id) + + @property + def run_id(self): + """ + The ID of the current run. + + Returns: + str: The run ID. + + Raises: + ValueError: If the run ID is not set. + """ + if not self._run_id: + raise ValueError("Run ID not set") + return self._run_id + + def set_run_id(self, run_id: str): + """ + Sets the ID of the current run. + + Args: + run_id (str): The run ID. + """ + for vertex in self.vertices: + self.state_manager.subscribe(run_id, vertex.update_graph_state) + self._run_id = run_id + + @property + def sorted_vertices_layers(self) -> List[List[str]]: + """ + The sorted layers of vertices in the graph. + + Returns: + List[List[str]]: The sorted layers of vertices. + """ + if not self._sorted_vertices_layers: + self.sort_vertices() + return self._sorted_vertices_layers + + def define_vertices_lists(self): + """ + Defines the lists of vertices that are inputs, outputs, and have session_id. + """ + attributes = ["is_input", "is_output", "has_session_id", "is_state"] + for vertex in self.vertices: + for attribute in attributes: + if getattr(vertex, attribute): + getattr(self, f"_{attribute}_vertices").append(vertex.id) + + async def _run( + self, + inputs: Dict[str, str], + input_components: list[str], + input_type: InputType | None, + outputs: list[str], + stream: bool, + session_id: str, + ) -> List[Optional["ResultData"]]: + """ + Runs the graph with the given inputs. + + Args: + inputs (Dict[str, str]): The input values for the graph. + input_components (list[str]): The components to run for the inputs. + outputs (list[str]): The outputs to retrieve from the graph. + stream (bool): Whether to stream the results or not. + session_id (str): The session ID for the graph. + + Returns: + List[Optional["ResultData"]]: The outputs of the graph. + """ + if input_components and not isinstance(input_components, list): + raise ValueError(f"Invalid components value: {input_components}. Expected list") + elif input_components is None: + input_components = [] + + if not isinstance(inputs.get(INPUT_FIELD_NAME, ""), str): + raise ValueError(f"Invalid input value: {inputs.get(INPUT_FIELD_NAME)}. Expected string") + if inputs: + for vertex_id in self._is_input_vertices: + vertex = self.get_vertex(vertex_id) + # If the vertex is not in the input_components list + if input_components and ( + vertex_id not in input_components or vertex.display_name not in input_components + ): + continue + # If the input_type is not any and the input_type is not in the vertex id + # Example: input_type = "chat" and vertex.id = "OpenAI-19ddn" + elif input_type is not None and input_type != "any" and input_type not in vertex.id.lower(): + continue + if vertex is None: + raise ValueError(f"Vertex {vertex_id} not found") + vertex.update_raw_params(inputs, overwrite=True) + # Update all the vertices with the session_id + for vertex_id in self._has_session_id_vertices: + vertex = self.get_vertex(vertex_id) + if vertex is None: + raise ValueError(f"Vertex {vertex_id} not found") + vertex.update_raw_params({"session_id": session_id}) + # Process the graph + try: + await self.process() + self.increment_run_count() + except Exception as exc: + logger.exception(exc) + raise ValueError(f"Error running graph: {exc}") from exc + # Get the outputs + vertex_outputs = [] + for vertex in self.vertices: + if vertex is None: + raise ValueError(f"Vertex {vertex_id} not found") + + if not vertex.result and not stream and hasattr(vertex, "consume_async_generator"): + await vertex.consume_async_generator() + if (not outputs and vertex.is_output) or (vertex.display_name in outputs or vertex.id in outputs): + vertex_outputs.append(vertex.result) + + return vertex_outputs + + def run( + self, + inputs: list[Dict[str, str]], + input_components: Optional[list[list[str]]] = None, + types: Optional[list[InputType | None]] = None, + outputs: Optional[list[str]] = None, + session_id: Optional[str] = None, + stream: bool = False, + ) -> List[RunOutputs]: + """ + Run the graph with the given inputs and return the outputs. + + Args: + inputs (Dict[str, str]): A dictionary of input values. + input_components (Optional[list[str]]): A list of input components. + types (Optional[list[str]]): A list of types. + outputs (Optional[list[str]]): A list of output components. + session_id (Optional[str]): The session ID. + stream (bool): Whether to stream the outputs. + + Returns: + List[RunOutputs]: A list of RunOutputs objects representing the outputs. + """ + # run the async function in a sync way + # this could be used in a FastAPI endpoint + # so we should take care of the event loop + loop = asyncio.get_event_loop() + return loop.run_until_complete( + self.arun( + inputs=inputs, + inputs_components=input_components, + types=types, + outputs=outputs, + session_id=session_id, + stream=stream, + ) + ) + + async def arun( + self, + inputs: list[Dict[str, str]], + inputs_components: Optional[list[list[str]]] = None, + types: Optional[list[InputType | None]] = None, + outputs: Optional[list[str]] = None, + session_id: Optional[str] = None, + stream: bool = False, + ) -> List[RunOutputs]: + """ + Runs the graph with the given inputs. + + Args: + inputs (list[Dict[str, str]]): The input values for the graph. + inputs_components (Optional[list[list[str]]], optional): The components to run for the inputs. Defaults to None. + outputs (Optional[list[str]], optional): The outputs to retrieve from the graph. Defaults to None. + session_id (Optional[str], optional): The session ID for the graph. Defaults to None. + stream (bool, optional): Whether to stream the results or not. Defaults to False. + + Returns: + List[RunOutputs]: The outputs of the graph. + """ + # inputs is {"message": "Hello, world!"} + # we need to go through self.inputs and update the self._raw_params + # of the vertices that are inputs + # if the value is a list, we need to run multiple times + vertex_outputs = [] + if not isinstance(inputs, list): + inputs = [inputs] + elif not inputs: + inputs = [{}] + # Length of all should be the as inputs length + # just add empty lists to complete the length + if inputs_components is None: + inputs_components = [] + for _ in range(len(inputs) - len(inputs_components)): + inputs_components.append([]) + if types is None: + types = [] + for _ in range(len(inputs) - len(types)): + types.append("any") + for run_inputs, components, input_type in zip(inputs, inputs_components, types): + run_outputs = await self._run( + inputs=run_inputs, + input_components=components, + input_type=input_type, + outputs=outputs or [], + stream=stream, + session_id=session_id or "", + ) + run_output_object = RunOutputs(inputs=run_inputs, outputs=run_outputs) + logger.debug(f"Run outputs: {run_output_object}") + vertex_outputs.append(run_output_object) + return vertex_outputs + + def next_vertex_to_build(self): + """ + Returns the next vertex to be built. + + Yields: + str: The ID of the next vertex to be built. + """ + yield from chain.from_iterable(self.vertices_layers) + + @property + def metadata(self): + """ + The metadata of the graph. + + Returns: + dict: The metadata of the graph. + """ + return { + "runs": self._runs, + "updates": self._updates, + "inactivated_vertices": self.inactivated_vertices, + } + + def build_graph_maps(self): + """ + Builds the adjacency maps for the graph. + """ + self.predecessor_map, self.successor_map = self.build_adjacency_maps() + + self.in_degree_map = self.build_in_degree() + self.parent_child_map = self.build_parent_child_map() + + def reset_inactivated_vertices(self): + """ + Resets the inactivated vertices in the graph. + """ + self.inactivated_vertices = [] + self.inactivated_vertices = set() + + def mark_all_vertices(self, state: str): + """Marks all vertices in the graph.""" + for vertex in self.vertices: + vertex.set_state(state) + + def mark_vertex(self, vertex_id: str, state: str): + """Marks a vertex in the graph.""" + vertex = self.get_vertex(vertex_id) + vertex.set_state(state) + + def mark_branch(self, vertex_id: str, state: str): + """Marks a branch of the graph.""" + self.mark_vertex(vertex_id, state) + for child_id in self.parent_child_map[vertex_id]: + self.mark_branch(child_id, state) + + def build_parent_child_map(self): + parent_child_map = defaultdict(list) + for vertex in self.vertices: + parent_child_map[vertex.id] = [child.id for child in self.get_successors(vertex)] + return parent_child_map + + def increment_run_count(self): + self._runs += 1 + + def increment_update_count(self): + self._updates += 1 + + def __getstate__(self): + return self.raw_graph_data + + def __setstate__(self, state): + self.__init__(**state) + + @classmethod + def from_payload(cls, payload: Dict, flow_id: Optional[str] = None) -> "Graph": + """ + Creates a graph from a payload. + + Args: + payload (Dict): The payload to create the graph from.˜` + + Returns: + Graph: The created graph. + """ + if "data" in payload: + payload = payload["data"] + try: + vertices = payload["nodes"] + edges = payload["edges"] + return cls(vertices, edges, flow_id) + except KeyError as exc: + logger.exception(exc) + if "nodes" not in payload and "edges" not in payload: + logger.exception(exc) + raise ValueError( + f"Invalid payload. Expected keys 'nodes' and 'edges'. Found {list(payload.keys())}" + ) from exc + raise ValueError(f"Error while creating graph from payload: {exc}") from exc + + def __eq__(self, other: object) -> bool: + if not isinstance(other, Graph): + return False + return self.__repr__() == other.__repr__() + + # update this graph with another graph by comparing the __repr__ of each vertex + # and if the __repr__ of a vertex is not the same as the other + # then update the .data of the vertex to the self + # both graphs have the same vertices and edges + # but the data of the vertices might be different + + def update_edges_from_vertex(self, vertex: Vertex, other_vertex: Vertex) -> None: + """Updates the edges of a vertex in the Graph.""" + new_edges = [] + for edge in self.edges: + if edge.source_id == other_vertex.id or edge.target_id == other_vertex.id: + continue + new_edges.append(edge) + new_edges += other_vertex.edges + self.edges = new_edges + + def vertex_data_is_identical(self, vertex: Vertex, other_vertex: Vertex) -> bool: + data_is_equivalent = vertex == other_vertex + if not data_is_equivalent: + return False + return self.vertex_edges_are_identical(vertex, other_vertex) + + def vertex_edges_are_identical(self, vertex: Vertex, other_vertex: Vertex) -> bool: + same_length = len(vertex.edges) == len(other_vertex.edges) + if not same_length: + return False + for edge in vertex.edges: + if edge not in other_vertex.edges: + return False + return True + + def update(self, other: "Graph") -> "Graph": + # Existing vertices in self graph + existing_vertex_ids = set(vertex.id for vertex in self.vertices) + # Vertex IDs in the other graph + other_vertex_ids = set(other.vertex_map.keys()) + + # Find vertices that are in other but not in self (new vertices) + new_vertex_ids = other_vertex_ids - existing_vertex_ids + + # Find vertices that are in self but not in other (removed vertices) + removed_vertex_ids = existing_vertex_ids - other_vertex_ids + + # Remove vertices that are not in the other graph + for vertex_id in removed_vertex_ids: + try: + self.remove_vertex(vertex_id) + except ValueError: + pass + + # The order here matters because adding the vertex is required + # if any of them have edges that point to any of the new vertices + # By adding them first, them adding the edges we ensure that the + # edges have valid vertices to point to + + # Add new vertices + for vertex_id in new_vertex_ids: + new_vertex = other.get_vertex(vertex_id) + self._add_vertex(new_vertex) + + # Now update the edges + for vertex_id in new_vertex_ids: + new_vertex = other.get_vertex(vertex_id) + self._update_edges(new_vertex) + # Graph is set at the end because the edges come from the graph + # and the other graph is where the new edges and vertices come from + new_vertex.graph = self + + # Update existing vertices that have changed + for vertex_id in existing_vertex_ids.intersection(other_vertex_ids): + self_vertex = self.get_vertex(vertex_id) + other_vertex = other.get_vertex(vertex_id) + # If the vertices are not identical, update the vertex + if not self.vertex_data_is_identical(self_vertex, other_vertex): + self.update_vertex_from_another(self_vertex, other_vertex) + + self.build_graph_maps() + self.increment_update_count() + return self + + def update_vertex_from_another(self, vertex: Vertex, other_vertex: Vertex) -> None: + """ + Updates a vertex from another vertex. + + Args: + vertex (Vertex): The vertex to be updated. + other_vertex (Vertex): The vertex to update from. + """ + vertex._data = other_vertex._data + vertex._parse_data() + # Now we update the edges of the vertex + self.update_edges_from_vertex(vertex, other_vertex) + vertex.params = {} + vertex._build_params() + vertex.graph = self + # If the vertex is frozen, we don't want + # to reset the results nor the _built attribute + if not vertex.frozen: + vertex._built = False + vertex.result = None + vertex.artifacts = {} + vertex.set_top_level(self.top_level_vertices) + self.reset_all_edges_of_vertex(vertex) + + def reset_all_edges_of_vertex(self, vertex: Vertex) -> None: + """Resets all the edges of a vertex.""" + for edge in vertex.edges: + for vid in [edge.source_id, edge.target_id]: + if vid in self.vertex_map: + _vertex = self.vertex_map[vid] + if not _vertex.frozen: + _vertex._build_params() + + def _add_vertex(self, vertex: Vertex) -> None: + """Adds a vertex to the graph.""" + self.vertices.append(vertex) + self.vertex_map[vertex.id] = vertex + + def add_vertex(self, vertex: Vertex) -> None: + """Adds a new vertex to the graph.""" + self._add_vertex(vertex) + self._update_edges(vertex) + + def _update_edges(self, vertex: Vertex) -> None: + """Updates the edges of a vertex.""" + # Vertex has edges, so we need to update the edges + for edge in vertex.edges: + if edge not in self.edges and edge.source_id in self.vertex_map and edge.target_id in self.vertex_map: + self.edges.append(edge) + + def _build_graph(self) -> None: + """Builds the graph from the vertices and edges.""" + self.vertices = self._build_vertices() + self.vertex_map = {vertex.id: vertex for vertex in self.vertices} + self.edges = self._build_edges() + + # This is a hack to make sure that the LLM vertex is sent to + # the toolkit vertex + self._build_vertex_params() + + # Now that we have the vertices and edges + # We need to map the vertices that are connected to + # to ChatVertex instances + + def remove_vertex(self, vertex_id: str) -> None: + """Removes a vertex from the graph.""" + vertex = self.get_vertex(vertex_id) + if vertex is None: + return + self.vertices.remove(vertex) + self.vertex_map.pop(vertex_id) + self.edges = [edge for edge in self.edges if edge.source_id != vertex_id and edge.target_id != vertex_id] + + def _build_vertex_params(self) -> None: + """Identifies and handles the LLM vertex within the graph.""" + llm_vertex = None + for vertex in self.vertices: + vertex._build_params() + if isinstance(vertex, LLMVertex): + llm_vertex = vertex + + if llm_vertex: + for vertex in self.vertices: + if isinstance(vertex, ToolkitVertex): + vertex.params["llm"] = llm_vertex + + def _validate_vertex(self, vertex: Vertex) -> bool: + """Validates a vertex.""" + # All vertices that do not have edges are invalid + return len(self.get_vertex_edges(vertex.id)) > 0 + + def get_vertex(self, vertex_id: str) -> Vertex: + """Returns a vertex by id.""" + try: + return self.vertex_map[vertex_id] + except KeyError: + raise ValueError(f"Vertex {vertex_id} not found") + + async def build_vertex( + self, + lock: asyncio.Lock, + set_cache_coro: Callable[["Graph", asyncio.Lock], Coroutine], + vertex_id: str, + inputs_dict: Optional[Dict[str, str]] = None, + user_id: Optional[str] = None, + ): + """ + Builds a vertex in the graph. + + Args: + lock (asyncio.Lock): A lock to synchronize access to the graph. + set_cache_coro (Coroutine): A coroutine to set the cache. + vertex_id (str): The ID of the vertex to build. + inputs (Optional[Dict[str, str]]): Optional dictionary of inputs for the vertex. Defaults to None. + user_id (Optional[str]): Optional user ID. Defaults to None. + + Returns: + Tuple: A tuple containing the next runnable vertices, top level vertices, result dictionary, + parameters, validity flag, artifacts, and the built vertex. + + Raises: + ValueError: If no result is found for the vertex. + """ + vertex = self.get_vertex(vertex_id) + try: + if not vertex.frozen or not vertex._built: + await vertex.build(user_id=user_id, inputs=inputs_dict) + + if vertex.result is not None: + params = vertex._built_object_repr() + valid = True + result_dict = vertex.result + artifacts = vertex.artifacts + else: + raise ValueError(f"No result found for vertex {vertex_id}") + + next_runnable_vertices, top_level_vertices = await self.get_next_and_top_level_vertices( + lock, set_cache_coro, vertex + ) + return next_runnable_vertices, top_level_vertices, result_dict, params, valid, artifacts, vertex + except Exception as exc: + logger.exception(f"Error building vertex: {exc}") + raise exc + + async def get_next_and_top_level_vertices( + self, lock: asyncio.Lock, set_cache_coro: Callable[["Graph", asyncio.Lock], Coroutine], vertex: Vertex + ): + """ + Retrieves the next runnable vertices and the top level vertices for a given vertex. + + Args: + lock (asyncio.Lock): The lock used to synchronize access to the graph. + set_cache_coro (Coroutine): The coroutine used to set the cache for the graph. + vertex (Vertex): The vertex for which to retrieve the next runnable and top level vertices. + + Returns: + Tuple[List[Vertex], List[Vertex]]: A tuple containing the next runnable vertices and the top level vertices. + """ + next_runnable_vertices = await self.run_manager.get_next_runnable_vertices(lock, set_cache_coro, self, vertex) + top_level_vertices = self.run_manager.get_top_level_vertices(self, next_runnable_vertices) + return next_runnable_vertices, top_level_vertices + + def get_vertex_edges( + self, + vertex_id: str, + is_target: Optional[bool] = None, + is_source: Optional[bool] = None, + ) -> List[ContractEdge]: + """Returns a list of edges for a given vertex.""" + # The idea here is to return the edges that have the vertex_id as source or target + # or both + return [ + edge + for edge in self.edges + if (edge.source_id == vertex_id and is_source is not False) + or (edge.target_id == vertex_id and is_target is not False) + ] + + def get_vertices_with_target(self, vertex_id: str) -> List[Vertex]: + """Returns the vertices connected to a vertex.""" + vertices: List[Vertex] = [] + for edge in self.edges: + if edge.target_id == vertex_id: + vertex = self.get_vertex(edge.source_id) + if vertex is None: + continue + vertices.append(vertex) + return vertices + + async def process(self) -> "Graph": + """Processes the graph with vertices in each layer run in parallel.""" + vertices_layers = self.sorted_vertices_layers + vertex_task_run_count: Dict[str, int] = {} + for layer_index, layer in enumerate(vertices_layers): + tasks = [] + for vertex_id in layer: + vertex = self.get_vertex(vertex_id) + task = asyncio.create_task( + vertex.build(), + name=f"{vertex.display_name} Run {vertex_task_run_count.get(vertex_id, 0)}", + ) + tasks.append(task) + vertex_task_run_count[vertex_id] = vertex_task_run_count.get(vertex_id, 0) + 1 + logger.debug(f"Running layer {layer_index} with {len(tasks)} tasks") + await self._execute_tasks(tasks) + logger.debug("Graph processing complete") + return self + + async def _execute_tasks(self, tasks): + """Executes tasks in parallel, handling exceptions for each task.""" + results = [] + for i, task in enumerate(asyncio.as_completed(tasks)): + try: + result = await task + results.append(result) + except Exception as e: + # Log the exception along with the task name for easier debugging + # task_name = task.get_name() + # coroutine has not attribute get_name + task_name = tasks[i].get_name() + logger.error(f"Task {task_name} failed with exception: {e}") + # Cancel all remaining tasks + for t in tasks[i:]: + t.cancel() + raise e + return results + + def topological_sort(self) -> List[Vertex]: + """ + Performs a topological sort of the vertices in the graph. + + Returns: + List[Vertex]: A list of vertices in topological order. + + Raises: + ValueError: If the graph contains a cycle. + """ + # States: 0 = unvisited, 1 = visiting, 2 = visited + state = {vertex: 0 for vertex in self.vertices} + sorted_vertices = [] + + def dfs(vertex): + if state[vertex] == 1: + # We have a cycle + raise ValueError("Graph contains a cycle, cannot perform topological sort") + if state[vertex] == 0: + state[vertex] = 1 + for edge in vertex.edges: + if edge.source_id == vertex.id: + dfs(self.get_vertex(edge.target_id)) + state[vertex] = 2 + sorted_vertices.append(vertex) + + # Visit each vertex + for vertex in self.vertices: + if state[vertex] == 0: + dfs(vertex) + + return list(reversed(sorted_vertices)) + + def generator_build(self) -> Generator[Vertex, None, None]: + """Builds each vertex in the graph and yields it.""" + sorted_vertices = self.topological_sort() + logger.debug("There are %s vertices in the graph", len(sorted_vertices)) + yield from sorted_vertices + + def get_predecessors(self, vertex): + """Returns the predecessors of a vertex.""" + return [self.get_vertex(source_id) for source_id in self.predecessor_map.get(vertex.id, [])] + + def get_all_successors(self, vertex, recursive=True, flat=True): + # Recursively get the successors of the current vertex + # successors = vertex.successors + # if not successors: + # return [] + # successors_result = [] + # for successor in successors: + # # Just return a list of successors + # if recursive: + # next_successors = self.get_all_successors(successor) + # successors_result.extend(next_successors) + # successors_result.append(successor) + # return successors_result + # The above is the version without the flat parameter + # The below is the version with the flat parameter + # the flat parameter will define if each layer of successors + # becomes one list or if the result is a list of lists + # if flat is True, the result will be a list of vertices + # if flat is False, the result will be a list of lists of vertices + # each list will represent a layer of successors + successors = vertex.successors + if not successors: + return [] + successors_result = [] + for successor in successors: + if recursive: + next_successors = self.get_all_successors(successor) + if flat: + successors_result.extend(next_successors) + else: + successors_result.append(next_successors) + if flat: + successors_result.append(successor) + else: + successors_result.append([successor]) + return successors_result + + def get_successors(self, vertex): + """Returns the successors of a vertex.""" + return [self.get_vertex(target_id) for target_id in self.successor_map.get(vertex.id, [])] + + def get_vertex_neighbors(self, vertex: Vertex) -> Dict[Vertex, int]: + """Returns the neighbors of a vertex.""" + neighbors: Dict[Vertex, int] = {} + for edge in self.edges: + if edge.source_id == vertex.id: + neighbor = self.get_vertex(edge.target_id) + if neighbor is None: + continue + if neighbor not in neighbors: + neighbors[neighbor] = 0 + neighbors[neighbor] += 1 + elif edge.target_id == vertex.id: + neighbor = self.get_vertex(edge.source_id) + if neighbor is None: + continue + if neighbor not in neighbors: + neighbors[neighbor] = 0 + neighbors[neighbor] += 1 + return neighbors + + def _build_edges(self) -> List[ContractEdge]: + """Builds the edges of the graph.""" + # Edge takes two vertices as arguments, so we need to build the vertices first + # and then build the edges + # if we can't find a vertex, we raise an error + + edges: set[ContractEdge] = set() + for edge in self._edges: + source = self.get_vertex(edge["source"]) + target = self.get_vertex(edge["target"]) + + if source is None: + raise ValueError(f"Source vertex {edge['source']} not found") + if target is None: + raise ValueError(f"Target vertex {edge['target']} not found") + new_edge = ContractEdge(source, target, edge) + + edges.add(new_edge) + + return list(edges) + + def _get_vertex_class(self, node_type: str, node_base_type: str, node_id: str) -> Type[Vertex]: + """Returns the node class based on the node type.""" + # First we check for the node_base_type + node_name = node_id.split("-")[0] + if node_name in ["ChatOutput", "ChatInput"]: + return ChatVertex + elif node_name in ["ShouldRunNext"]: + return RoutingVertex + elif node_name in ["SharedState", "Notify", "GetNotified"]: + return StateVertex + elif node_base_type in lazy_load_vertex_dict.VERTEX_TYPE_MAP: + return lazy_load_vertex_dict.VERTEX_TYPE_MAP[node_base_type] + elif node_name in lazy_load_vertex_dict.VERTEX_TYPE_MAP: + return lazy_load_vertex_dict.VERTEX_TYPE_MAP[node_name] + + if node_type in FILE_TOOLS: + return FileToolVertex + if node_type in lazy_load_vertex_dict.VERTEX_TYPE_MAP: + return lazy_load_vertex_dict.VERTEX_TYPE_MAP[node_type] + return ( + lazy_load_vertex_dict.VERTEX_TYPE_MAP[node_base_type] + if node_base_type in lazy_load_vertex_dict.VERTEX_TYPE_MAP + else Vertex + ) + + def _build_vertices(self) -> List[Vertex]: + """Builds the vertices of the graph.""" + vertices: List[Vertex] = [] + for vertex in self._vertices: + vertex_data = vertex["data"] + vertex_type: str = vertex_data["type"] # type: ignore + vertex_base_type: str = vertex_data["node"]["template"]["_type"] # type: ignore + if "id" not in vertex_data: + raise ValueError(f"Vertex data for {vertex_data['display_name']} does not contain an id") + + VertexClass = self._get_vertex_class(vertex_type, vertex_base_type, vertex_data["id"]) + + vertex_instance = VertexClass(vertex, graph=self) + vertex_instance.set_top_level(self.top_level_vertices) + vertices.append(vertex_instance) + + return vertices + + def get_children_by_vertex_type(self, vertex: Vertex, vertex_type: str) -> List[Vertex]: + """Returns the children of a vertex based on the vertex type.""" + children = [] + vertex_types = [vertex.data["type"]] + if "node" in vertex.data: + vertex_types += vertex.data["node"]["base_classes"] + if vertex_type in vertex_types: + children.append(vertex) + return children + + def __repr__(self): + vertex_ids = [vertex.id for vertex in self.vertices] + edges_repr = "\n".join([f"{edge.source_id} --> {edge.target_id}" for edge in self.edges]) + return f"Graph:\nNodes: {vertex_ids}\nConnections:\n{edges_repr}" + + def sort_up_to_vertex(self, vertex_id: str, is_start: bool = False) -> List[Vertex]: + """Cuts the graph up to a given vertex and sorts the resulting subgraph.""" + # Initial setup + visited = set() # To keep track of visited vertices + excluded = set() # To keep track of vertices that should be excluded + stack = [vertex_id] # Use a list as a stack for DFS + + def get_successors(vertex, recursive=True): + # Recursively get the successors of the current vertex + successors = vertex.successors + if not successors: + return [] + successors_result = [] + for successor in successors: + # Just return a list of successors + if recursive: + next_successors = get_successors(successor) + successors_result.extend(next_successors) + successors_result.append(successor) + return successors_result + + stop_or_start_vertex = self.get_vertex(vertex_id) + stop_predecessors = [pre.id for pre in stop_or_start_vertex.predecessors] + # DFS to collect all vertices that can reach the specified vertex + while stack: + current_id = stack.pop() + if current_id not in visited and current_id not in excluded: + visited.add(current_id) + current_vertex = self.get_vertex(current_id) + # Assuming get_predecessors is a method that returns all vertices with edges to current_vertex + for predecessor in current_vertex.predecessors: + stack.append(predecessor.id) + + if current_id == vertex_id: + # We should add to visited all the vertices that are successors of the current vertex + # and their successors and so on + # if the vertex is a start, it means we are starting from the beginning + # and getting successors + for successor in current_vertex.successors: + if is_start: + stack.append(successor.id) + else: + excluded.add(successor.id) + all_successors = get_successors(successor) + for successor in all_successors: + if is_start: + stack.append(successor.id) + else: + excluded.add(successor.id) + elif current_id not in stop_predecessors: + # If the current vertex is not the target vertex, we should add all its successors + # to the stack if they are not in visited + for successor in current_vertex.successors: + if successor.id not in visited: + stack.append(successor.id) + + # Filter the original graph's vertices and edges to keep only those in `visited` + vertices_to_keep = [self.get_vertex(vid) for vid in visited] + + return vertices_to_keep + + def layered_topological_sort( + self, + vertices: List[Vertex], + filter_graphs: bool = False, + ) -> List[List[str]]: + """Performs a layered topological sort of the vertices in the graph.""" + vertices_ids = {vertex.id for vertex in vertices} + # Queue for vertices with no incoming edges + queue = deque( + vertex.id + for vertex in vertices + # if filter_graphs then only vertex.is_input will be considered + if self.in_degree_map[vertex.id] == 0 and (not filter_graphs or vertex.is_input) + ) + layers: List[List[str]] = [] + visited = set(queue) + current_layer = 0 + while queue: + layers.append([]) # Start a new layer + layer_size = len(queue) + for _ in range(layer_size): + vertex_id = queue.popleft() + visited.add(vertex_id) + + layers[current_layer].append(vertex_id) + for neighbor in self.successor_map[vertex_id]: + # only vertices in `vertices_ids` should be considered + # because vertices by have been filtered out + # in a previous step. All dependencies of theirs + # will be built automatically if required + if neighbor not in vertices_ids: + continue + + self.in_degree_map[neighbor] -= 1 # 'remove' edge + if self.in_degree_map[neighbor] == 0 and neighbor not in visited: + queue.append(neighbor) + + # if > 0 it might mean not all predecessors have added to the queue + # so we should process the neighbors predecessors + elif self.in_degree_map[neighbor] > 0: + for predecessor in self.predecessor_map[neighbor]: + if predecessor not in queue and predecessor not in visited: + queue.append(predecessor) + + current_layer += 1 # Next layer + new_layers = self.refine_layers(layers) + return new_layers + + def refine_layers(self, initial_layers): + # Map each vertex to its current layer + vertex_to_layer = {} + for layer_index, layer in enumerate(initial_layers): + for vertex in layer: + vertex_to_layer[vertex] = layer_index + + # Build the adjacency list for reverse lookup (dependencies) + + refined_layers = [[] for _ in initial_layers] # Start with empty layers + new_layer_index_map = defaultdict(int) + + # Map each vertex to its new layer index + # by finding the lowest layer index of its dependencies + # and subtracting 1 + # If a vertex has no dependencies, it will be placed in the first layer + # If a vertex has dependencies, it will be placed in the lowest layer index of its dependencies + # minus 1 + for vertex_id, deps in self.successor_map.items(): + indexes = [vertex_to_layer[dep] for dep in deps if dep in vertex_to_layer] + new_layer_index = max(min(indexes, default=0) - 1, 0) + new_layer_index_map[vertex_id] = new_layer_index + + for layer_index, layer in enumerate(initial_layers): + for vertex_id in layer: + # Place the vertex in the highest possible layer where its dependencies are met + new_layer_index = new_layer_index_map[vertex_id] + if new_layer_index > layer_index: + refined_layers[new_layer_index].append(vertex_id) + vertex_to_layer[vertex_id] = new_layer_index + else: + refined_layers[layer_index].append(vertex_id) + + # Remove empty layers if any + refined_layers = [layer for layer in refined_layers if layer] + + return refined_layers + + def sort_chat_inputs_first(self, vertices_layers: List[List[str]]) -> List[List[str]]: + chat_inputs_first = [] + for layer in vertices_layers: + for vertex_id in layer: + if "ChatInput" in vertex_id: + # Remove the ChatInput from the layer + layer.remove(vertex_id) + chat_inputs_first.append(vertex_id) + if not chat_inputs_first: + return vertices_layers + + vertices_layers = [chat_inputs_first] + vertices_layers + + return vertices_layers + + def sort_vertices( + self, + stop_component_id: Optional[str] = None, + start_component_id: Optional[str] = None, + ) -> List[str]: + """Sorts the vertices in the graph.""" + self.mark_all_vertices("ACTIVE") + if stop_component_id is not None: + self.stop_vertex = stop_component_id + vertices = self.sort_up_to_vertex(stop_component_id) + elif start_component_id: + vertices = self.sort_up_to_vertex(start_component_id, is_start=True) + else: + vertices = self.vertices + # without component_id we are probably running in the chat + # so we want to pick only graphs that start with ChatInput or + # TextInput + + vertices_layers = self.layered_topological_sort(vertices) + vertices_layers = self.sort_by_avg_build_time(vertices_layers) + # vertices_layers = self.sort_chat_inputs_first(vertices_layers) + self.increment_run_count() + self._sorted_vertices_layers = vertices_layers + first_layer = vertices_layers[0] + # save the only the rest + self.vertices_layers = vertices_layers[1:] + self.vertices_to_run = {vertex_id for vertex_id in chain.from_iterable(vertices_layers)} + self.build_run_map() + # Return just the first layer + return first_layer + + def sort_interface_components_first(self, vertices_layers: List[List[str]]) -> List[List[str]]: + """Sorts the vertices in the graph so that vertices containing ChatInput or ChatOutput come first.""" + + def contains_interface_component(vertex): + return any(component.value in vertex for component in InterfaceComponentTypes) + + # Sort each inner list so that vertices containing ChatInput or ChatOutput come first + sorted_vertices = [ + sorted( + inner_list, + key=lambda vertex: not contains_interface_component(vertex), + ) + for inner_list in vertices_layers + ] + return sorted_vertices + + def sort_by_avg_build_time(self, vertices_layers: List[List[str]]) -> List[List[str]]: + """Sorts the vertices in the graph so that vertices with the lowest average build time come first.""" + + def sort_layer_by_avg_build_time(vertices_ids: List[str]) -> List[str]: + """Sorts the vertices in the graph so that vertices with the lowest average build time come first.""" + if len(vertices_ids) == 1: + return vertices_ids + vertices_ids.sort(key=lambda vertex_id: self.get_vertex(vertex_id).avg_build_time) + + return vertices_ids + + sorted_vertices = [sort_layer_by_avg_build_time(layer) for layer in vertices_layers] + return sorted_vertices + + def is_vertex_runnable(self, vertex_id: str) -> bool: + """Returns whether a vertex is runnable.""" + return self.run_manager.is_vertex_runnable(vertex_id) + + def build_run_map(self): + """ + Builds the run map for the graph. + + This method is responsible for building the run map for the graph, + which maps each node in the graph to its corresponding run function. + + Returns: + None + """ + self.run_manager.build_run_map(self) + + def find_runnable_predecessors_for_successors(self, vertex_id: str) -> List[str]: + """ + For each successor of the current vertex, find runnable predecessors if any. + This checks the direct predecessors of each successor to identify any that are + immediately runnable, expanding the search to ensure progress can be made. + """ + return self.run_manager.find_runnable_predecessors_for_successors(vertex_id) + + def remove_from_predecessors(self, vertex_id: str): + self.run_manager.remove_from_predecessors(vertex_id) + + def build_in_degree(self): + in_degree = defaultdict(int) + for edge in self.edges: + in_degree[edge.target_id] += 1 + return in_degree + + def build_adjacency_maps(self): + """Returns the adjacency maps for the graph.""" + predecessor_map = defaultdict(list) + successor_map = defaultdict(list) + for edge in self.edges: + predecessor_map[edge.target_id].append(edge.source_id) + successor_map[edge.source_id].append(edge.target_id) + return predecessor_map, successor_map diff --git a/src/backend/langflow/graph/graph/constants.py b/src/backend/base/langflow/graph/graph/constants.py similarity index 89% rename from src/backend/langflow/graph/graph/constants.py rename to src/backend/base/langflow/graph/graph/constants.py index 928280743..658c3c68a 100644 --- a/src/backend/langflow/graph/graph/constants.py +++ b/src/backend/base/langflow/graph/graph/constants.py @@ -1,6 +1,5 @@ from langflow.graph.vertex import types from langflow.interface.agents.base import agent_creator -from langflow.interface.chains.base import chain_creator from langflow.interface.custom.base import custom_component_creator from langflow.interface.document_loaders.base import documentloader_creator from langflow.interface.embeddings.base import embedding_creator @@ -15,6 +14,9 @@ from langflow.interface.tools.base import tool_creator from langflow.interface.wrappers.base import wrapper_creator from langflow.utils.lazy_load import LazyLoadDictBase +CHAT_COMPONENTS = ["ChatInput", "ChatOutput", "TextInput", "SessionID"] +ROUTING_COMPONENTS = ["ShouldRunNext"] + class VertexTypesDict(LazyLoadDictBase): def __init__(self): @@ -31,14 +33,11 @@ class VertexTypesDict(LazyLoadDictBase): "Custom": ["Custom Tool", "Python Function"], } - def get_custom_component_vertex_type(self): - return types.CustomComponentVertex - def get_type_dict(self): return { **{t: types.PromptVertex for t in prompt_creator.to_list()}, **{t: types.AgentVertex for t in agent_creator.to_list()}, - **{t: types.ChainVertex for t in chain_creator.to_list()}, + # **{t: types.ChainVertex for t in chain_creator.to_list()}, **{t: types.ToolVertex for t in tool_creator.to_list()}, **{t: types.ToolkitVertex for t in toolkits_creator.to_list()}, **{t: types.WrapperVertex for t in wrapper_creator.to_list()}, @@ -51,7 +50,12 @@ class VertexTypesDict(LazyLoadDictBase): **{t: types.OutputParserVertex for t in output_parser_creator.to_list()}, **{t: types.CustomComponentVertex for t in custom_component_creator.to_list()}, **{t: types.RetrieverVertex for t in retriever_creator.to_list()}, + **{t: types.ChatVertex for t in CHAT_COMPONENTS}, + **{t: types.RoutingVertex for t in ROUTING_COMPONENTS}, } + def get_custom_component_vertex_type(self): + return types.CustomComponentVertex + lazy_load_vertex_dict = VertexTypesDict() diff --git a/src/backend/base/langflow/graph/graph/runnable_vertices_manager.py b/src/backend/base/langflow/graph/graph/runnable_vertices_manager.py new file mode 100644 index 000000000..875f43472 --- /dev/null +++ b/src/backend/base/langflow/graph/graph/runnable_vertices_manager.py @@ -0,0 +1,111 @@ +import asyncio +from collections import defaultdict +from typing import TYPE_CHECKING, Awaitable, Callable, List + +if TYPE_CHECKING: + from langflow.graph.graph.base import Graph + from langflow.graph.vertex.base import Vertex + + +class RunnableVerticesManager: + def __init__(self): + self.run_map = defaultdict(list) # Tracks successors of each vertex + self.run_predecessors = defaultdict(set) # Tracks predecessors for each vertex + self.vertices_to_run = set() # Set of vertices that are ready to run + + def is_vertex_runnable(self, vertex_id: str) -> bool: + """Determines if a vertex is runnable.""" + return vertex_id in self.vertices_to_run and not self.run_predecessors.get(vertex_id) + + def find_runnable_predecessors_for_successors(self, vertex_id: str) -> List[str]: + """Finds runnable predecessors for the successors of a given vertex.""" + runnable_vertices = [] + visited = set() + + for successor_id in self.run_map.get(vertex_id, []): + for predecessor_id in self.run_predecessors.get(successor_id, []): + if predecessor_id not in visited and self.is_vertex_runnable(predecessor_id): + runnable_vertices.append(predecessor_id) + visited.add(predecessor_id) + return runnable_vertices + + def remove_from_predecessors(self, vertex_id: str): + """Removes a vertex from the predecessor list of its successors.""" + predecessors = self.run_map.get(vertex_id, []) + for predecessor in predecessors: + if vertex_id in self.run_predecessors[predecessor]: + self.run_predecessors[predecessor].remove(vertex_id) + + def build_run_map(self, graph): + """Builds a map of vertices and their runnable successors.""" + self.run_map = defaultdict(list) + for vertex_id, predecessors in graph.predecessor_map.items(): + for predecessor in predecessors: + self.run_map[predecessor].append(vertex_id) + self.run_predecessors = graph.predecessor_map.copy() + self.vertices_to_run = graph.vertices_to_run + + def update_vertex_run_state(self, vertex_id: str, is_runnable: bool): + """Updates the runnable state of a vertex.""" + if is_runnable: + self.vertices_to_run.add(vertex_id) + else: + self.vertices_to_run.discard(vertex_id) + + async def get_next_runnable_vertices( + self, + lock: asyncio.Lock, + set_cache_coro: Callable[["Graph", asyncio.Lock], Awaitable[None]], + graph: "Graph", + vertex: "Vertex", + ): + """ + Retrieves the next runnable vertices in the graph for a given vertex. + + Args: + graph (Graph): The graph object representing the flow. + vertex (Vertex): The current vertex. + vertex_id (str): The ID of the current vertex. + chat_service (ChatService): The chat service object. + flow_id (str): The ID of the flow. + + Returns: + list: A list of IDs of the next runnable vertices. + + """ + async with lock: + self.remove_from_predecessors(vertex.id) + direct_successors_ready = [v for v in vertex.successors_ids if self.is_vertex_runnable(v)] + if not direct_successors_ready: + # No direct successors ready, look for runnable predecessors of successors + next_runnable_vertices = self.find_runnable_predecessors_for_successors(vertex.id) + else: + next_runnable_vertices = direct_successors_ready + + for v_id in set(next_runnable_vertices): # Use set to avoid duplicates + self.update_vertex_run_state(v_id, is_runnable=False) + self.remove_from_predecessors(v_id) + await set_cache_coro(data=graph, lock=lock) # type: ignore + return next_runnable_vertices + + @staticmethod + def get_top_level_vertices(graph, vertices_ids): + """ + Retrieves the top-level vertices from the given graph based on the provided vertex IDs. + + Args: + graph (Graph): The graph object containing the vertices. + vertices_ids (list): A list of vertex IDs. + + Returns: + list: A list of top-level vertex IDs. + + """ + top_level_vertices = [] + for vertex_id in vertices_ids: + vertex = graph.get_vertex(vertex_id) + if vertex.parent_is_top_level: + top_level_vertices.append(vertex.parent_node_id) + else: + top_level_vertices.append(vertex_id) + return top_level_vertices diff --git a/src/backend/base/langflow/graph/graph/state_manager.py b/src/backend/base/langflow/graph/graph/state_manager.py new file mode 100644 index 000000000..880adca55 --- /dev/null +++ b/src/backend/base/langflow/graph/graph/state_manager.py @@ -0,0 +1,36 @@ +from typing import TYPE_CHECKING, Callable + +from langflow.services.deps import get_state_service +from loguru import logger + +if TYPE_CHECKING: + from langflow.services.state.service import StateService + + +class GraphStateManager: + def __init__(self): + self.state_service: "StateService" = get_state_service() + + def append_state(self, key, new_state, run_id: str): + self.state_service.append_state(key, new_state, run_id) + + def update_state(self, key, new_state, run_id: str): + self.state_service.update_state(key, new_state, run_id) + + def get_state(self, key, run_id: str): + return self.state_service.get_state(key, run_id) + + def subscribe(self, key, observer: Callable): + self.state_service.subscribe(key, observer) + + def notify_observers(self, key, new_state): + for callback in self.observers[key]: + callback(key, new_state, append=False) + + def notify_append_observers(self, key, new_state): + for callback in self.observers[key]: + try: + callback(key, new_state, append=True) + except Exception as e: + logger.error(f"Error in observer {callback} for key {key}: {e}") + logger.warning("Callbacks not implemented yet") diff --git a/src/backend/langflow/graph/graph/utils.py b/src/backend/base/langflow/graph/graph/utils.py similarity index 82% rename from src/backend/langflow/graph/graph/utils.py rename to src/backend/base/langflow/graph/graph/utils.py index d43fc4d84..a3299739e 100644 --- a/src/backend/langflow/graph/graph/utils.py +++ b/src/backend/base/langflow/graph/graph/utils.py @@ -1,6 +1,5 @@ -import copy from collections import deque -from typing import Dict, List +import copy def find_last_node(nodes, edges): @@ -47,38 +46,6 @@ def ungroup_node(group_node_data, base_flow): return nodes -def raw_topological_sort(nodes, edges) -> List[Dict]: - # Redefine the above function but using the nodes and self._edges - # which are dicts instead of Vertex and Edge objects - # nodes have an id, edges have a source and target keys - # return a list of node ids in topological order - - # States: 0 = unvisited, 1 = visiting, 2 = visited - state = {node["id"]: 0 for node in nodes} - nodes_dict = {node["id"]: node for node in nodes} - sorted_vertices = [] - - def dfs(node): - if state[node] == 1: - # We have a cycle - raise ValueError("Graph contains a cycle, cannot perform topological sort") - if state[node] == 0: - state[node] = 1 - for edge in edges: - if edge["source"] == node: - dfs(edge["target"]) - state[node] = 2 - sorted_vertices.append(node) - - # Visit each node - for node in nodes: - if state[node["id"]] == 0: - dfs(node["id"]) - - reverse_sorted = list(reversed(sorted_vertices)) - return [nodes_dict[node_id] for node_id in reverse_sorted] - - def process_flow(flow_object): cloned_flow = copy.deepcopy(flow_object) processed_nodes = set() # To keep track of processed nodes @@ -99,8 +66,7 @@ def process_flow(flow_object): # Mark node as processed processed_nodes.add(node_id) - sorted_nodes_list = raw_topological_sort(cloned_flow["nodes"], cloned_flow["edges"]) - nodes_to_process = deque(sorted_nodes_list) + nodes_to_process = deque(cloned_flow["nodes"]) while nodes_to_process: node = nodes_to_process.popleft() @@ -141,11 +107,7 @@ def update_template(template, g_nodes): g_nodes[node_index]["data"]["node"]["template"][field]["display_name"] = display_name -def update_target_handle( - new_edge, - g_nodes, - group_node_id, -): +def update_target_handle(new_edge, g_nodes, group_node_id): """ Updates the target handle of a given edge if it is a proxy node. @@ -162,8 +124,6 @@ def update_target_handle( proxy_id = target_handle["proxy"]["id"] if node := next((n for n in g_nodes if n["id"] == proxy_id), None): set_new_target_handle(proxy_id, new_edge, target_handle, node) - else: - raise ValueError(f"Group node {group_node_id} has an invalid target proxy node {proxy_id}") return new_edge diff --git a/src/backend/base/langflow/graph/schema.py b/src/backend/base/langflow/graph/schema.py new file mode 100644 index 000000000..0bbdfa720 --- /dev/null +++ b/src/backend/base/langflow/graph/schema.py @@ -0,0 +1,55 @@ +from enum import Enum +from typing import Any, List, Optional + +from pydantic import BaseModel, Field, field_serializer + +from langflow.graph.utils import serialize_field +from langflow.utils.schemas import ChatOutputResponse, ContainsEnumMeta + + +class ResultData(BaseModel): + results: Optional[Any] = Field(default_factory=dict) + artifacts: Optional[Any] = Field(default_factory=dict) + messages: Optional[list[ChatOutputResponse]] = Field(default_factory=list) + timedelta: Optional[float] = None + duration: Optional[str] = None + component_display_name: Optional[str] = None + component_id: Optional[str] = None + + @field_serializer("results") + def serialize_results(self, value): + if isinstance(value, dict): + return {key: serialize_field(val) for key, val in value.items()} + return serialize_field(value) + + +class InterfaceComponentTypes(str, Enum, metaclass=ContainsEnumMeta): + # ChatInput and ChatOutput are the only ones that are + # power components + ChatInput = "ChatInput" + ChatOutput = "ChatOutput" + TextInput = "TextInput" + TextOutput = "TextOutput" + + def __contains__(cls, item): + try: + cls(item) + except ValueError: + return False + else: + return True + + +INPUT_COMPONENTS = [ + InterfaceComponentTypes.ChatInput, + InterfaceComponentTypes.TextInput, +] +OUTPUT_COMPONENTS = [ + InterfaceComponentTypes.ChatOutput, + InterfaceComponentTypes.TextOutput, +] + + +class RunOutputs(BaseModel): + inputs: dict = Field(default_factory=dict) + outputs: List[Optional[ResultData]] = Field(default_factory=list) diff --git a/src/backend/langflow/graph/utils.py b/src/backend/base/langflow/graph/utils.py similarity index 53% rename from src/backend/langflow/graph/utils.py rename to src/backend/base/langflow/graph/utils.py index e163d76c4..83e2177b1 100644 --- a/src/backend/langflow/graph/utils.py +++ b/src/backend/base/langflow/graph/utils.py @@ -1,5 +1,8 @@ from typing import Any, Union +from langchain_core.documents import Document +from pydantic import BaseModel + from langflow.interface.utils import extract_input_variables_from_prompt @@ -7,6 +10,10 @@ class UnbuiltObject: pass +class UnbuiltResult: + pass + + def validate_prompt(prompt: str): """Validate prompt.""" if extract_input_variables_from_prompt(prompt): @@ -29,3 +36,17 @@ def flatten_list(list_of_lists: list[Union[list, Any]]) -> list: else: new_list.append(item) return new_list + + +def serialize_field(value): + """Unified serialization function for handling both BaseModel and Document types, + including handling lists of these types.""" + if isinstance(value, (list, tuple)): + return [serialize_field(v) for v in value] + elif isinstance(value, Document): + return value.to_json() + elif isinstance(value, BaseModel): + return value.model_dump() + elif isinstance(value, str): + return {"result": value} + return value diff --git a/src/backend/langflow/services/chat/__init__.py b/src/backend/base/langflow/graph/vertex/__init__.py similarity index 100% rename from src/backend/langflow/services/chat/__init__.py rename to src/backend/base/langflow/graph/vertex/__init__.py diff --git a/src/backend/base/langflow/graph/vertex/base.py b/src/backend/base/langflow/graph/vertex/base.py new file mode 100644 index 000000000..5d855fcdb --- /dev/null +++ b/src/backend/base/langflow/graph/vertex/base.py @@ -0,0 +1,749 @@ +import ast +import asyncio +import inspect +import types +from enum import Enum +from typing import TYPE_CHECKING, Any, AsyncIterator, Callable, Dict, Iterator, List, Optional + +from loguru import logger + +from langflow.graph.schema import INPUT_COMPONENTS, OUTPUT_COMPONENTS, InterfaceComponentTypes, ResultData +from langflow.graph.utils import UnbuiltObject, UnbuiltResult +from langflow.graph.vertex.utils import generate_result +from langflow.interface.initialize import loading +from langflow.interface.listing import lazy_load_dict +from langflow.schema.schema import INPUT_FIELD_NAME +from langflow.services.deps import get_storage_service +from langflow.utils.constants import DIRECT_TYPES +from langflow.utils.schemas import ChatOutputResponse +from langflow.utils.util import sync_to_async, unescape_string + +if TYPE_CHECKING: + from langflow.graph.edge.base import ContractEdge + from langflow.graph.graph.base import Graph + + +class VertexStates(str, Enum): + """Vertex are related to it being active, inactive, or in an error state.""" + + ACTIVE = "active" + INACTIVE = "inactive" + ERROR = "error" + + +class Vertex: + def __init__( + self, + data: Dict, + graph: "Graph", + base_type: Optional[str] = None, + is_task: bool = False, + params: Optional[Dict] = None, + ) -> None: + # is_external means that the Vertex send or receives data from + # an external source (e.g the chat) + self._lock = asyncio.Lock() + self.will_stream = False + self.updated_raw_params = False + self.id: str = data["id"] + self.base_name = self.id.split("-")[0] + self.is_state = False + self.is_input = any(input_component_name in self.id for input_component_name in INPUT_COMPONENTS) + self.is_output = any(output_component_name in self.id for output_component_name in OUTPUT_COMPONENTS) + self.has_session_id = None + self._custom_component = None + self.has_external_input = False + self.has_external_output = False + self.graph = graph + self._data = data + self.base_type: Optional[str] = base_type + self._parse_data() + self._built_object = UnbuiltObject() + self._built_result = None + self._built = False + self.artifacts: Dict[str, Any] = {} + self.steps: List[Callable] = [self._build] + self.steps_ran: List[Callable] = [] + self.task_id: Optional[str] = None + self.is_task = is_task + self.params = params or {} + self.parent_node_id: Optional[str] = self._data.get("parent_node_id") + self.load_from_db_fields: List[str] = [] + self.parent_is_top_level = False + self.layer = None + self.should_run = True + self.result: Optional[ResultData] = None + try: + self.is_interface_component = self.vertex_type in InterfaceComponentTypes + except ValueError: + self.is_interface_component = False + + self.use_result = False + self.build_times: List[float] = [] + self.state = VertexStates.ACTIVE + + def update_graph_state(self, key, new_state, append: bool): + if append: + self.graph.append_state(key, new_state, caller=self.id) + else: + self.graph.update_state(key, new_state, caller=self.id) + + def set_state(self, state: str): + self.state = VertexStates[state] + if self.state == VertexStates.INACTIVE and self.graph.in_degree_map[self.id] < 2: + # If the vertex is inactive and has only one in degree + # it means that it is not a merge point in the graph + self.graph.inactivated_vertices.add(self.id) + elif self.state == VertexStates.ACTIVE and self.id in self.graph.inactivated_vertices: + self.graph.inactivated_vertices.remove(self.id) + + @property + def avg_build_time(self): + return sum(self.build_times) / len(self.build_times) if self.build_times else 0 + + def add_build_time(self, time): + self.build_times.append(time) + + def set_result(self, result: ResultData) -> None: + self.result = result + + def get_built_result(self): + # If the Vertex.type is a power component + # then we need to return the built object + # instead of the result dict + if self.is_interface_component and not isinstance(self._built_object, UnbuiltObject): + result = self._built_object + # if it is not a dict or a string and hasattr model_dump then + # return the model_dump + if not isinstance(result, (dict, str)) and hasattr(result, "content"): + return result.content + return result + if isinstance(self._built_object, str): + self._built_result = self._built_object + + if isinstance(self._built_result, UnbuiltResult): + return {} + return self._built_result if isinstance(self._built_result, dict) else {"result": self._built_result} + + def set_artifacts(self) -> None: + pass + + @property + def edges(self) -> List["ContractEdge"]: + return self.graph.get_vertex_edges(self.id) + + @property + def predecessors(self) -> List["Vertex"]: + return self.graph.get_predecessors(self) + + @property + def successors(self) -> List["Vertex"]: + return self.graph.get_successors(self) + + @property + def successors_ids(self) -> List[str]: + return self.graph.successor_map.get(self.id, []) + + def __getstate__(self): + return { + "_data": self._data, + "params": {}, + "base_type": self.base_type, + "base_name": self.base_name, + "is_task": self.is_task, + "id": self.id, + "_built_object": UnbuiltObject(), + "_built": False, + "parent_node_id": self.parent_node_id, + "parent_is_top_level": self.parent_is_top_level, + "load_from_db_fields": self.load_from_db_fields, + "is_input": self.is_input, + "is_output": self.is_output, + } + + def __setstate__(self, state): + self._lock = asyncio.Lock() + self._data = state["_data"] + self.params = state["params"] + self.base_type = state["base_type"] + self.is_task = state["is_task"] + self.id = state["id"] + self.frozen = state.get("frozen", False) + self.is_input = state.get("is_input", False) + self.is_output = state.get("is_output", False) + self.base_name = state["base_name"] + self._parse_data() + if "_built_object" in state: + self._built_object = state["_built_object"] + self._built = state["_built"] + else: + self._built_object = UnbuiltObject() + self._built = False + if "_built_result" in state: + self._built_result = state["_built_result"] + else: + self._built_result = UnbuiltResult() + self.artifacts: Dict[str, Any] = {} + self.task_id: Optional[str] = None + self.parent_node_id = state["parent_node_id"] + self.parent_is_top_level = state["parent_is_top_level"] + self.load_from_db_fields = state["load_from_db_fields"] + self.layer = state.get("layer") + self.steps = state.get("steps", [self._build]) + + def set_top_level(self, top_level_vertices: List[str]) -> None: + self.parent_is_top_level = self.parent_node_id in top_level_vertices + + def _parse_data(self) -> None: + self.data = self._data["data"] + self.output = self.data["node"]["base_classes"] + self.display_name = self.data["node"].get("display_name", self.id.split("-")[0]) + + self.description = self.data["node"].get("description", "") + self.frozen = self.data["node"].get("frozen", False) + self.selected_output_type = self.data["node"].get("selected_output_type") + self.is_input = self.data["node"].get("is_input") or self.is_input + self.is_output = self.data["node"].get("is_output") or self.is_output + template_dicts = {key: value for key, value in self.data["node"]["template"].items() if isinstance(value, dict)} + + self.has_session_id = "session_id" in template_dicts + + self.required_inputs = [ + template_dicts[key]["type"] for key, value in template_dicts.items() if value["required"] + ] + self.optional_inputs = [ + template_dicts[key]["type"] for key, value in template_dicts.items() if not value["required"] + ] + # Add the template_dicts[key]["input_types"] to the optional_inputs + self.optional_inputs.extend( + [input_type for value in template_dicts.values() for input_type in value.get("input_types", [])] + ) + + template_dict = self.data["node"]["template"] + self.vertex_type = ( + self.data["type"] + if "Tool" not in self.output or template_dict["_type"].islower() + else template_dict["_type"] + ) + + if self.base_type is None: + for base_type, value in lazy_load_dict.ALL_TYPES_DICT.items(): + if self.vertex_type in value: + self.base_type = base_type + break + + def get_task(self): + # using the task_id, get the task from celery + # and return it + from celery.result import AsyncResult # type: ignore + + return AsyncResult(self.task_id) + + def _build_params(self): + # sourcery skip: merge-list-append, remove-redundant-if + # Some params are required, some are optional + # but most importantly, some params are python base classes + # like str and others are LangChain objects like LLMChain, BasePromptTemplate + # so we need to be able to distinguish between the two + + # The dicts with "type" == "str" are the ones that are python base classes + # and most likely have a "value" key + + # So for each key besides "_type" in the template dict, we have a dict + # with a "type" key. If the type is not "str", then we need to get the + # edge that connects to that node and get the Node with the required data + # and use that as the value for the param + # If the type is "str", then we need to get the value of the "value" key + # and use that as the value for the param + + if self.graph is None: + raise ValueError("Graph not found") + + if self.updated_raw_params: + self.updated_raw_params = False + return + + template_dict = {key: value for key, value in self.data["node"]["template"].items() if isinstance(value, dict)} + params = {} + + for edge in self.edges: + if not hasattr(edge, "target_param"): + continue + param_key = edge.target_param + + # If the param_key is in the template_dict and the edge.target_id is the current node + # We check this to make sure params with the same name but different target_id + # don't get overwritten + if param_key in template_dict and edge.target_id == self.id: + if template_dict[param_key]["list"]: + if param_key not in params: + params[param_key] = [] + params[param_key].append(self.graph.get_vertex(edge.source_id)) + elif edge.target_id == self.id: + if isinstance(template_dict[param_key].get("value"), dict): + # we don't know the key of the dict but we need to set the value + # to the vertex that is the source of the edge + param_dict = template_dict[param_key]["value"] + params[param_key] = {key: self.graph.get_vertex(edge.source_id) for key in param_dict.keys()} + else: + params[param_key] = self.graph.get_vertex(edge.source_id) + + load_from_db_fields = [] + for field_name, field in template_dict.items(): + if field_name in params: + continue + # Skip _type and any value that has show == False and is not code + # If we don't want to show code but we want to use it + if field_name == "_type" or (not field.get("show") and field_name != "code"): + continue + # If the type is not transformable to a python base class + # then we need to get the edge that connects to this node + if field.get("type") == "file": + # Load the type in value.get('fileTypes') using + # what is inside value.get('content') + # value.get('value') is the file name + if file_path := field.get("file_path"): + storage_service = get_storage_service() + try: + flow_id, file_name = file_path.split("/") + full_path = storage_service.build_full_path(flow_id, file_name) + except ValueError as e: + if "too many values to unpack" in str(e): + full_path = file_path + else: + raise e + params[field_name] = full_path + elif field.get("required"): + raise ValueError(f"File path not found for {self.display_name}") + elif field.get("type") in DIRECT_TYPES and params.get(field_name) is None: + val = field.get("value") + if field.get("type") == "code": + try: + params[field_name] = ast.literal_eval(val) if val else None + except Exception: + params[field_name] = val + elif field.get("type") in ["dict", "NestedDict"]: + # When dict comes from the frontend it comes as a + # list of dicts, so we need to convert it to a dict + # before passing it to the build method + if isinstance(val, list): + params[field_name] = {k: v for item in field.get("value", []) for k, v in item.items()} + elif isinstance(val, dict): + params[field_name] = val + elif field.get("type") == "int" and val is not None: + try: + params[field_name] = int(val) + except ValueError: + params[field_name] = val + elif field.get("type") == "float" and val is not None: + try: + params[field_name] = float(val) + except ValueError: + params[field_name] = val + params[field_name] = val + elif field.get("type") == "str" and val is not None: + # val may contain escaped \n, \t, etc. + # so we need to unescape it + if isinstance(val, list): + params[field_name] = [unescape_string(v) for v in val] + elif isinstance(val, str): + params[field_name] = unescape_string(val) + elif val is not None and val != "": + params[field_name] = val + + elif val is not None and val != "": + params[field_name] = val + if field.get("load_from_db"): + load_from_db_fields.append(field_name) + + if not field.get("required") and params.get(field_name) is None: + if field.get("default"): + params[field_name] = field.get("default") + else: + params.pop(field_name, None) + # Add _type to params + self.params = params + self.load_from_db_fields = load_from_db_fields + self._raw_params = params.copy() + + def update_raw_params(self, new_params: Dict[str, str], overwrite: bool = False): + """ + Update the raw parameters of the vertex with the given new parameters. + + Args: + new_params (Dict[str, Any]): The new parameters to update. + + Raises: + ValueError: If any key in new_params is not found in self._raw_params. + """ + # First check if the input_value in _raw_params is not a vertex + if not new_params: + return + if any(isinstance(self._raw_params.get(key), Vertex) for key in new_params): + return + if not overwrite: + for key in new_params.copy(): + if key not in self._raw_params: + new_params.pop(key) + self._raw_params.update(new_params) + self.params = self._raw_params.copy() + self.updated_raw_params = True + + async def _build(self, user_id=None): + """ + Initiate the build process. + """ + logger.debug(f"Building {self.display_name}") + await self._build_each_vertex_in_params_dict(user_id) + await self._get_and_instantiate_class(user_id) + self._validate_built_object() + + self._built = True + + def extract_messages_from_artifacts(self, artifacts: Dict[str, Any]) -> List[dict]: + """ + Extracts messages from the artifacts. + + Args: + artifacts (Dict[str, Any]): The artifacts to extract messages from. + + Returns: + List[str]: The extracted messages. + """ + try: + messages = [ + ChatOutputResponse( + message=artifacts["message"], + sender=artifacts.get("sender"), + sender_name=artifacts.get("sender_name"), + session_id=artifacts.get("session_id"), + component_id=self.id, + ).model_dump(exclude_none=True) + ] + except KeyError: + messages = [] + + return messages + + def _finalize_build(self): + result_dict = self.get_built_result() + # We need to set the artifacts to pass information + # to the frontend + self.set_artifacts() + artifacts = self.artifacts + messages = self.extract_messages_from_artifacts(artifacts) + result_dict = ResultData( + results=result_dict, + artifacts=artifacts, + messages=messages, + component_display_name=self.display_name, + component_id=self.id, + ) + self.set_result(result_dict) + + async def _run( + self, + user_id: str, + inputs: Optional[dict] = None, + session_id: Optional[str] = None, + ): + # user_id is just for compatibility with the other build methods + inputs = inputs or {} + # inputs = {key: value or "" for key, value in inputs.items()} + # if hasattr(self._built_object, "input_keys"): + # # test if all keys are in inputs + # # and if not add them with empty string + # # for key in self._built_object.input_keys: + # # if key not in inputs: + # # inputs[key] = "" + # if inputs == {} and hasattr(self._built_object, "prompt"): + # inputs = self._built_object.prompt.partial_variables + if isinstance(self._built_object, str): + self._built_result = self._built_object + + result = await generate_result(self._built_object, inputs, self.has_external_output, session_id) + self._built_result = result + + async def _build_each_vertex_in_params_dict(self, user_id=None): + """ + Iterates over each vertex in the params dictionary and builds it. + """ + for key, value in self._raw_params.items(): + if self._is_vertex(value): + if value == self: + del self.params[key] + continue + await self._build_vertex_and_update_params( + key, + value, + ) + elif isinstance(value, list) and self._is_list_of_vertices(value): + await self._build_list_of_vertices_and_update_params(key, value) + elif isinstance(value, dict): + await self._build_dict_and_update_params( + key, + value, + ) + elif key not in self.params or self.updated_raw_params: + self.params[key] = value + + async def _build_dict_and_update_params( + self, + key, + vertices_dict: Dict[str, "Vertex"], + ): + """ + Iterates over a dictionary of vertices, builds each and updates the params dictionary. + """ + for sub_key, value in vertices_dict.items(): + if not self._is_vertex(value): + self.params[key][sub_key] = value + else: + result = await value.get_result() + self.params[key][sub_key] = result + + def _is_vertex(self, value): + """ + Checks if the provided value is an instance of Vertex. + """ + return isinstance(value, Vertex) + + def _is_list_of_vertices(self, value): + """ + Checks if the provided value is a list of Vertex instances. + """ + return all(self._is_vertex(vertex) for vertex in value) + + async def get_result( + self, + ) -> Any: + """ + Retrieves the result of the vertex. + + This is a read-only method so it raises an error if the vertex has not been built yet. + + Returns: + The result of the vertex. + """ + async with self._lock: + return await self._get_result() + + async def _get_result(self) -> Any: + """ + Retrieves the result of the built component. + + If the component has not been built yet, a ValueError is raised. + + Returns: + The built result if use_result is True, else the built object. + """ + if not self._built: + raise ValueError(f"Component {self.display_name} has not been built yet") + return self._built_result if self.use_result else self._built_object + + async def _build_vertex_and_update_params(self, key, vertex: "Vertex"): + """ + Builds a given vertex and updates the params dictionary accordingly. + """ + + result = await vertex.get_result() + self._handle_func(key, result) + if isinstance(result, list): + self._extend_params_list_with_result(key, result) + self.params[key] = result + + async def _build_list_of_vertices_and_update_params( + self, + key, + vertices: List["Vertex"], + ): + """ + Iterates over a list of vertices, builds each and updates the params dictionary. + """ + self.params[key] = [] + for vertex in vertices: + result = await vertex.get_result() + # Weird check to see if the params[key] is a list + # because sometimes it is a Record and breaks the code + if not isinstance(self.params[key], list): + self.params[key] = [self.params[key]] + + if isinstance(result, list): + self.params[key].extend(result) + else: + try: + if self.params[key] == result: + continue + + self.params[key].append(result) + except AttributeError as e: + logger.exception(e) + raise ValueError( + f"Params {key} ({self.params[key]}) is not a list and cannot be extended with {result}" + f"Error building vertex {self.display_name}: {str(e)}" + ) from e + + def _handle_func(self, key, result): + """ + Handles 'func' key by checking if the result is a function and setting it as coroutine. + """ + if key == "func": + if not isinstance(result, types.FunctionType): + if hasattr(result, "run"): + result = result.run # type: ignore + elif hasattr(result, "get_function"): + result = result.get_function() # type: ignore + elif inspect.iscoroutinefunction(result): + self.params["coroutine"] = result + else: + self.params["coroutine"] = sync_to_async(result) + + def _extend_params_list_with_result(self, key, result): + """ + Extends a list in the params dictionary with the given result if it exists. + """ + if isinstance(self.params[key], list): + self.params[key].extend(result) + + async def _get_and_instantiate_class(self, user_id=None): + """ + Gets the class from a dictionary and instantiates it with the params. + """ + if self.base_type is None: + raise ValueError(f"Base type for vertex {self.display_name} not found") + try: + result = await loading.instantiate_class( + user_id=user_id, + vertex=self, + ) + self._update_built_object_and_artifacts(result) + except Exception as exc: + logger.exception(exc) + + raise ValueError(f"Error building vertex {self.display_name}: {str(exc)}") from exc + + def _update_built_object_and_artifacts(self, result): + """ + Updates the built object and its artifacts. + """ + if isinstance(result, tuple): + if len(result) == 2: + self._built_object, self.artifacts = result + elif len(result) == 3: + self._custom_component, self._built_object, self.artifacts = result + else: + self._built_object = result + + def _validate_built_object(self): + """ + Checks if the built object is None and raises a ValueError if so. + """ + if isinstance(self._built_object, UnbuiltObject): + raise ValueError(f"{self.display_name}: {self._built_object_repr()}") + elif self._built_object is None: + message = f"{self.display_name} returned None." + if self.base_type == "custom_components": + message += " Make sure your build method returns a component." + + logger.warning(message) + elif isinstance(self._built_object, (Iterator, AsyncIterator)): + if self.display_name in ["Text Output"]: + raise ValueError(f"You are trying to stream to a {self.display_name}. Try using a Chat Output instead.") + + def _reset(self, params_update: Optional[Dict[str, Any]] = None): + self._built = False + self._built_object = UnbuiltObject() + self._built_result = UnbuiltResult() + self.artifacts = {} + self.steps_ran = [] + self._build_params() + + def _is_chat_input(self): + return False + + def build_inactive(self): + # Just set the results to None + self._built = True + self._built_object = None + self._built_result = None + + async def build( + self, + user_id=None, + inputs: Optional[Dict[str, Any]] = None, + requester: Optional["Vertex"] = None, + **kwargs, + ) -> Any: + async with self._lock: + if self.state == VertexStates.INACTIVE: + # If the vertex is inactive, return None + self.build_inactive() + return + + if self.frozen and self._built: + return self.get_requester_result(requester) + elif self._built and requester is not None: + # This means that the vertex has already been built + # and we are just getting the result for the requester + return await self.get_requester_result(requester) + self._reset() + + if self._is_chat_input() and inputs: + inputs = {"input_value": inputs.get(INPUT_FIELD_NAME, "")} + self.update_raw_params(inputs, overwrite=True) + + # Run steps + for step in self.steps: + if step not in self.steps_ran: + if inspect.iscoroutinefunction(step): + await step(user_id=user_id, **kwargs) + else: + step(user_id=user_id, **kwargs) + self.steps_ran.append(step) + + self._finalize_build() + + return await self.get_requester_result(requester) + + async def get_requester_result(self, requester: Optional["Vertex"]): + # If the requester is None, this means that + # the Vertex is the root of the graph + if requester is None: + return self._built_object + + # Get the requester edge + requester_edge = next((edge for edge in self.edges if edge.target_id == requester.id), None) + # Return the result of the requester edge + return ( + None + if requester_edge is None + else await requester_edge.get_result_from_source(source=self, target=requester) + ) + + def add_edge(self, edge: "ContractEdge") -> None: + if edge not in self.edges: + self.edges.append(edge) + + def __repr__(self) -> str: + return f"Vertex(display_name={self.display_name}, id={self.id}, data={self.data})" + + def __eq__(self, __o: object) -> bool: + try: + if not isinstance(__o, Vertex): + return False + # We should create a more robust comparison + # for the Vertex class + ids_are_equal = self.id == __o.id + # self._data is a dict and we need to compare them + # to check if they are equal + data_are_equal = self.data == __o.data + return ids_are_equal and data_are_equal + except AttributeError: + return False + + def __hash__(self) -> int: + return id(self) + + def _built_object_repr(self): + # Add a message with an emoji, stars for sucess, + return "Built sucessfully ✨" if self._built_object is not None else "Failed to build 😵‍💫" diff --git a/src/backend/langflow/graph/vertex/constants.py b/src/backend/base/langflow/graph/vertex/constants.py similarity index 100% rename from src/backend/langflow/graph/vertex/constants.py rename to src/backend/base/langflow/graph/vertex/constants.py diff --git a/src/backend/base/langflow/graph/vertex/types.py b/src/backend/base/langflow/graph/vertex/types.py new file mode 100644 index 000000000..d7a98df8a --- /dev/null +++ b/src/backend/base/langflow/graph/vertex/types.py @@ -0,0 +1,491 @@ +import ast +import json +from typing import AsyncIterator, Callable, Dict, Iterator, List, Optional, Union +import yaml +from langchain_core.messages import AIMessage +from loguru import logger + +from langflow.graph.schema import InterfaceComponentTypes +from langflow.graph.utils import UnbuiltObject, flatten_list, serialize_field +from langflow.graph.vertex.base import Vertex +from langflow.interface.utils import extract_input_variables_from_prompt +from langflow.schema import Record +from langflow.schema.schema import INPUT_FIELD_NAME +from langflow.services.monitor.utils import log_vertex_build +from langflow.utils.schemas import ChatOutputResponse +from langflow.utils.util import unescape_string + + +class AgentVertex(Vertex): + def __init__(self, data: Dict, graph, params: Optional[Dict] = None): + super().__init__(data, graph=graph, base_type="agents", params=params) + + self.tools: List[Union[ToolkitVertex, ToolVertex]] = [] + self.chains: List[ChainVertex] = [] + self.steps: List[Callable] = [self._custom_build] + + def __getstate__(self): + state = super().__getstate__() + state["tools"] = self.tools + state["chains"] = self.chains + return state + + def __setstate__(self, state): + self.tools = state["tools"] + self.chains = state["chains"] + super().__setstate__(state) + + def _set_tools_and_chains(self) -> None: + for edge in self.edges: + if not hasattr(edge, "source"): + continue + source_node = edge.source + if isinstance(source_node, (ToolVertex, ToolkitVertex)): + self.tools.append(source_node) + elif isinstance(source_node, ChainVertex): + self.chains.append(source_node) + + async def _custom_build(self, *args, **kwargs): + user_id = kwargs.get("user_id", None) + self._set_tools_and_chains() + # First, build the tools + for tool_node in self.tools: + await tool_node.build(user_id=user_id) + + # Next, build the chains and the rest + for chain_node in self.chains: + await chain_node.build(tools=self.tools, user_id=user_id) + + await self._build(user_id=user_id) + + +class ToolVertex(Vertex): + def __init__(self, data: Dict, graph, params: Optional[Dict] = None): + super().__init__(data, graph=graph, base_type="tools", params=params) + + +class LLMVertex(Vertex): + built_node_type = None + class_built_object = None + + def __init__(self, data: Dict, graph, params: Optional[Dict] = None): + super().__init__(data, graph=graph, base_type="models", params=params) + self.steps: List[Callable] = [self._custom_build] + + async def _custom_build(self, *args, **kwargs): + # LLM is different because some models might take up too much memory + # or time to load. So we only load them when we need them. + # Avoid deepcopying the LLM + # that are loaded from a file + force = kwargs.get("force", False) + user_id = kwargs.get("user_id", None) + if self.vertex_type == self.built_node_type: + self._built_object = self.class_built_object + if not self._built or force: + await self._build(user_id=user_id) + self.built_node_type = self.vertex_type + self.class_built_object = self._built_object + + +class ToolkitVertex(Vertex): + def __init__(self, data: Dict, graph, params=None): + super().__init__(data, graph=graph, base_type="toolkits", params=params) + + +class FileToolVertex(ToolVertex): + def __init__(self, data: Dict, graph, params=None): + super().__init__( + data, + params=params, + graph=graph, + ) + + +class WrapperVertex(Vertex): + def __init__(self, data: Dict, graph, params=None): + super().__init__(data, graph=graph, base_type="wrappers") + self.steps: List[Callable] = [self._custom_build] + + async def _custom_build(self, *args, **kwargs): + force = kwargs.get("force", False) + user_id = kwargs.get("user_id", None) + if not self._built or force: + if "headers" in self.params: + self.params["headers"] = ast.literal_eval(self.params["headers"]) + await self._build(user_id=user_id) + + +class DocumentLoaderVertex(Vertex): + def __init__(self, data: Dict, graph, params: Optional[Dict] = None): + super().__init__(data, graph=graph, base_type="documentloaders", params=params) + + def _built_object_repr(self): + # This built_object is a list of documents. Maybe we should + # show how many documents are in the list? + + if not isinstance(self._built_object, UnbuiltObject): + avg_length = sum(len(record.get_text()) for record in self._built_object if hasattr(record, "text")) / len( + self._built_object + ) + return f"""{self.display_name}({len(self._built_object)} records) + \nAvg. Record Length (characters): {int(avg_length)} + Records: {self._built_object[:3]}...""" + return f"{self.vertex_type}()" + + +class EmbeddingVertex(Vertex): + def __init__(self, data: Dict, graph, params: Optional[Dict] = None): + super().__init__(data, graph=graph, base_type="embeddings", params=params) + + +class VectorStoreVertex(Vertex): + def __init__(self, data: Dict, graph, params=None): + super().__init__(data, graph=graph, base_type="vectorstores") + + self.params = params or {} + + # VectorStores may contain databse connections + # so we need to define the __reduce__ method and the __setstate__ method + # to avoid pickling errors + def clean_edges_for_pickling(self): + # for each edge that has self as source + # we need to clear the _built_object of the target + # so that we don't try to pickle a database connection + for edge in self.edges: + if edge.source == self: + edge.target._built_object = None + edge.target._built = False + edge.target.params[edge.target_param] = self + + def remove_docs_and_texts_from_params(self): + # remove documents and texts from params + # so that we don't try to pickle a database connection + self.params.pop("documents", None) + self.params.pop("texts", None) + + def __getstate__(self): + # We want to save the params attribute + # and if "documents" or "texts" are in the params + # we want to remove them because they have already + # been processed. + params = self.params.copy() + params.pop("documents", None) + params.pop("texts", None) + self.clean_edges_for_pickling() + + return super().__getstate__() + + def __setstate__(self, state): + super().__setstate__(state) + self.remove_docs_and_texts_from_params() + + +class MemoryVertex(Vertex): + def __init__(self, data: Dict, graph): + super().__init__(data, graph=graph, base_type="memory") + + +class RetrieverVertex(Vertex): + def __init__(self, data: Dict, graph): + super().__init__(data, graph=graph, base_type="retrievers") + + +class TextSplitterVertex(Vertex): + def __init__(self, data: Dict, graph, params: Optional[Dict] = None): + super().__init__(data, graph=graph, base_type="textsplitters", params=params) + + def _built_object_repr(self): + # This built_object is a list of documents. Maybe we should + # show how many documents are in the list? + + if not isinstance(self._built_object, UnbuiltObject): + avg_length = sum(len(doc.page_content) for doc in self._built_object) / len(self._built_object) + return f"""{self.vertex_type}({len(self._built_object)} documents) + \nAvg. Document Length (characters): {int(avg_length)} + \nDocuments: {self._built_object[:3]}...""" + return f"{self.vertex_type}()" + + +class ChainVertex(Vertex): + def __init__(self, data: Dict, graph): + super().__init__(data, graph=graph, base_type="chains") + self.steps = [self._custom_build] + + async def _custom_build(self, *args, **kwargs): + force = kwargs.get("force", False) + user_id = kwargs.get("user_id", None) + # Remove this once LLMChain is CustomComponent + self.params.pop("code", None) + for key, value in self.params.items(): + if isinstance(value, PromptVertex): + # Build the PromptVertex, passing the tools if available + tools = kwargs.get("tools", None) + self.params[key] = value.build(tools=tools, frozen=force) + + await self._build(user_id=user_id) + + def set_artifacts(self) -> None: + if isinstance(self._built_object, UnbuiltObject): + return + if self._built_object and hasattr(self._built_object, "input_keys"): + self.artifacts = dict(input_keys=self._built_object.input_keys) + + def _built_object_repr(self): + if isinstance(self._built_object, str): + return self._built_object + return super()._built_object_repr() + + +class PromptVertex(Vertex): + def __init__(self, data: Dict, graph): + super().__init__(data, graph=graph, base_type="prompts") + self.steps: List[Callable] = [self._custom_build] + + async def _custom_build(self, *args, **kwargs): + force = kwargs.get("force", False) + user_id = kwargs.get("user_id", None) + tools = kwargs.get("tools", []) + if not self._built or force: + if "input_variables" not in self.params or self.params["input_variables"] is None: + self.params["input_variables"] = [] + # Check if it is a ZeroShotPrompt and needs a tool + if "ShotPrompt" in self.vertex_type: + tools = [tool_node.build(user_id=user_id) for tool_node in tools] if tools is not None else [] + # flatten the list of tools if it is a list of lists + # first check if it is a list + if tools and isinstance(tools, list) and isinstance(tools[0], list): + tools = flatten_list(tools) + self.params["tools"] = tools + prompt_params = [ + key for key, value in self.params.items() if isinstance(value, str) and key != "format_instructions" + ] + else: + prompt_params = ["template"] + + if "prompt" not in self.params and "messages" not in self.params: + for param in prompt_params: + prompt_text = self.params[param] + variables = extract_input_variables_from_prompt(prompt_text) + self.params["input_variables"].extend(variables) + self.params["input_variables"] = list(set(self.params["input_variables"])) + elif isinstance(self.params, dict): + self.params.pop("input_variables", None) + + await self._build(user_id=user_id) + + def _built_object_repr(self): + if not self.artifacts or self._built_object is None or not hasattr(self._built_object, "format"): + return super()._built_object_repr() + elif isinstance(self._built_object, UnbuiltObject): + return super()._built_object_repr() + # We'll build the prompt with the artifacts + # to show the user what the prompt looks like + # with the variables filled in + artifacts = self.artifacts.copy() + # Remove the handle_keys from the artifacts + # so the prompt format doesn't break + artifacts.pop("handle_keys", None) + try: + if not hasattr(self._built_object, "template") and hasattr(self._built_object, "prompt"): + template = self._built_object.prompt.template + else: + template = self._built_object.template + for key, value in artifacts.items(): + if value: + replace_key = "{" + key + "}" + template = template.replace(replace_key, value) + return template if isinstance(template, str) else f"{self.vertex_type}({template})" + except KeyError: + return str(self._built_object) + + +class OutputParserVertex(Vertex): + def __init__(self, data: Dict, graph): + super().__init__(data, graph=graph, base_type="output_parsers") + + +class CustomComponentVertex(Vertex): + def __init__(self, data: Dict, graph): + super().__init__(data, graph=graph, base_type="custom_components") + + def _built_object_repr(self): + if self.artifacts and "repr" in self.artifacts: + return self.artifacts["repr"] or super()._built_object_repr() + + +class ChatVertex(Vertex): + def __init__(self, data: Dict, graph): + super().__init__(data, graph=graph, base_type="custom_components", is_task=True) + self.steps = [self._build, self._run] + + def build_stream_url(self): + return f"/api/v1/build/{self.graph.flow_id}/{self.id}/stream" + + def _built_object_repr(self): + if self.task_id and self.is_task: + if task := self.get_task(): + return str(task.info) + else: + return f"Task {self.task_id} is not running" + if self.artifacts: + # dump as a yaml string + artifacts = {k.title().replace("_", " "): v for k, v in self.artifacts.items() if v is not None} + yaml_str = yaml.dump(artifacts, default_flow_style=False, allow_unicode=True) + return yaml_str + return super()._built_object_repr() + + async def _run(self, *args, **kwargs): + if self.is_interface_component: + if self.vertex_type in ["ChatOutput", "ChatInput"]: + artifacts = None + sender = self.params.get("sender", None) + sender_name = self.params.get("sender_name", None) + message = self.params.get(INPUT_FIELD_NAME, None) + if isinstance(message, str): + message = unescape_string(message) + stream_url = None + if isinstance(self._built_object, AIMessage): + artifacts = ChatOutputResponse.from_message( + self._built_object, + sender=sender, + sender_name=sender_name, + ) + elif not isinstance(self._built_object, UnbuiltObject): + if isinstance(self._built_object, dict): + # Turn the dict into a pleasing to + # read JSON inside a code block + message = dict_to_codeblock(self._built_object) + elif isinstance(self._built_object, Record): + message = self._built_object.text + elif isinstance(message, (AsyncIterator, Iterator)): + stream_url = self.build_stream_url() + message = "" + elif not isinstance(self._built_object, str): + message = str(self._built_object) + # if the message is a generator or iterator + # it means that it is a stream of messages + else: + message = self._built_object + + artifacts = ChatOutputResponse( + message=message, + sender=sender, + sender_name=sender_name, + stream_url=stream_url, + ) + + self.will_stream = stream_url is not None + if artifacts: + self.artifacts = artifacts.model_dump(exclude_none=True) + if isinstance(self._built_object, (AsyncIterator, Iterator)): + if self.params["return_record"]: + self._built_object = Record(text=message, data=self.artifacts) + else: + self._built_object = message + self._built_result = self._built_object + + else: + await super()._run(*args, **kwargs) + + async def stream(self): + iterator = self.params.get(INPUT_FIELD_NAME, None) + if not isinstance(iterator, (AsyncIterator, Iterator)): + raise ValueError("The message must be an iterator or an async iterator.") + is_async = isinstance(iterator, AsyncIterator) + complete_message = "" + if is_async: + async for message in iterator: + message = message.content if hasattr(message, "content") else message + message = message.text if hasattr(message, "text") else message + yield message + complete_message += message + else: + for message in iterator: + message = message.content if hasattr(message, "content") else message + message = message.text if hasattr(message, "text") else message + yield message + complete_message += message + self.artifacts = ChatOutputResponse( + message=complete_message, + sender=self.params.get("sender", ""), + sender_name=self.params.get("sender_name", ""), + ).model_dump() + self.params[INPUT_FIELD_NAME] = complete_message + self._built_object = Record(text=complete_message, data=self.artifacts) + self._built_result = complete_message + # Update artifacts with the message + # and remove the stream_url + self._finalize_build() + logger.debug(f"Streamed message: {complete_message}") + + await log_vertex_build( + flow_id=self.graph.flow_id, + vertex_id=self.id, + valid=True, + params=self._built_object_repr(), + data=self.result, + artifacts=self.artifacts, + ) + + self._validate_built_object() + self._built = True + + async def consume_async_generator(self): + async for _ in self.stream(): + pass + + def _is_chat_input(self): + return self.vertex_type == InterfaceComponentTypes.ChatInput and self.is_input + + +class RoutingVertex(Vertex): + def __init__(self, data: Dict, graph): + super().__init__(data, graph=graph, base_type="custom_components") + self.use_result = True + self.steps = [self._build] + + def _built_object_repr(self): + if self.artifacts and "repr" in self.artifacts: + return self.artifacts["repr"] or super()._built_object_repr() + return super()._built_object_repr() + + @property + def successors_ids(self): + if isinstance(self._built_object, bool): + ids = super().successors_ids + if self._built_object: + return ids + return [] + raise ValueError("RoutingVertex should return a boolean value.") + + def _run(self, *args, **kwargs): + if self._built_object: + condition = self._built_object.get("condition") + result = self._built_object.get("result") + if condition is None: + raise ValueError("Condition is required for the routing vertex.") + if result is None: + raise ValueError("Result is required for the routing vertex.") + if condition is True: + self._built_result = result + else: + self.graph.mark_branch(self.id, "INACTIVE") + self._built_result = None + + +class StateVertex(Vertex): + def __init__(self, data: Dict, graph): + super().__init__(data, graph=graph, base_type="custom_components") + self.steps = [self._build] + self.is_state = True + + @property + def successors_ids(self) -> List[str]: + successors = self.graph.successor_map.get(self.id, []) + return successors + self.graph.activated_vertices + + +def dict_to_codeblock(d: dict) -> str: + serialized = {key: serialize_field(val) for key, val in d.items()} + json_str = json.dumps(serialized, indent=4) + return f"```json\n{json_str}\n```" diff --git a/src/backend/base/langflow/graph/vertex/utils.py b/src/backend/base/langflow/graph/vertex/utils.py new file mode 100644 index 000000000..ea2693e29 --- /dev/null +++ b/src/backend/base/langflow/graph/vertex/utils.py @@ -0,0 +1,65 @@ +from typing import Any, Optional, Union + +from langchain_core.messages import BaseMessage +from langchain_core.runnables import Runnable +from loguru import logger + +from langflow.utils.constants import PYTHON_BASIC_TYPES + + +def is_basic_type(obj): + return type(obj) in PYTHON_BASIC_TYPES + + +async def invoke_lc_runnable( + built_object: Runnable, inputs: dict, has_external_output: bool, session_id: Optional[str] = None, **kwargs +) -> Union[str, BaseMessage]: + # Setup callbacks for asynchronous execution + from langflow.processing.base import setup_callbacks + + callbacks = setup_callbacks(sync=False, trace_id=session_id, **kwargs) + + try: + if has_external_output and hasattr(built_object, "astream"): + # Asynchronous stream handling if supported and required + output = "" + async for chunk in built_object.astream(inputs, {"callbacks": callbacks}): + output += chunk + return output + else: + # Direct asynchronous invocation + return await built_object.ainvoke(inputs, {"callbacks": callbacks}) + except Exception as async_exc: + logger.debug(f"Async error, falling back to sync: {str(async_exc)}") + + # Setup synchronous callbacks for the fallback + sync_callbacks = setup_callbacks(sync=True, trace_id=session_id, **kwargs) + try: + # Synchronous fallback if asynchronous execution fails + if has_external_output and hasattr(built_object, "stream"): + # Synchronous stream handling if supported and required + output = "" + for chunk in built_object.stream(inputs, {"callbacks": sync_callbacks}): + output += chunk + return output + else: + # Direct synchronous invocation + return built_object.invoke(inputs, {"callbacks": sync_callbacks}) + except Exception as sync_exc: + logger.error(f"Sync error after async failure: {str(sync_exc)}") + # Handle or re-raise exception as appropriate for your application + raise sync_exc from async_exc + + +async def generate_result(built_object: Any, inputs: dict, has_external_output: bool, session_id: Optional[str] = None): + # If the built_object is instance of Runnable + # we can call `invoke` or `stream` on it + # if it has_external_outputl, we need to call `stream` if it has it + # if not, we call `invoke` if it has it + if isinstance(built_object, Runnable): + result = await invoke_lc_runnable( + built_object=built_object, inputs=inputs, has_external_output=has_external_output, session_id=session_id + ) + else: + result = built_object + return result diff --git a/src/backend/base/langflow/helpers/__init__.py b/src/backend/base/langflow/helpers/__init__.py new file mode 100644 index 000000000..adfa72088 --- /dev/null +++ b/src/backend/base/langflow/helpers/__init__.py @@ -0,0 +1,3 @@ +from .record import docs_to_records, records_to_text + +__all__ = ["docs_to_records", "records_to_text"] diff --git a/src/backend/base/langflow/helpers/flow.py b/src/backend/base/langflow/helpers/flow.py new file mode 100644 index 000000000..654122dcd --- /dev/null +++ b/src/backend/base/langflow/helpers/flow.py @@ -0,0 +1,201 @@ +from typing import TYPE_CHECKING, Any, Callable, Coroutine, List, Optional, Tuple, Type, Union, cast + +from pydantic.v1 import BaseModel, Field, create_model +from sqlmodel import select + +from langflow.schema.schema import INPUT_FIELD_NAME, Record +from langflow.services.database.models.flow.model import Flow +from langflow.services.deps import session_scope + +if TYPE_CHECKING: + from langflow.graph.graph.base import Graph + from langflow.graph.vertex.base import Vertex + +INPUT_TYPE_MAP = { + "ChatInput": {"type_hint": "Optional[str]", "default": '""'}, + "TextInput": {"type_hint": "Optional[str]", "default": '""'}, + "JSONInput": {"type_hint": "Optional[dict]", "default": "{}"}, +} + + +def list_flows(*, user_id: Optional[str] = None) -> List[Record]: + if not user_id: + raise ValueError("Session is invalid") + try: + with session_scope() as session: + flows = session.exec( + select(Flow).where(Flow.user_id == user_id).where(Flow.is_component == False) # noqa + ).all() + + flows_records = [flow.to_record() for flow in flows] + return flows_records + except Exception as e: + raise ValueError(f"Error listing flows: {e}") + + +async def load_flow( + user_id: str, flow_id: Optional[str] = None, flow_name: Optional[str] = None, tweaks: Optional[dict] = None +) -> "Graph": + from langflow.graph.graph.base import Graph + from langflow.processing.process import process_tweaks + + if not flow_id and not flow_name: + raise ValueError("Flow ID or Flow Name is required") + if not flow_id and flow_name: + flow_id = find_flow(flow_name, user_id) + if not flow_id: + raise ValueError(f"Flow {flow_name} not found") + + with session_scope() as session: + graph_data = flow.data if (flow := session.get(Flow, flow_id)) else None + if not graph_data: + raise ValueError(f"Flow {flow_id} not found") + if tweaks: + graph_data = process_tweaks(graph_data=graph_data, tweaks=tweaks) + graph = Graph.from_payload(graph_data, flow_id=flow_id) + return graph + + +def find_flow(flow_name: str, user_id: str) -> Optional[str]: + with session_scope() as session: + flow = session.exec(select(Flow).where(Flow.name == flow_name).where(Flow.user_id == user_id)).first() + return flow.id if flow else None + + +async def run_flow( + inputs: Optional[Union[dict, List[dict]]] = None, + tweaks: Optional[dict] = None, + flow_id: Optional[str] = None, + flow_name: Optional[str] = None, + user_id: Optional[str] = None, +) -> Any: + if user_id is None: + raise ValueError("Session is invalid") + graph = await load_flow(user_id, flow_id, flow_name, tweaks) + + if inputs is None: + inputs = [] + inputs_list = [] + inputs_components = [] + types = [] + for input_dict in inputs: + inputs_list.append({INPUT_FIELD_NAME: cast(str, input_dict.get("input_value"))}) + inputs_components.append(input_dict.get("components", [])) + types.append(input_dict.get("type", [])) + + return await graph.arun(inputs_list, inputs_components=inputs_components, types=types) + + +def generate_function_for_flow(inputs: List["Vertex"], flow_id: str) -> Coroutine: + """ + Generate a dynamic flow function based on the given inputs and flow ID. + + Args: + inputs (List[Vertex]): The list of input vertices for the flow. + flow_id (str): The ID of the flow. + + Returns: + Coroutine: The dynamic flow function. + + Raises: + None + + Example: + inputs = [vertex1, vertex2] + flow_id = "my_flow" + function = generate_function_for_flow(inputs, flow_id) + result = function(input1, input2) + """ + # Prepare function arguments with type hints and default values + args = [ + f"{input_.display_name.lower().replace(' ', '_')}: {INPUT_TYPE_MAP[input_.base_name]['type_hint']} = {INPUT_TYPE_MAP[input_.base_name]['default']}" + for input_ in inputs + ] + + # Maintain original argument names for constructing the tweaks dictionary + original_arg_names = [input_.display_name for input_ in inputs] + + # Prepare a Pythonic, valid function argument string + func_args = ", ".join(args) + + # Map original argument names to their corresponding Pythonic variable names in the function + arg_mappings = ", ".join( + f'"{original_name}": {name}' + for original_name, name in zip(original_arg_names, [arg.split(":")[0] for arg in args]) + ) + + func_body = f""" +from typing import Optional +async def flow_function({func_args}): + tweaks = {{ {arg_mappings} }} + from langflow.helpers.flow import run_flow + from langchain_core.tools import ToolException + try: + return await run_flow( + tweaks={{key: {{'input_value': value}} for key, value in tweaks.items()}}, + flow_id="{flow_id}", + ) + except Exception as e: + raise ToolException(f'Error running flow: ' + e) +""" + + compiled_func = compile(func_body, "", "exec") + local_scope: dict = {} + exec(compiled_func, globals(), local_scope) + return local_scope["flow_function"] + + +def build_function_and_schema(flow_record: Record, graph: "Graph") -> Tuple[Callable, Type[BaseModel]]: + """ + Builds a dynamic function and schema for a given flow. + + Args: + flow_record (Record): The flow record containing information about the flow. + graph (Graph): The graph representing the flow. + + Returns: + Tuple[Callable, BaseModel]: A tuple containing the dynamic function and the schema. + """ + flow_id = flow_record.id + inputs = get_flow_inputs(graph) + dynamic_flow_function = generate_function_for_flow(inputs, flow_id) + schema = build_schema_from_inputs(flow_record.name, inputs) + return dynamic_flow_function, schema + + +def get_flow_inputs(graph: "Graph") -> List["Vertex"]: + """ + Retrieves the flow inputs from the given graph. + + Args: + graph (Graph): The graph object representing the flow. + + Returns: + List[Record]: A list of input records, where each record contains the ID, name, and description of the input vertex. + """ + inputs = [] + for vertex in graph.vertices: + if vertex.is_input: + inputs.append(vertex) + return inputs + + +def build_schema_from_inputs(name: str, inputs: List["Vertex"]) -> Type[BaseModel]: + """ + Builds a schema from the given inputs. + + Args: + name (str): The name of the schema. + inputs (List[tuple[str, str, str]]): A list of tuples representing the inputs. + Each tuple contains three elements: the input name, the input type, and the input description. + + Returns: + BaseModel: The schema model. + + """ + fields = {} + for input_ in inputs: + field_name = input_.display_name.lower().replace(" ", "_") + description = input_.description + fields[field_name] = (str, Field(default="", description=description)) + return create_model(name, **fields) # type: ignore diff --git a/src/backend/base/langflow/helpers/record.py b/src/backend/base/langflow/helpers/record.py new file mode 100644 index 000000000..7c13a9ad4 --- /dev/null +++ b/src/backend/base/langflow/helpers/record.py @@ -0,0 +1,41 @@ +from typing import Union +from langchain_core.documents import Document + +from langflow.schema import Record + + +def docs_to_records(documents: list[Document]) -> list[Record]: + """ + Converts a list of Documents to a list of Records. + + Args: + documents (list[Document]): The list of Documents to convert. + + Returns: + list[Record]: The converted list of Records. + """ + return [Record.from_document(document) for document in documents] + + +def records_to_text(template: str, records: Union[Record, list[Record]]) -> str: + """ + Converts a list of Records to a list of texts. + + Args: + records (list[Record]): The list of Records to convert. + + Returns: + list[str]: The converted list of texts. + """ + if isinstance(records, Record): + records = [records] + # Check if there are any format strings in the template + _records = [] + for record in records: + # If it is not a record, create one with the key "text" + if not isinstance(record, Record): + record = Record(text=record) + _records.append(record) + + formated_records = [template.format(data=record.data, **record.data) for record in _records] + return "\n".join(formated_records) diff --git a/src/backend/langflow/services/credentials/__init__.py b/src/backend/base/langflow/initial_setup/__init__.py similarity index 100% rename from src/backend/langflow/services/credentials/__init__.py rename to src/backend/base/langflow/initial_setup/__init__.py diff --git a/src/backend/base/langflow/initial_setup/setup.py b/src/backend/base/langflow/initial_setup/setup.py new file mode 100644 index 000000000..f2181f85e --- /dev/null +++ b/src/backend/base/langflow/initial_setup/setup.py @@ -0,0 +1,239 @@ +from collections import defaultdict +from copy import deepcopy +from datetime import datetime, timezone +from pathlib import Path + +import orjson +from emoji import demojize, purely_emoji # type: ignore +from loguru import logger +from sqlmodel import select + +from langflow.base.constants import FIELD_FORMAT_ATTRIBUTES, NODE_FORMAT_ATTRIBUTES +from langflow.interface.types import get_all_components +from langflow.services.database.models.flow.model import Flow, FlowCreate +from langflow.services.deps import get_settings_service, session_scope + +STARTER_FOLDER_NAME = "Starter Projects" + + +# In the folder ./starter_projects we have a few JSON files that represent +# starter projects. We want to load these into the database so that users +# can use them as a starting point for their own projects. + + +def update_projects_components_with_latest_component_versions(project_data, all_types_dict): + # project data has a nodes key, which is a list of nodes + # we want to run through each node and see if it exists in the all_types_dict + # if so, we go into the template key and also get the template from all_types_dict + # and update it all + node_changes_log = defaultdict(list) + project_data_copy = deepcopy(project_data) + for node in project_data_copy.get("nodes", []): + node_data = node.get("data").get("node") + if node_data.get("display_name") in all_types_dict: + latest_node = all_types_dict.get(node_data.get("display_name")) + latest_template = latest_node.get("template") + node_data["template"]["code"] = latest_template["code"] + + for attr in NODE_FORMAT_ATTRIBUTES: + if attr in latest_node: + # Check if it needs to be updated + if latest_node[attr] != node_data.get(attr): + node_changes_log[node_data["display_name"]].append( + { + "attr": attr, + "old_value": node_data.get(attr), + "new_value": latest_node[attr], + } + ) + node_data[attr] = latest_node[attr] + + for field_name, field_dict in latest_template.items(): + if field_name not in node_data["template"]: + continue + # The idea here is to update some attributes of the field + for attr in FIELD_FORMAT_ATTRIBUTES: + if attr in field_dict and attr in node_data["template"].get(field_name): + # Check if it needs to be updated + if field_dict[attr] != node_data["template"][field_name][attr]: + node_changes_log[node_data["display_name"]].append( + { + "attr": f"{field_name}.{attr}", + "old_value": node_data["template"][field_name][attr], + "new_value": field_dict[attr], + } + ) + node_data["template"][field_name][attr] = field_dict[attr] + log_node_changes(node_changes_log) + return project_data_copy + + +def log_node_changes(node_changes_log): + # The idea here is to log the changes that were made to the nodes in debug + # Something like: + # Node: "Node Name" was updated with the following changes: + # attr_name: old_value -> new_value + # let's create one log per node + formatted_messages = [] + for node_name, changes in node_changes_log.items(): + message = f"\nNode: {node_name} was updated with the following changes:" + for change in changes: + message += f"\n- {change['attr']}: {change['old_value']} -> {change['new_value']}" + formatted_messages.append(message) + if formatted_messages: + logger.debug("\n".join(formatted_messages)) + + +def load_starter_projects(): + starter_projects = [] + folder = Path(__file__).parent / "starter_projects" + for file in folder.glob("*.json"): + project = orjson.loads(file.read_text(encoding="utf-8")) + starter_projects.append((file, project)) + logger.info(f"Loaded starter project {file}") + return starter_projects + + +def get_project_data(project): + project_name = project.get("name") + project_description = project.get("description") + project_is_component = project.get("is_component") + project_updated_at = project.get("updated_at") + if not project_updated_at: + project_updated_at = datetime.now(tz=timezone.utc).isoformat() + updated_at_datetime = datetime.strptime(project_updated_at, "%Y-%m-%dT%H:%M:%S.%f%z") + else: + updated_at_datetime = datetime.strptime(project_updated_at, "%Y-%m-%dT%H:%M:%S.%f") + project_data = project.get("data") + project_icon = project.get("icon") + if project_icon and purely_emoji(project_icon): + project_icon = demojize(project_icon) + else: + project_icon = "" + project_icon_bg_color = project.get("icon_bg_color") + return ( + project_name, + project_description, + project_is_component, + updated_at_datetime, + project_data, + project_icon, + project_icon_bg_color, + ) + + +def update_project_file(project_path, project, updated_project_data): + project["data"] = updated_project_data + with open(project_path, "w", encoding="utf-8") as f: + f.write(orjson.dumps(project, option=orjson.OPT_INDENT_2).decode()) + logger.info(f"Updated starter project {project['name']} file") + + +def update_existing_project( + existing_project, + project_name, + project_description, + project_is_component, + updated_at_datetime, + project_data, + project_icon, + project_icon_bg_color, +): + logger.info(f"Updating starter project {project_name}") + existing_project.data = project_data + existing_project.folder = STARTER_FOLDER_NAME + existing_project.description = project_description + existing_project.is_component = project_is_component + existing_project.updated_at = updated_at_datetime + existing_project.icon = project_icon + existing_project.icon_bg_color = project_icon_bg_color + + +def create_new_project( + session, + project_name, + project_description, + project_is_component, + updated_at_datetime, + project_data, + project_icon, + project_icon_bg_color, +): + logger.debug(f"Creating starter project {project_name}") + new_project = FlowCreate( + name=project_name, + description=project_description, + icon=project_icon, + icon_bg_color=project_icon_bg_color, + data=project_data, + is_component=project_is_component, + updated_at=updated_at_datetime, + folder=STARTER_FOLDER_NAME, + ) + db_flow = Flow.model_validate(new_project, from_attributes=True) + session.add(db_flow) + + +def get_all_flows_similar_to_project(session, project_name): + flows = session.exec( + select(Flow).where( + Flow.name == project_name, + Flow.folder == STARTER_FOLDER_NAME, + ) + ).all() + return flows + + +def delete_start_projects(session): + flows = session.exec( + select(Flow).where( + Flow.folder == STARTER_FOLDER_NAME, + ) + ).all() + for flow in flows: + session.delete(flow) + session.commit() + + +def create_or_update_starter_projects(): + components_paths = get_settings_service().settings.COMPONENTS_PATH + try: + all_types_dict = get_all_components(components_paths, as_dict=True) + except Exception as e: + logger.exception(f"Error loading components: {e}") + raise e + with session_scope() as session: + starter_projects = load_starter_projects() + delete_start_projects(session) + for project_path, project in starter_projects: + ( + project_name, + project_description, + project_is_component, + updated_at_datetime, + project_data, + project_icon, + project_icon_bg_color, + ) = get_project_data(project) + updated_project_data = update_projects_components_with_latest_component_versions( + project_data, all_types_dict + ) + if updated_project_data != project_data: + project_data = updated_project_data + # We also need to update the project data in the file + + update_project_file(project_path, project, updated_project_data) + if project_name and project_data: + for existing_project in get_all_flows_similar_to_project(session, project_name): + session.delete(existing_project) + + create_new_project( + session, + project_name, + project_description, + project_is_component, + updated_at_datetime, + project_data, + project_icon, + project_icon_bg_color, + ) diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Basic Prompting (Hello, world!).json b/src/backend/base/langflow/initial_setup/starter_projects/Basic Prompting (Hello, world!).json new file mode 100644 index 000000000..ca465fc23 --- /dev/null +++ b/src/backend/base/langflow/initial_setup/starter_projects/Basic Prompting (Hello, world!).json @@ -0,0 +1,888 @@ +{ + "id": "c091a57f-43a7-4a5e-b352-035ae8d8379c", + "data": { + "nodes": [ + { + "id": "Prompt-uxBqP", + "type": "genericNode", + "position": { + "x": 53.588791333410654, + "y": -107.07318910019967 + }, + "data": { + "type": "Prompt", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from langchain_core.prompts import PromptTemplate\n\nfrom langflow.field_typing import Prompt, TemplateField, Text\nfrom langflow.interface.custom.custom_component import CustomComponent\n\n\nclass PromptComponent(CustomComponent):\n display_name: str = \"Prompt\"\n description: str = \"Create a prompt template with dynamic variables.\"\n icon = \"prompts\"\n\n def build_config(self):\n return {\n \"template\": TemplateField(display_name=\"Template\"),\n \"code\": TemplateField(advanced=True),\n }\n\n def build(\n self,\n template: Prompt,\n **kwargs,\n ) -> Text:\n from langflow.base.prompts.utils import dict_values_to_string\n\n prompt_template = PromptTemplate.from_template(Text(template))\n kwargs = dict_values_to_string(kwargs)\n kwargs = {k: \"\\n\".join(v) if isinstance(v, list) else v for k, v in kwargs.items()}\n try:\n formated_prompt = prompt_template.format(**kwargs)\n except Exception as exc:\n raise ValueError(f\"Error formatting prompt: {exc}\") from exc\n self.status = f'Prompt:\\n\"{formated_prompt}\"'\n return formated_prompt\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "template": { + "type": "prompt", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "Answer the user as if you were a pirate.\n\nUser: {user_input}\n\nAnswer: ", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "template", + "display_name": "Template", + "advanced": false, + "input_types": [ + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "_type": "CustomComponent", + "user_input": { + "field_type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "user_input", + "display_name": "user_input", + "advanced": false, + "input_types": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "type": "str" + } + }, + "description": "Create a prompt template with dynamic variables.", + "icon": "prompts", + "is_input": null, + "is_output": null, + "is_composition": null, + "base_classes": [ + "object", + "str", + "Text" + ], + "name": "", + "display_name": "Prompt", + "documentation": "", + "custom_fields": { + "template": [ + "user_input" + ] + }, + "output_types": [ + "Text" + ], + "full_path": null, + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false, + "error": null + }, + "id": "Prompt-uxBqP", + "description": "Create a prompt template with dynamic variables.", + "display_name": "Prompt" + }, + "selected": true, + "width": 384, + "height": 383, + "dragging": false, + "positionAbsolute": { + "x": 53.588791333410654, + "y": -107.07318910019967 + } + }, + { + "id": "OpenAIModel-k39HS", + "type": "genericNode", + "position": { + "x": 634.8148772766217, + "y": 27.035057029045305 + }, + "data": { + "type": "OpenAIModel", + "node": { + "template": { + "input_value": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Input", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional\n\nfrom langchain_openai import ChatOpenAI\n\nfrom langflow.base.constants import STREAM_INFO_TEXT\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.field_typing import NestedDict, Text\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n\n field_order = [\n \"max_tokens\",\n \"model_kwargs\",\n \"model_name\",\n \"openai_api_base\",\n \"openai_api_key\",\n \"temperature\",\n \"input_value\",\n \"system_message\",\n \"stream\",\n ]\n\n def build_config(self):\n return {\n \"input_value\": {\"display_name\": \"Input\"},\n \"max_tokens\": {\n \"display_name\": \"Max Tokens\",\n \"advanced\": True,\n },\n \"model_kwargs\": {\n \"display_name\": \"Model Kwargs\",\n \"advanced\": True,\n },\n \"model_name\": {\n \"display_name\": \"Model Name\",\n \"advanced\": False,\n \"options\": [\n \"gpt-4-turbo-preview\",\n \"gpt-3.5-turbo\",\n \"gpt-4-0125-preview\",\n \"gpt-4-1106-preview\",\n \"gpt-4-vision-preview\",\n \"gpt-3.5-turbo-0125\",\n \"gpt-3.5-turbo-1106\",\n ],\n \"value\": \"gpt-4-turbo-preview\",\n },\n \"openai_api_base\": {\n \"display_name\": \"OpenAI API Base\",\n \"advanced\": True,\n \"info\": (\n \"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\n\"\n \"You can change this to use other APIs like JinaChat, LocalAI and Prem.\"\n ),\n },\n \"openai_api_key\": {\n \"display_name\": \"OpenAI API Key\",\n \"info\": \"The OpenAI API Key to use for the OpenAI model.\",\n \"advanced\": False,\n \"password\": True,\n },\n \"temperature\": {\n \"display_name\": \"Temperature\",\n \"advanced\": False,\n \"value\": 0.1,\n },\n \"stream\": {\n \"display_name\": \"Stream\",\n \"info\": STREAM_INFO_TEXT,\n \"advanced\": True,\n },\n \"system_message\": {\n \"display_name\": \"System Message\",\n \"info\": \"System message to pass to the model.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n input_value: Text,\n openai_api_key: str,\n temperature: float,\n model_name: str,\n max_tokens: Optional[int] = 256,\n model_kwargs: NestedDict = {},\n openai_api_base: Optional[str] = None,\n stream: bool = False,\n system_message: Optional[str] = None,\n ) -> Text:\n if not openai_api_base:\n openai_api_base = \"https://api.openai.com/v1\"\n output = ChatOpenAI(\n max_tokens=max_tokens,\n model_kwargs=model_kwargs,\n model=model_name,\n base_url=openai_api_base,\n api_key=openai_api_key,\n temperature=temperature,\n )\n\n return self.get_chat_result(output, stream, input_value, system_message)\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "max_tokens": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 256, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "max_tokens", + "display_name": "Max Tokens", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "model_kwargs": { + "type": "NestedDict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": {}, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "model_kwargs", + "display_name": "Model Kwargs", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "model_name": { + "type": "str", + "required": true, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "gpt-3.5-turbo", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "gpt-4-turbo-preview", + "gpt-3.5-turbo", + "gpt-4-0125-preview", + "gpt-4-1106-preview", + "gpt-4-vision-preview", + "gpt-3.5-turbo-0125", + "gpt-3.5-turbo-1106" + ], + "name": "model_name", + "display_name": "Model Name", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_api_base": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "openai_api_base", + "display_name": "OpenAI API Base", + "advanced": true, + "dynamic": false, + "info": "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_api_key": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": true, + "name": "openai_api_key", + "display_name": "OpenAI API Key", + "advanced": false, + "dynamic": false, + "info": "The OpenAI API Key to use for the OpenAI model.", + "load_from_db": true, + "title_case": false, + "input_types": [ + "Text" + ], + "value": "" + }, + "stream": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": true, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "stream", + "display_name": "Stream", + "advanced": true, + "dynamic": false, + "info": "Stream the response from the model. Streaming works only in Chat.", + "load_from_db": false, + "title_case": false + }, + "system_message": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "system_message", + "display_name": "System Message", + "advanced": true, + "dynamic": false, + "info": "System message to pass to the model.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "temperature": { + "type": "float", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 0.1, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "temperature", + "display_name": "Temperature", + "advanced": false, + "dynamic": false, + "info": "", + "rangeSpec": { + "step_type": "float", + "min": -1, + "max": 1, + "step": 0.1 + }, + "load_from_db": false, + "title_case": false + }, + "_type": "CustomComponent" + }, + "description": "Generates text using OpenAI LLMs.", + "icon": "OpenAI", + "base_classes": [ + "object", + "Text", + "str" + ], + "display_name": "OpenAI", + "documentation": "", + "custom_fields": { + "input_value": null, + "openai_api_key": null, + "temperature": null, + "model_name": null, + "max_tokens": null, + "model_kwargs": null, + "openai_api_base": null, + "stream": null, + "system_message": null + }, + "output_types": [ + "Text" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [ + "max_tokens", + "model_kwargs", + "model_name", + "openai_api_base", + "openai_api_key", + "temperature", + "input_value", + "system_message", + "stream" + ], + "beta": false + }, + "id": "OpenAIModel-k39HS", + "description": "Generates text using OpenAI LLMs.", + "display_name": "OpenAI" + }, + "selected": false, + "width": 384, + "height": 563, + "positionAbsolute": { + "x": 634.8148772766217, + "y": 27.035057029045305 + }, + "dragging": false + }, + { + "id": "ChatOutput-njtka", + "type": "genericNode", + "position": { + "x": 1193.250417197867, + "y": 71.88476890163852 + }, + "data": { + "type": "ChatOutput", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional, Union\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.schema import Record\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Interaction Panel.\"\n icon = \"ChatOutput\"\n\n def build(\n self,\n sender: Optional[str] = \"Machine\",\n sender_name: Optional[str] = \"AI\",\n input_value: Optional[str] = None,\n session_id: Optional[str] = None,\n return_record: Optional[bool] = False,\n record_template: Optional[str] = \"{text}\",\n ) -> Union[Text, Record]:\n return super().build(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n session_id=session_id,\n return_record=return_record,\n record_template=record_template,\n )\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "input_value": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Message", + "advanced": false, + "input_types": [ + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "record_template": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "{text}", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "record_template", + "display_name": "Record Template", + "advanced": true, + "dynamic": false, + "info": "In case of Message being a Record, this template will be used to convert it to text.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "return_record": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "return_record", + "display_name": "Return Record", + "advanced": true, + "dynamic": false, + "info": "Return the message as a record containing the sender, sender_name, and session_id.", + "load_from_db": false, + "title_case": false + }, + "sender": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "Machine", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "Machine", + "User" + ], + "name": "sender", + "display_name": "Sender Type", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "sender_name": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "AI", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "sender_name", + "display_name": "Sender Name", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "session_id": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "session_id", + "display_name": "Session ID", + "advanced": true, + "dynamic": false, + "info": "If provided, the message will be stored in the memory.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "_type": "CustomComponent" + }, + "description": "Display a chat message in the Interaction Panel.", + "icon": "ChatOutput", + "base_classes": [ + "Record", + "Text", + "str", + "object" + ], + "display_name": "Chat Output", + "documentation": "", + "custom_fields": { + "sender": null, + "sender_name": null, + "input_value": null, + "session_id": null, + "return_record": null, + "record_template": null + }, + "output_types": [ + "Text", + "Record" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "ChatOutput-njtka" + }, + "selected": false, + "width": 384, + "height": 383, + "positionAbsolute": { + "x": 1193.250417197867, + "y": 71.88476890163852 + }, + "dragging": false + }, + { + "id": "ChatInput-P3fgL", + "type": "genericNode", + "position": { + "x": -495.2223093083827, + "y": -232.56998443685862 + }, + "data": { + "type": "ChatInput", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional, Union\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.schema import Record\n\n\nclass ChatInput(ChatComponent):\n display_name = \"Chat Input\"\n description = \"Get chat inputs from the Interaction Panel.\"\n icon = \"ChatInput\"\n\n def build_config(self):\n build_config = super().build_config()\n build_config[\"input_value\"] = {\n \"input_types\": [],\n \"display_name\": \"Message\",\n \"multiline\": True,\n }\n\n return build_config\n\n def build(\n self,\n sender: Optional[str] = \"User\",\n sender_name: Optional[str] = \"User\",\n input_value: Optional[str] = None,\n session_id: Optional[str] = None,\n return_record: Optional[bool] = False,\n ) -> Union[Text, Record]:\n return super().build(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n session_id=session_id,\n return_record=return_record,\n )\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "input_value": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Message", + "advanced": false, + "input_types": [], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "value": "hi" + }, + "return_record": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "return_record", + "display_name": "Return Record", + "advanced": true, + "dynamic": false, + "info": "Return the message as a record containing the sender, sender_name, and session_id.", + "load_from_db": false, + "title_case": false + }, + "sender": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "User", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "Machine", + "User" + ], + "name": "sender", + "display_name": "Sender Type", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "sender_name": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "User", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "sender_name", + "display_name": "Sender Name", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "session_id": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "session_id", + "display_name": "Session ID", + "advanced": true, + "dynamic": false, + "info": "If provided, the message will be stored in the memory.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "_type": "CustomComponent" + }, + "description": "Get chat inputs from the Interaction Panel.", + "icon": "ChatInput", + "base_classes": [ + "object", + "Record", + "str", + "Text" + ], + "display_name": "Chat Input", + "documentation": "", + "custom_fields": { + "sender": null, + "sender_name": null, + "input_value": null, + "session_id": null, + "return_record": null + }, + "output_types": [ + "Text", + "Record" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "ChatInput-P3fgL" + }, + "selected": false, + "width": 384, + "height": 375, + "positionAbsolute": { + "x": -495.2223093083827, + "y": -232.56998443685862 + }, + "dragging": false + } + ], + "edges": [ + { + "source": "OpenAIModel-k39HS", + "sourceHandle": "{œbaseClassesœ:[œobjectœ,œTextœ,œstrœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-k39HSœ}", + "target": "ChatOutput-njtka", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-njtkaœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "input_value", + "id": "ChatOutput-njtka", + "inputTypes": [ + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "object", + "Text", + "str" + ], + "dataType": "OpenAIModel", + "id": "OpenAIModel-k39HS" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-OpenAIModel-k39HS{œbaseClassesœ:[œobjectœ,œTextœ,œstrœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-k39HSœ}-ChatOutput-njtka{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-njtkaœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}" + }, + { + "source": "Prompt-uxBqP", + "sourceHandle": "{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-uxBqPœ}", + "target": "OpenAIModel-k39HS", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-k39HSœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "input_value", + "id": "OpenAIModel-k39HS", + "inputTypes": [ + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "object", + "str", + "Text" + ], + "dataType": "Prompt", + "id": "Prompt-uxBqP" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-Prompt-uxBqP{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-uxBqPœ}-OpenAIModel-k39HS{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-k39HSœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}" + }, + { + "source": "ChatInput-P3fgL", + "sourceHandle": "{œbaseClassesœ:[œobjectœ,œRecordœ,œstrœ,œTextœ],œdataTypeœ:œChatInputœ,œidœ:œChatInput-P3fgLœ}", + "target": "Prompt-uxBqP", + "targetHandle": "{œfieldNameœ:œuser_inputœ,œidœ:œPrompt-uxBqPœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "user_input", + "id": "Prompt-uxBqP", + "inputTypes": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "object", + "Record", + "str", + "Text" + ], + "dataType": "ChatInput", + "id": "ChatInput-P3fgL" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-ChatInput-P3fgL{œbaseClassesœ:[œobjectœ,œRecordœ,œstrœ,œTextœ],œdataTypeœ:œChatInputœ,œidœ:œChatInput-P3fgLœ}-Prompt-uxBqP{œfieldNameœ:œuser_inputœ,œidœ:œPrompt-uxBqPœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}" + } + ], + "viewport": { + "x": 260.58251815500563, + "y": 318.2261172111936, + "zoom": 0.43514115784696294 + } + }, + "description": "This flow will get you experimenting with the basics of the UI, the Chat and the Prompt component. \n\nTry changing the Template in it to see how the model behaves. \nYou can change it to this and a Text Input into the `type_of_person` variable : \"Answer the user as if you were a pirate.\n\nUser: {user_input}\n\nAnswer: \" ", + "name": "Basic Prompting (Hello, world!)", + "last_tested_version": "1.0.0a4", + "is_component": false +} \ No newline at end of file diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Langflow Blog Writter.json b/src/backend/base/langflow/initial_setup/starter_projects/Langflow Blog Writter.json new file mode 100644 index 000000000..9663a78ef --- /dev/null +++ b/src/backend/base/langflow/initial_setup/starter_projects/Langflow Blog Writter.json @@ -0,0 +1,989 @@ +{ + "id": "6ad5559d-fb66-4fdc-8f98-96f4ac12799d", + "data": { + "nodes": [ + { + "id": "Prompt-Rse03", + "type": "genericNode", + "position": { + "x": 1331.381712783371, + "y": 535.0279854229713 + }, + "data": { + "type": "Prompt", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from langchain_core.prompts import PromptTemplate\n\nfrom langflow.field_typing import Prompt, TemplateField, Text\nfrom langflow.interface.custom.custom_component import CustomComponent\n\n\nclass PromptComponent(CustomComponent):\n display_name: str = \"Prompt\"\n description: str = \"Create a prompt template with dynamic variables.\"\n icon = \"prompts\"\n\n def build_config(self):\n return {\n \"template\": TemplateField(display_name=\"Template\"),\n \"code\": TemplateField(advanced=True),\n }\n\n def build(\n self,\n template: Prompt,\n **kwargs,\n ) -> Text:\n from langflow.base.prompts.utils import dict_values_to_string\n\n prompt_template = PromptTemplate.from_template(Text(template))\n kwargs = dict_values_to_string(kwargs)\n kwargs = {k: \"\\n\".join(v) if isinstance(v, list) else v for k, v in kwargs.items()}\n try:\n formated_prompt = prompt_template.format(**kwargs)\n except Exception as exc:\n raise ValueError(f\"Error formatting prompt: {exc}\") from exc\n self.status = f'Prompt:\\n\"{formated_prompt}\"'\n return formated_prompt\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "template": { + "type": "prompt", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "Reference 1:\n\n{reference_1}\n\n---\n\nReference 2:\n\n{reference_2}\n\n---\n\n{instructions}\n\nBlog: \n\n\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "template", + "display_name": "Template", + "advanced": false, + "input_types": ["Text"], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "_type": "CustomComponent", + "reference_1": { + "field_type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "reference_1", + "display_name": "reference_1", + "advanced": false, + "input_types": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "type": "str" + }, + "reference_2": { + "field_type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "reference_2", + "display_name": "reference_2", + "advanced": false, + "input_types": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "type": "str" + }, + "instructions": { + "field_type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "instructions", + "display_name": "instructions", + "advanced": false, + "input_types": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "type": "str" + } + }, + "description": "Create a prompt template with dynamic variables.", + "icon": "prompts", + "is_input": null, + "is_output": null, + "is_composition": null, + "base_classes": ["object", "Text", "str"], + "name": "", + "display_name": "Prompt", + "documentation": "", + "custom_fields": { + "template": ["reference_1", "reference_2", "instructions"] + }, + "output_types": ["Text"], + "full_path": null, + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false, + "error": null + }, + "id": "Prompt-Rse03", + "description": "Create a prompt template with dynamic variables.", + "display_name": "Prompt" + }, + "selected": false, + "width": 384, + "height": 571, + "dragging": false, + "positionAbsolute": { + "x": 1331.381712783371, + "y": 535.0279854229713 + } + }, + { + "id": "URL-HYPkR", + "type": "genericNode", + "position": { + "x": 568.2971412887712, + "y": 700.9983368007821 + }, + "data": { + "type": "URL", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Any, Dict\n\nfrom langchain_community.document_loaders.web_base import WebBaseLoader\n\nfrom langflow.interface.custom.custom_component import CustomComponent\nfrom langflow.schema import Record\n\n\nclass URLComponent(CustomComponent):\n display_name = \"URL\"\n description = \"Fetch content from one or more URLs.\"\n icon = \"layout-template\"\n\n def build_config(self) -> Dict[str, Any]:\n return {\n \"urls\": {\"display_name\": \"URL\"},\n }\n\n def build(\n self,\n urls: list[str],\n ) -> list[Record]:\n loader = WebBaseLoader(web_paths=urls)\n docs = loader.load()\n records = self.to_records(docs)\n self.status = records\n return records\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "urls": { + "type": "str", + "required": true, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "urls", + "display_name": "URL", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": ["Text"], + "value": [ + "https://www.promptingguide.ai/techniques/prompt_chaining" + ] + }, + "_type": "CustomComponent" + }, + "description": "Fetch content from one or more URLs.", + "icon": "layout-template", + "base_classes": ["Record"], + "display_name": "URL", + "documentation": "", + "custom_fields": { + "urls": null + }, + "output_types": ["Record"], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "URL-HYPkR" + }, + "selected": false, + "width": 384, + "height": 281, + "positionAbsolute": { + "x": 568.2971412887712, + "y": 700.9983368007821 + }, + "dragging": false + }, + { + "id": "ChatOutput-JPlxl", + "type": "genericNode", + "position": { + "x": 2503.8617424688505, + "y": 789.3005578928434 + }, + "data": { + "type": "ChatOutput", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional, Union\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.schema import Record\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Interaction Panel.\"\n icon = \"ChatOutput\"\n\n def build(\n self,\n sender: Optional[str] = \"Machine\",\n sender_name: Optional[str] = \"AI\",\n input_value: Optional[str] = None,\n session_id: Optional[str] = None,\n return_record: Optional[bool] = False,\n record_template: Optional[str] = \"{text}\",\n ) -> Union[Text, Record]:\n return super().build(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n session_id=session_id,\n return_record=return_record,\n record_template=record_template,\n )\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "input_value": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Message", + "advanced": false, + "input_types": ["Text"], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "record_template": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "{text}", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "record_template", + "display_name": "Record Template", + "advanced": true, + "dynamic": false, + "info": "In case of Message being a Record, this template will be used to convert it to text.", + "load_from_db": false, + "title_case": false, + "input_types": ["Text"] + }, + "return_record": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "return_record", + "display_name": "Return Record", + "advanced": true, + "dynamic": false, + "info": "Return the message as a record containing the sender, sender_name, and session_id.", + "load_from_db": false, + "title_case": false + }, + "sender": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "Machine", + "fileTypes": [], + "file_path": "", + "password": false, + "options": ["Machine", "User"], + "name": "sender", + "display_name": "Sender Type", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": ["Text"] + }, + "sender_name": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "AI", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "sender_name", + "display_name": "Sender Name", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": ["Text"] + }, + "session_id": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "session_id", + "display_name": "Session ID", + "advanced": true, + "dynamic": false, + "info": "If provided, the message will be stored in the memory.", + "load_from_db": false, + "title_case": false, + "input_types": ["Text"] + }, + "_type": "CustomComponent" + }, + "description": "Display a chat message in the Interaction Panel.", + "icon": "ChatOutput", + "base_classes": ["Text", "Record", "object", "str"], + "display_name": "Chat Output", + "documentation": "", + "custom_fields": { + "sender": null, + "sender_name": null, + "input_value": null, + "session_id": null, + "return_record": null, + "record_template": null + }, + "output_types": ["Text", "Record"], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "ChatOutput-JPlxl" + }, + "selected": false, + "width": 384, + "height": 383 + }, + { + "id": "OpenAIModel-gi29P", + "type": "genericNode", + "position": { + "x": 1917.7089968570963, + "y": 575.9186499244129 + }, + "data": { + "type": "OpenAIModel", + "node": { + "template": { + "input_value": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Input", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": ["Text"] + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional\n\nfrom langchain_openai import ChatOpenAI\n\nfrom langflow.base.constants import STREAM_INFO_TEXT\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.field_typing import NestedDict, Text\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n\n field_order = [\n \"max_tokens\",\n \"model_kwargs\",\n \"model_name\",\n \"openai_api_base\",\n \"openai_api_key\",\n \"temperature\",\n \"input_value\",\n \"system_message\",\n \"stream\",\n ]\n\n def build_config(self):\n return {\n \"input_value\": {\"display_name\": \"Input\"},\n \"max_tokens\": {\n \"display_name\": \"Max Tokens\",\n \"advanced\": True,\n },\n \"model_kwargs\": {\n \"display_name\": \"Model Kwargs\",\n \"advanced\": True,\n },\n \"model_name\": {\n \"display_name\": \"Model Name\",\n \"advanced\": False,\n \"options\": [\n \"gpt-4-turbo-preview\",\n \"gpt-3.5-turbo\",\n \"gpt-4-0125-preview\",\n \"gpt-4-1106-preview\",\n \"gpt-4-vision-preview\",\n \"gpt-3.5-turbo-0125\",\n \"gpt-3.5-turbo-1106\",\n ],\n \"value\": \"gpt-4-turbo-preview\",\n },\n \"openai_api_base\": {\n \"display_name\": \"OpenAI API Base\",\n \"advanced\": True,\n \"info\": (\n \"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\n\"\n \"You can change this to use other APIs like JinaChat, LocalAI and Prem.\"\n ),\n },\n \"openai_api_key\": {\n \"display_name\": \"OpenAI API Key\",\n \"info\": \"The OpenAI API Key to use for the OpenAI model.\",\n \"advanced\": False,\n \"password\": True,\n },\n \"temperature\": {\n \"display_name\": \"Temperature\",\n \"advanced\": False,\n \"value\": 0.1,\n },\n \"stream\": {\n \"display_name\": \"Stream\",\n \"info\": STREAM_INFO_TEXT,\n \"advanced\": True,\n },\n \"system_message\": {\n \"display_name\": \"System Message\",\n \"info\": \"System message to pass to the model.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n input_value: Text,\n openai_api_key: str,\n temperature: float,\n model_name: str,\n max_tokens: Optional[int] = 256,\n model_kwargs: NestedDict = {},\n openai_api_base: Optional[str] = None,\n stream: bool = False,\n system_message: Optional[str] = None,\n ) -> Text:\n if not openai_api_base:\n openai_api_base = \"https://api.openai.com/v1\"\n output = ChatOpenAI(\n max_tokens=max_tokens,\n model_kwargs=model_kwargs,\n model=model_name,\n base_url=openai_api_base,\n api_key=openai_api_key,\n temperature=temperature,\n )\n\n return self.get_chat_result(output, stream, input_value, system_message)\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "max_tokens": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "1024", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "max_tokens", + "display_name": "Max Tokens", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "model_kwargs": { + "type": "NestedDict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": {}, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "model_kwargs", + "display_name": "Model Kwargs", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "model_name": { + "type": "str", + "required": true, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "gpt-3.5-turbo-0125", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "gpt-4-turbo-preview", + "gpt-3.5-turbo", + "gpt-4-0125-preview", + "gpt-4-1106-preview", + "gpt-4-vision-preview", + "gpt-3.5-turbo-0125", + "gpt-3.5-turbo-1106" + ], + "name": "model_name", + "display_name": "Model Name", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": ["Text"] + }, + "openai_api_base": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "openai_api_base", + "display_name": "OpenAI API Base", + "advanced": true, + "dynamic": false, + "info": "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.", + "load_from_db": false, + "title_case": false, + "input_types": ["Text"] + }, + "openai_api_key": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": true, + "name": "openai_api_key", + "display_name": "OpenAI API Key", + "advanced": false, + "dynamic": false, + "info": "The OpenAI API Key to use for the OpenAI model.", + "load_from_db": false, + "title_case": false, + "input_types": ["Text"], + "value": "" + }, + "stream": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": true, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "stream", + "display_name": "Stream", + "advanced": true, + "dynamic": false, + "info": "Stream the response from the model. Streaming works only in Chat.", + "load_from_db": false, + "title_case": false + }, + "system_message": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "system_message", + "display_name": "System Message", + "advanced": true, + "dynamic": false, + "info": "System message to pass to the model.", + "load_from_db": false, + "title_case": false, + "input_types": ["Text"] + }, + "temperature": { + "type": "float", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "0.1", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "temperature", + "display_name": "Temperature", + "advanced": false, + "dynamic": false, + "info": "", + "rangeSpec": { + "step_type": "float", + "min": -1, + "max": 1, + "step": 0.1 + }, + "load_from_db": false, + "title_case": false + }, + "_type": "CustomComponent" + }, + "description": "Generates text using OpenAI LLMs.", + "icon": "OpenAI", + "base_classes": ["str", "Text", "object"], + "display_name": "OpenAI", + "documentation": "", + "custom_fields": { + "input_value": null, + "openai_api_key": null, + "temperature": null, + "model_name": null, + "max_tokens": null, + "model_kwargs": null, + "openai_api_base": null, + "stream": null, + "system_message": null + }, + "output_types": ["Text"], + "field_formatters": {}, + "frozen": false, + "field_order": [ + "max_tokens", + "model_kwargs", + "model_name", + "openai_api_base", + "openai_api_key", + "temperature", + "input_value", + "system_message", + "stream" + ], + "beta": false + }, + "id": "OpenAIModel-gi29P" + }, + "selected": false, + "width": 384, + "height": 563, + "positionAbsolute": { + "x": 1917.7089968570963, + "y": 575.9186499244129 + }, + "dragging": false + }, + { + "id": "URL-2cX90", + "type": "genericNode", + "position": { + "x": 573.961301764604, + "y": 336.41463436122086 + }, + "data": { + "type": "URL", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Any, Dict\n\nfrom langchain_community.document_loaders.web_base import WebBaseLoader\n\nfrom langflow.interface.custom.custom_component import CustomComponent\nfrom langflow.schema import Record\n\n\nclass URLComponent(CustomComponent):\n display_name = \"URL\"\n description = \"Fetch content from one or more URLs.\"\n icon = \"layout-template\"\n\n def build_config(self) -> Dict[str, Any]:\n return {\n \"urls\": {\"display_name\": \"URL\"},\n }\n\n def build(\n self,\n urls: list[str],\n ) -> list[Record]:\n loader = WebBaseLoader(web_paths=urls)\n docs = loader.load()\n records = self.to_records(docs)\n self.status = records\n return records\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "urls": { + "type": "str", + "required": true, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "urls", + "display_name": "URL", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": ["Text"], + "value": ["https://www.promptingguide.ai/introduction/basics"] + }, + "_type": "CustomComponent" + }, + "description": "Fetch content from one or more URLs.", + "icon": "layout-template", + "base_classes": ["Record"], + "display_name": "URL", + "documentation": "", + "custom_fields": { + "urls": null + }, + "output_types": ["Record"], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "URL-2cX90" + }, + "selected": false, + "width": 384, + "height": 281, + "positionAbsolute": { + "x": 573.961301764604, + "y": 336.41463436122086 + }, + "dragging": false + }, + { + "id": "TextInput-og8Or", + "type": "genericNode", + "position": { + "x": 569.9387927203336, + "y": 1095.3352160671316 + }, + "data": { + "type": "TextInput", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional\n\nfrom langflow.base.io.text import TextComponent\nfrom langflow.field_typing import Text\n\n\nclass TextInput(TextComponent):\n display_name = \"Text Input\"\n description = \"Get text inputs from the Interaction Panel.\"\n icon = \"type\"\n\n def build_config(self):\n return {\n \"input_value\": {\n \"display_name\": \"Value\",\n \"input_types\": [\"Record\", \"Text\"],\n \"info\": \"Text or Record to be passed as input.\",\n },\n \"record_template\": {\n \"display_name\": \"Record Template\",\n \"multiline\": True,\n \"info\": \"Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n input_value: Optional[str] = \"\",\n record_template: Optional[str] = \"\",\n ) -> Text:\n return super().build(input_value=input_value, record_template=record_template)\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "input_value": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "Use the references above for style to write a new blog/tutorial about prompt engineering techniques. Suggest non-covered topics.", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Value", + "advanced": false, + "input_types": ["Record", "Text"], + "dynamic": false, + "info": "Text or Record to be passed as input.", + "load_from_db": false, + "title_case": false + }, + "record_template": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "record_template", + "display_name": "Record Template", + "advanced": true, + "dynamic": false, + "info": "Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.", + "load_from_db": false, + "title_case": false, + "input_types": ["Text"] + }, + "_type": "CustomComponent" + }, + "description": "Get text inputs from the Interaction Panel.", + "icon": "type", + "base_classes": ["object", "Text", "str"], + "display_name": "Instructions", + "documentation": "", + "custom_fields": { + "input_value": null, + "record_template": null + }, + "output_types": ["Text"], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "TextInput-og8Or" + }, + "selected": false, + "width": 384, + "height": 289, + "positionAbsolute": { + "x": 569.9387927203336, + "y": 1095.3352160671316 + }, + "dragging": false + } + ], + "edges": [ + { + "source": "URL-HYPkR", + "target": "Prompt-Rse03", + "sourceHandle": "{œbaseClassesœ:[œRecordœ],œdataTypeœ:œURLœ,œidœ:œURL-HYPkRœ}", + "targetHandle": "{œfieldNameœ:œreference_2œ,œidœ:œPrompt-Rse03œ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-URL-HYPkR{œbaseClassesœ:[œRecordœ],œdataTypeœ:œURLœ,œidœ:œURL-HYPkRœ}-Prompt-Rse03{œfieldNameœ:œreference_2œ,œidœ:œPrompt-Rse03œ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "reference_2", + "id": "Prompt-Rse03", + "inputTypes": ["Document", "BaseOutputParser", "Record", "Text"], + "type": "str" + }, + "sourceHandle": { + "baseClasses": ["Record"], + "dataType": "URL", + "id": "URL-HYPkR" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "selected": false + }, + { + "source": "OpenAIModel-gi29P", + "sourceHandle": "{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-gi29Pœ}", + "target": "ChatOutput-JPlxl", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-JPlxlœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "input_value", + "id": "ChatOutput-JPlxl", + "inputTypes": ["Text"], + "type": "str" + }, + "sourceHandle": { + "baseClasses": ["str", "Text", "object"], + "dataType": "OpenAIModel", + "id": "OpenAIModel-gi29P" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-OpenAIModel-gi29P{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-gi29Pœ}-ChatOutput-JPlxl{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-JPlxlœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}" + }, + { + "source": "URL-2cX90", + "sourceHandle": "{œbaseClassesœ:[œRecordœ],œdataTypeœ:œURLœ,œidœ:œURL-2cX90œ}", + "target": "Prompt-Rse03", + "targetHandle": "{œfieldNameœ:œreference_1œ,œidœ:œPrompt-Rse03œ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "reference_1", + "id": "Prompt-Rse03", + "inputTypes": ["Document", "BaseOutputParser", "Record", "Text"], + "type": "str" + }, + "sourceHandle": { + "baseClasses": ["Record"], + "dataType": "URL", + "id": "URL-2cX90" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-URL-2cX90{œbaseClassesœ:[œRecordœ],œdataTypeœ:œURLœ,œidœ:œURL-2cX90œ}-Prompt-Rse03{œfieldNameœ:œreference_1œ,œidœ:œPrompt-Rse03œ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}" + }, + { + "source": "TextInput-og8Or", + "sourceHandle": "{œbaseClassesœ:[œobjectœ,œTextœ,œstrœ],œdataTypeœ:œTextInputœ,œidœ:œTextInput-og8Orœ}", + "target": "Prompt-Rse03", + "targetHandle": "{œfieldNameœ:œinstructionsœ,œidœ:œPrompt-Rse03œ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "instructions", + "id": "Prompt-Rse03", + "inputTypes": ["Document", "BaseOutputParser", "Record", "Text"], + "type": "str" + }, + "sourceHandle": { + "baseClasses": ["object", "Text", "str"], + "dataType": "TextInput", + "id": "TextInput-og8Or" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-TextInput-og8Or{œbaseClassesœ:[œobjectœ,œTextœ,œstrœ],œdataTypeœ:œTextInputœ,œidœ:œTextInput-og8Orœ}-Prompt-Rse03{œfieldNameœ:œinstructionsœ,œidœ:œPrompt-Rse03œ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}" + }, + { + "source": "Prompt-Rse03", + "sourceHandle": "{œbaseClassesœ:[œobjectœ,œTextœ,œstrœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-Rse03œ}", + "target": "OpenAIModel-gi29P", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-gi29Pœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "input_value", + "id": "OpenAIModel-gi29P", + "inputTypes": ["Text"], + "type": "str" + }, + "sourceHandle": { + "baseClasses": ["object", "Text", "str"], + "dataType": "Prompt", + "id": "Prompt-Rse03" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-Prompt-Rse03{œbaseClassesœ:[œobjectœ,œTextœ,œstrœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-Rse03œ}-OpenAIModel-gi29P{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-gi29Pœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "selected": false + } + ], + "viewport": { + "x": -214.14726025721177, + "y": -35.83855793844168, + "zoom": 0.47344308394045925 + } + }, + "description": "This flow can be used to create a blog post following instructions from the user, using two other blogs as reference.", + "name": "Blog Writer", + "last_tested_version": "1.0.0a0", + "is_component": false +} diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Langflow Document QA.json b/src/backend/base/langflow/initial_setup/starter_projects/Langflow Document QA.json new file mode 100644 index 000000000..b8449f430 --- /dev/null +++ b/src/backend/base/langflow/initial_setup/starter_projects/Langflow Document QA.json @@ -0,0 +1,1031 @@ +{ + "id": "fecbce42-6f11-454c-8ab2-db6eddbbbb0f", + "data": { + "nodes": [ + { + "id": "Prompt-tHwPf", + "type": "genericNode", + "position": { + "x": 585.7906101139403, + "y": 117.52115876762832 + }, + "data": { + "type": "Prompt", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from langchain_core.prompts import PromptTemplate\n\nfrom langflow.field_typing import Prompt, TemplateField, Text\nfrom langflow.interface.custom.custom_component import CustomComponent\n\n\nclass PromptComponent(CustomComponent):\n display_name: str = \"Prompt\"\n description: str = \"Create a prompt template with dynamic variables.\"\n icon = \"prompts\"\n\n def build_config(self):\n return {\n \"template\": TemplateField(display_name=\"Template\"),\n \"code\": TemplateField(advanced=True),\n }\n\n def build(\n self,\n template: Prompt,\n **kwargs,\n ) -> Text:\n from langflow.base.prompts.utils import dict_values_to_string\n\n prompt_template = PromptTemplate.from_template(Text(template))\n kwargs = dict_values_to_string(kwargs)\n kwargs = {k: \"\\n\".join(v) if isinstance(v, list) else v for k, v in kwargs.items()}\n try:\n formated_prompt = prompt_template.format(**kwargs)\n except Exception as exc:\n raise ValueError(f\"Error formatting prompt: {exc}\") from exc\n self.status = f'Prompt:\\n\"{formated_prompt}\"'\n return formated_prompt\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "template": { + "type": "prompt", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "Answer user's questions based on the document below:\n\n---\n\n{Document}\n\n---\n\nQuestion:\n{Question}\n\nAnswer:\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "template", + "display_name": "Template", + "advanced": false, + "input_types": [ + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "_type": "CustomComponent", + "Document": { + "field_type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "Document", + "display_name": "Document", + "advanced": false, + "input_types": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "type": "str" + }, + "Question": { + "field_type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "Question", + "display_name": "Question", + "advanced": false, + "input_types": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "type": "str" + } + }, + "description": "Create a prompt template with dynamic variables.", + "icon": "prompts", + "is_input": null, + "is_output": null, + "is_composition": null, + "base_classes": [ + "object", + "str", + "Text" + ], + "name": "", + "display_name": "Prompt", + "documentation": "", + "custom_fields": { + "template": [ + "Document", + "Question" + ] + }, + "output_types": [ + "Text" + ], + "full_path": null, + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false, + "error": null + }, + "id": "Prompt-tHwPf", + "description": "A component for creating prompt templates using dynamic variables.", + "display_name": "Prompt" + }, + "selected": false, + "width": 384, + "height": 479, + "positionAbsolute": { + "x": 585.7906101139403, + "y": 117.52115876762832 + }, + "dragging": false + }, + { + "id": "File-6TEsD", + "type": "genericNode", + "position": { + "x": -18.636536329280602, + "y": 3.951948774836353 + }, + "data": { + "type": "File", + "node": { + "template": { + "path": { + "type": "file", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [ + ".txt", + ".md", + ".mdx", + ".csv", + ".json", + ".yaml", + ".yml", + ".xml", + ".html", + ".htm", + ".pdf", + ".docx" + ], + "password": false, + "name": "path", + "display_name": "Path", + "advanced": false, + "dynamic": false, + "info": "Supported file types: txt, md, mdx, csv, json, yaml, yml, xml, html, htm, pdf, docx", + "load_from_db": false, + "title_case": false, + "value": "" + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from pathlib import Path\nfrom typing import Any, Dict\n\nfrom langflow.base.data.utils import TEXT_FILE_TYPES, parse_text_file_to_record\nfrom langflow.interface.custom.custom_component import CustomComponent\nfrom langflow.schema import Record\n\n\nclass FileComponent(CustomComponent):\n display_name = \"Files\"\n description = \"A generic file loader.\"\n\n def build_config(self) -> Dict[str, Any]:\n return {\n \"path\": {\n \"display_name\": \"Path\",\n \"field_type\": \"file\",\n \"file_types\": TEXT_FILE_TYPES,\n \"info\": f\"Supported file types: {', '.join(TEXT_FILE_TYPES)}\",\n },\n \"silent_errors\": {\n \"display_name\": \"Silent Errors\",\n \"advanced\": True,\n \"info\": \"If true, errors will not raise an exception.\",\n },\n }\n\n def load_file(self, path: str, silent_errors: bool = False) -> Record:\n resolved_path = self.resolve_path(path)\n path_obj = Path(resolved_path)\n extension = path_obj.suffix[1:].lower()\n if extension == \"doc\":\n raise ValueError(\"doc files are not supported. Please save as .docx\")\n if extension not in TEXT_FILE_TYPES:\n raise ValueError(f\"Unsupported file type: {extension}\")\n record = parse_text_file_to_record(resolved_path, silent_errors)\n self.status = record if record else \"No data\"\n return record or Record()\n\n def build(\n self,\n path: str,\n silent_errors: bool = False,\n ) -> Record:\n record = self.load_file(path, silent_errors)\n self.status = record\n return record\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "silent_errors": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "silent_errors", + "display_name": "Silent Errors", + "advanced": true, + "dynamic": false, + "info": "If true, errors will not raise an exception.", + "load_from_db": false, + "title_case": false + }, + "_type": "CustomComponent" + }, + "description": "A generic file loader.", + "base_classes": [ + "Record" + ], + "display_name": "Files", + "documentation": "", + "custom_fields": { + "path": null, + "silent_errors": null + }, + "output_types": [ + "Record" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "File-6TEsD" + }, + "selected": false, + "width": 384, + "height": 282, + "positionAbsolute": { + "x": -18.636536329280602, + "y": 3.951948774836353 + }, + "dragging": false + }, + { + "id": "ChatInput-MsSJ9", + "type": "genericNode", + "position": { + "x": -28.80036300619821, + "y": 379.81180230285355 + }, + "data": { + "type": "ChatInput", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional, Union\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.schema import Record\n\n\nclass ChatInput(ChatComponent):\n display_name = \"Chat Input\"\n description = \"Get chat inputs from the Interaction Panel.\"\n icon = \"ChatInput\"\n\n def build_config(self):\n build_config = super().build_config()\n build_config[\"input_value\"] = {\n \"input_types\": [],\n \"display_name\": \"Message\",\n \"multiline\": True,\n }\n\n return build_config\n\n def build(\n self,\n sender: Optional[str] = \"User\",\n sender_name: Optional[str] = \"User\",\n input_value: Optional[str] = None,\n session_id: Optional[str] = None,\n return_record: Optional[bool] = False,\n ) -> Union[Text, Record]:\n return super().build(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n session_id=session_id,\n return_record=return_record,\n )\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "input_value": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Message", + "advanced": false, + "input_types": [], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "value": "" + }, + "return_record": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "return_record", + "display_name": "Return Record", + "advanced": true, + "dynamic": false, + "info": "Return the message as a record containing the sender, sender_name, and session_id.", + "load_from_db": false, + "title_case": false + }, + "sender": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "User", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "Machine", + "User" + ], + "name": "sender", + "display_name": "Sender Type", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "sender_name": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "User", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "sender_name", + "display_name": "Sender Name", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "session_id": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "session_id", + "display_name": "Session ID", + "advanced": true, + "dynamic": false, + "info": "If provided, the message will be stored in the memory.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "_type": "CustomComponent" + }, + "description": "Get chat inputs from the Interaction Panel.", + "icon": "ChatInput", + "base_classes": [ + "str", + "Record", + "Text", + "object" + ], + "display_name": "Chat Input", + "documentation": "", + "custom_fields": { + "sender": null, + "sender_name": null, + "input_value": null, + "session_id": null, + "return_record": null + }, + "output_types": [ + "Text", + "Record" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "ChatInput-MsSJ9" + }, + "selected": true, + "width": 384, + "height": 377, + "positionAbsolute": { + "x": -28.80036300619821, + "y": 379.81180230285355 + }, + "dragging": false + }, + { + "id": "ChatOutput-F5Awj", + "type": "genericNode", + "position": { + "x": 1733.3012915204283, + "y": 168.76098809939327 + }, + "data": { + "type": "ChatOutput", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional, Union\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.schema import Record\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Interaction Panel.\"\n icon = \"ChatOutput\"\n\n def build(\n self,\n sender: Optional[str] = \"Machine\",\n sender_name: Optional[str] = \"AI\",\n input_value: Optional[str] = None,\n session_id: Optional[str] = None,\n return_record: Optional[bool] = False,\n record_template: Optional[str] = \"{text}\",\n ) -> Union[Text, Record]:\n return super().build(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n session_id=session_id,\n return_record=return_record,\n record_template=record_template,\n )\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "input_value": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Message", + "advanced": false, + "input_types": [ + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "return_record": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "return_record", + "display_name": "Return Record", + "advanced": true, + "dynamic": false, + "info": "Return the message as a record containing the sender, sender_name, and session_id.", + "load_from_db": false, + "title_case": false + }, + "sender": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "Machine", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "Machine", + "User" + ], + "name": "sender", + "display_name": "Sender Type", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "sender_name": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "AI", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "sender_name", + "display_name": "Sender Name", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "session_id": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "session_id", + "display_name": "Session ID", + "advanced": true, + "dynamic": false, + "info": "If provided, the message will be stored in the memory.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "_type": "CustomComponent" + }, + "description": "Display a chat message in the Interaction Panel.", + "icon": "ChatOutput", + "base_classes": [ + "str", + "Record", + "Text", + "object" + ], + "display_name": "Chat Output", + "documentation": "", + "custom_fields": { + "sender": null, + "sender_name": null, + "input_value": null, + "session_id": null, + "return_record": null + }, + "output_types": [ + "Text", + "Record" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "ChatOutput-F5Awj" + }, + "selected": false, + "width": 384, + "height": 385, + "positionAbsolute": { + "x": 1733.3012915204283, + "y": 168.76098809939327 + }, + "dragging": false + }, + { + "id": "OpenAIModel-Bt067", + "type": "genericNode", + "position": { + "x": 1137.6078582863759, + "y": -14.41920034020356 + }, + "data": { + "type": "OpenAIModel", + "node": { + "template": { + "input_value": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Input", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional\n\nfrom langchain_openai import ChatOpenAI\n\nfrom langflow.base.constants import STREAM_INFO_TEXT\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.field_typing import NestedDict, Text\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n\n field_order = [\n \"max_tokens\",\n \"model_kwargs\",\n \"model_name\",\n \"openai_api_base\",\n \"openai_api_key\",\n \"temperature\",\n \"input_value\",\n \"system_message\",\n \"stream\",\n ]\n\n def build_config(self):\n return {\n \"input_value\": {\"display_name\": \"Input\"},\n \"max_tokens\": {\n \"display_name\": \"Max Tokens\",\n \"advanced\": True,\n },\n \"model_kwargs\": {\n \"display_name\": \"Model Kwargs\",\n \"advanced\": True,\n },\n \"model_name\": {\n \"display_name\": \"Model Name\",\n \"advanced\": False,\n \"options\": [\n \"gpt-4-turbo-preview\",\n \"gpt-3.5-turbo\",\n \"gpt-4-0125-preview\",\n \"gpt-4-1106-preview\",\n \"gpt-4-vision-preview\",\n \"gpt-3.5-turbo-0125\",\n \"gpt-3.5-turbo-1106\",\n ],\n \"value\": \"gpt-4-turbo-preview\",\n },\n \"openai_api_base\": {\n \"display_name\": \"OpenAI API Base\",\n \"advanced\": True,\n \"info\": (\n \"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\n\"\n \"You can change this to use other APIs like JinaChat, LocalAI and Prem.\"\n ),\n },\n \"openai_api_key\": {\n \"display_name\": \"OpenAI API Key\",\n \"info\": \"The OpenAI API Key to use for the OpenAI model.\",\n \"advanced\": False,\n \"password\": True,\n },\n \"temperature\": {\n \"display_name\": \"Temperature\",\n \"advanced\": False,\n \"value\": 0.1,\n },\n \"stream\": {\n \"display_name\": \"Stream\",\n \"info\": STREAM_INFO_TEXT,\n \"advanced\": True,\n },\n \"system_message\": {\n \"display_name\": \"System Message\",\n \"info\": \"System message to pass to the model.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n input_value: Text,\n openai_api_key: str,\n temperature: float,\n model_name: str,\n max_tokens: Optional[int] = 256,\n model_kwargs: NestedDict = {},\n openai_api_base: Optional[str] = None,\n stream: bool = False,\n system_message: Optional[str] = None,\n ) -> Text:\n if not openai_api_base:\n openai_api_base = \"https://api.openai.com/v1\"\n output = ChatOpenAI(\n max_tokens=max_tokens,\n model_kwargs=model_kwargs,\n model=model_name,\n base_url=openai_api_base,\n api_key=openai_api_key,\n temperature=temperature,\n )\n\n return self.get_chat_result(output, stream, input_value, system_message)\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "max_tokens": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 256, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "max_tokens", + "display_name": "Max Tokens", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "model_kwargs": { + "type": "NestedDict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": {}, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "model_kwargs", + "display_name": "Model Kwargs", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "model_name": { + "type": "str", + "required": true, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "gpt-4-turbo-preview", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "gpt-4-turbo-preview", + "gpt-3.5-turbo", + "gpt-4-0125-preview", + "gpt-4-1106-preview", + "gpt-4-vision-preview", + "gpt-3.5-turbo-0125", + "gpt-3.5-turbo-1106" + ], + "name": "model_name", + "display_name": "Model Name", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_api_base": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "openai_api_base", + "display_name": "OpenAI API Base", + "advanced": true, + "dynamic": false, + "info": "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_api_key": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": true, + "name": "openai_api_key", + "display_name": "OpenAI API Key", + "advanced": false, + "dynamic": false, + "info": "The OpenAI API Key to use for the OpenAI model.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ], + "value": "" + }, + "stream": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": true, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "stream", + "display_name": "Stream", + "advanced": false, + "dynamic": false, + "info": "Stream the response from the model. Streaming works only in Chat.", + "load_from_db": false, + "title_case": false + }, + "system_message": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "system_message", + "display_name": "System Message", + "advanced": true, + "dynamic": false, + "info": "System message to pass to the model.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "temperature": { + "type": "float", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 0.1, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "temperature", + "display_name": "Temperature", + "advanced": false, + "dynamic": false, + "info": "", + "rangeSpec": { + "step_type": "float", + "min": -1, + "max": 1, + "step": 0.1 + }, + "load_from_db": false, + "title_case": false + }, + "_type": "CustomComponent" + }, + "description": "Generates text using OpenAI LLMs.", + "icon": "OpenAI", + "base_classes": [ + "object", + "str", + "Text" + ], + "display_name": "OpenAI", + "documentation": "", + "custom_fields": { + "input_value": null, + "openai_api_key": null, + "temperature": null, + "model_name": null, + "max_tokens": null, + "model_kwargs": null, + "openai_api_base": null, + "stream": null, + "system_message": null + }, + "output_types": [ + "Text" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [ + "max_tokens", + "model_kwargs", + "model_name", + "openai_api_base", + "openai_api_key", + "temperature", + "input_value", + "system_message", + "stream" + ], + "beta": false + }, + "id": "OpenAIModel-Bt067" + }, + "selected": false, + "width": 384, + "height": 642, + "positionAbsolute": { + "x": 1137.6078582863759, + "y": -14.41920034020356 + }, + "dragging": false + } + ], + "edges": [ + { + "source": "ChatInput-MsSJ9", + "sourceHandle": "{œbaseClassesœ:[œstrœ,œRecordœ,œTextœ,œobjectœ],œdataTypeœ:œChatInputœ,œidœ:œChatInput-MsSJ9œ}", + "target": "Prompt-tHwPf", + "targetHandle": "{œfieldNameœ:œQuestionœ,œidœ:œPrompt-tHwPfœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "Question", + "id": "Prompt-tHwPf", + "inputTypes": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "str", + "Record", + "Text", + "object" + ], + "dataType": "ChatInput", + "id": "ChatInput-MsSJ9" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-ChatInput-MsSJ9{œbaseClassesœ:[œstrœ,œRecordœ,œTextœ,œobjectœ],œdataTypeœ:œChatInputœ,œidœ:œChatInput-MsSJ9œ}-Prompt-tHwPf{œfieldNameœ:œQuestionœ,œidœ:œPrompt-tHwPfœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}" + }, + { + "source": "File-6TEsD", + "sourceHandle": "{œbaseClassesœ:[œRecordœ],œdataTypeœ:œFileœ,œidœ:œFile-6TEsDœ}", + "target": "Prompt-tHwPf", + "targetHandle": "{œfieldNameœ:œDocumentœ,œidœ:œPrompt-tHwPfœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "Document", + "id": "Prompt-tHwPf", + "inputTypes": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "Record" + ], + "dataType": "File", + "id": "File-6TEsD" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-File-6TEsD{œbaseClassesœ:[œRecordœ],œdataTypeœ:œFileœ,œidœ:œFile-6TEsDœ}-Prompt-tHwPf{œfieldNameœ:œDocumentœ,œidœ:œPrompt-tHwPfœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}" + }, + { + "source": "Prompt-tHwPf", + "sourceHandle": "{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-tHwPfœ}", + "target": "OpenAIModel-Bt067", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-Bt067œ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "input_value", + "id": "OpenAIModel-Bt067", + "inputTypes": [ + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "object", + "str", + "Text" + ], + "dataType": "Prompt", + "id": "Prompt-tHwPf" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-Prompt-tHwPf{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-tHwPfœ}-OpenAIModel-Bt067{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-Bt067œ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}" + }, + { + "source": "OpenAIModel-Bt067", + "sourceHandle": "{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-Bt067œ}", + "target": "ChatOutput-F5Awj", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-F5Awjœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "input_value", + "id": "ChatOutput-F5Awj", + "inputTypes": [ + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "object", + "str", + "Text" + ], + "dataType": "OpenAIModel", + "id": "OpenAIModel-Bt067" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-OpenAIModel-Bt067{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-Bt067œ}-ChatOutput-F5Awj{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-F5Awjœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}" + } + ], + "viewport": { + "x": 352.20899206064655, + "y": 56.054900898593075, + "zoom": 0.9023391400011 + } + }, + "description": "This flow integrates PDF reading with a language model to answer document-specific questions. Ideal for small-scale texts, it facilitates direct queries with immediate insights.", + "name": "Document QA", + "last_tested_version": "1.0.0a0", + "is_component": false +} \ No newline at end of file diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Langflow Memory Conversation.json b/src/backend/base/langflow/initial_setup/starter_projects/Langflow Memory Conversation.json new file mode 100644 index 000000000..92dbdd6f2 --- /dev/null +++ b/src/backend/base/langflow/initial_setup/starter_projects/Langflow Memory Conversation.json @@ -0,0 +1,1274 @@ +{ + "id": "08d5cccf-d098-4367-b14b-1078429c9ed9", + "icon": "🤖", + "icon_bg_color": "#FFD700", + "data": { + "nodes": [ + { + "id": "ChatInput-t7F8v", + "type": "genericNode", + "position": { + "x": 1283.2700598313072, + "y": 982.5953650473145 + }, + "data": { + "type": "ChatInput", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional, Union\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.schema import Record\n\n\nclass ChatInput(ChatComponent):\n display_name = \"Chat Input\"\n description = \"Get chat inputs from the Interaction Panel.\"\n icon = \"ChatInput\"\n\n def build_config(self):\n build_config = super().build_config()\n build_config[\"input_value\"] = {\n \"input_types\": [],\n \"display_name\": \"Message\",\n \"multiline\": True,\n }\n\n return build_config\n\n def build(\n self,\n sender: Optional[str] = \"User\",\n sender_name: Optional[str] = \"User\",\n input_value: Optional[str] = None,\n session_id: Optional[str] = None,\n return_record: Optional[bool] = False,\n ) -> Union[Text, Record]:\n return super().build(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n session_id=session_id,\n return_record=return_record,\n )\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "input_value": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Message", + "advanced": false, + "input_types": [], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "value": "" + }, + "return_record": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "return_record", + "display_name": "Return Record", + "advanced": true, + "dynamic": false, + "info": "Return the message as a record containing the sender, sender_name, and session_id.", + "load_from_db": false, + "title_case": false + }, + "sender": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "User", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "Machine", + "User" + ], + "name": "sender", + "display_name": "Sender Type", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "sender_name": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "User", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "sender_name", + "display_name": "Sender Name", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "session_id": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "session_id", + "display_name": "Session ID", + "advanced": false, + "dynamic": false, + "info": "If provided, the message will be stored in the memory.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ], + "value": "MySessionID" + }, + "_type": "CustomComponent" + }, + "description": "Get chat inputs from the Interaction Panel.", + "icon": "ChatInput", + "base_classes": [ + "Text", + "object", + "Record", + "str" + ], + "display_name": "Chat Input", + "documentation": "", + "custom_fields": { + "sender": null, + "sender_name": null, + "input_value": null, + "session_id": null, + "return_record": null + }, + "output_types": [ + "Text", + "Record" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "ChatInput-t7F8v" + }, + "selected": false, + "width": 384, + "height": 469, + "positionAbsolute": { + "x": 1283.2700598313072, + "y": 982.5953650473145 + }, + "dragging": false + }, + { + "id": "ChatOutput-P1jEe", + "type": "genericNode", + "position": { + "x": 3154.916355514023, + "y": 851.051882666333 + }, + "data": { + "type": "ChatOutput", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional, Union\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.schema import Record\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Interaction Panel.\"\n icon = \"ChatOutput\"\n\n def build(\n self,\n sender: Optional[str] = \"Machine\",\n sender_name: Optional[str] = \"AI\",\n input_value: Optional[str] = None,\n session_id: Optional[str] = None,\n return_record: Optional[bool] = False,\n record_template: Optional[str] = \"{text}\",\n ) -> Union[Text, Record]:\n return super().build(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n session_id=session_id,\n return_record=return_record,\n record_template=record_template,\n )\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "input_value": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Message", + "advanced": false, + "input_types": [ + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "return_record": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "return_record", + "display_name": "Return Record", + "advanced": true, + "dynamic": false, + "info": "Return the message as a record containing the sender, sender_name, and session_id.", + "load_from_db": false, + "title_case": false + }, + "sender": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "Machine", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "Machine", + "User" + ], + "name": "sender", + "display_name": "Sender Type", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "sender_name": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "AI", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "sender_name", + "display_name": "Sender Name", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "session_id": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "session_id", + "display_name": "Session ID", + "advanced": false, + "dynamic": false, + "info": "If provided, the message will be stored in the memory.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ], + "value": "MySessionID" + }, + "_type": "CustomComponent" + }, + "description": "Display a chat message in the Interaction Panel.", + "icon": "ChatOutput", + "base_classes": [ + "Text", + "object", + "Record", + "str" + ], + "display_name": "Chat Output", + "documentation": "", + "custom_fields": { + "sender": null, + "sender_name": null, + "input_value": null, + "session_id": null, + "return_record": null + }, + "output_types": [ + "Text", + "Record" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "ChatOutput-P1jEe" + }, + "selected": false, + "width": 384, + "height": 477, + "dragging": false, + "positionAbsolute": { + "x": 3154.916355514023, + "y": 851.051882666333 + } + }, + { + "id": "MemoryComponent-cdA1J", + "type": "genericNode", + "position": { + "x": 1289.9606870058817, + "y": 442.16804561053766 + }, + "data": { + "type": "MemoryComponent", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional\n\nfrom langflow.field_typing import Text\nfrom langflow.helpers.record import records_to_text\nfrom langflow.interface.custom.custom_component import CustomComponent\nfrom langflow.memory import get_messages\n\n\nclass MemoryComponent(CustomComponent):\n display_name = \"Chat Memory\"\n description = \"Retrieves stored chat messages given a specific Session ID.\"\n beta: bool = True\n icon = \"history\"\n\n def build_config(self):\n return {\n \"sender\": {\n \"options\": [\"Machine\", \"User\", \"Machine and User\"],\n \"display_name\": \"Sender Type\",\n },\n \"sender_name\": {\"display_name\": \"Sender Name\", \"advanced\": True},\n \"n_messages\": {\n \"display_name\": \"Number of Messages\",\n \"info\": \"Number of messages to retrieve.\",\n },\n \"session_id\": {\n \"display_name\": \"Session ID\",\n \"info\": \"Session ID of the chat history.\",\n \"input_types\": [\"Text\"],\n },\n \"order\": {\n \"options\": [\"Ascending\", \"Descending\"],\n \"display_name\": \"Order\",\n \"info\": \"Order of the messages.\",\n \"advanced\": True,\n },\n \"record_template\": {\n \"display_name\": \"Record Template\",\n \"multiline\": True,\n \"info\": \"Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n sender: Optional[str] = \"Machine and User\",\n sender_name: Optional[str] = None,\n session_id: Optional[str] = None,\n n_messages: int = 5,\n order: Optional[str] = \"Descending\",\n record_template: Optional[str] = \"{sender_name}: {text}\",\n ) -> Text:\n order = \"DESC\" if order == \"Descending\" else \"ASC\"\n if sender == \"Machine and User\":\n sender = None\n messages = get_messages(\n sender=sender,\n sender_name=sender_name,\n session_id=session_id,\n limit=n_messages,\n order=order,\n )\n messages_str = records_to_text(template=record_template, records=messages)\n self.status = messages_str\n return messages_str\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "n_messages": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 5, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "n_messages", + "display_name": "Number of Messages", + "advanced": false, + "dynamic": false, + "info": "Number of messages to retrieve.", + "load_from_db": false, + "title_case": false + }, + "order": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "Descending", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "Ascending", + "Descending" + ], + "name": "order", + "display_name": "Order", + "advanced": true, + "dynamic": false, + "info": "Order of the messages.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "record_template": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "{sender_name}: {text}", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "record_template", + "display_name": "Record Template", + "advanced": true, + "dynamic": false, + "info": "Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "sender": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "Machine and User", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "Machine", + "User", + "Machine and User" + ], + "name": "sender", + "display_name": "Sender Type", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "sender_name": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "sender_name", + "display_name": "Sender Name", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "session_id": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "session_id", + "display_name": "Session ID", + "advanced": false, + "input_types": [ + "Text" + ], + "dynamic": false, + "info": "Session ID of the chat history.", + "load_from_db": false, + "title_case": false, + "value": "MySessionID" + }, + "_type": "CustomComponent" + }, + "description": "Retrieves stored chat messages given a specific Session ID.", + "icon": "history", + "base_classes": [ + "str", + "Text", + "object" + ], + "display_name": "Chat Memory", + "documentation": "", + "custom_fields": { + "sender": null, + "sender_name": null, + "session_id": null, + "n_messages": null, + "order": null, + "record_template": null + }, + "output_types": [ + "Text" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": true + }, + "id": "MemoryComponent-cdA1J", + "description": "Retrieves stored chat messages given a specific Session ID.", + "display_name": "Chat Memory" + }, + "selected": false, + "width": 384, + "height": 489, + "dragging": false, + "positionAbsolute": { + "x": 1289.9606870058817, + "y": 442.16804561053766 + } + }, + { + "id": "Prompt-ODkUx", + "type": "genericNode", + "position": { + "x": 1894.594426342426, + "y": 753.3797365481901 + }, + "data": { + "type": "Prompt", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from langchain_core.prompts import PromptTemplate\n\nfrom langflow.field_typing import Prompt, TemplateField, Text\nfrom langflow.interface.custom.custom_component import CustomComponent\n\n\nclass PromptComponent(CustomComponent):\n display_name: str = \"Prompt\"\n description: str = \"Create a prompt template with dynamic variables.\"\n icon = \"prompts\"\n\n def build_config(self):\n return {\n \"template\": TemplateField(display_name=\"Template\"),\n \"code\": TemplateField(advanced=True),\n }\n\n def build(\n self,\n template: Prompt,\n **kwargs,\n ) -> Text:\n from langflow.base.prompts.utils import dict_values_to_string\n\n prompt_template = PromptTemplate.from_template(Text(template))\n kwargs = dict_values_to_string(kwargs)\n kwargs = {k: \"\\n\".join(v) if isinstance(v, list) else v for k, v in kwargs.items()}\n try:\n formated_prompt = prompt_template.format(**kwargs)\n except Exception as exc:\n raise ValueError(f\"Error formatting prompt: {exc}\") from exc\n self.status = f'Prompt:\\n\"{formated_prompt}\"'\n return formated_prompt\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "template": { + "type": "prompt", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "{context}\n\nUser: {user_message}\nAI: ", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "template", + "display_name": "Template", + "advanced": false, + "input_types": [ + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "_type": "CustomComponent", + "context": { + "field_type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "context", + "display_name": "context", + "advanced": false, + "input_types": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "type": "str" + }, + "user_message": { + "field_type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "user_message", + "display_name": "user_message", + "advanced": false, + "input_types": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "type": "str" + } + }, + "description": "Create a prompt template with dynamic variables.", + "icon": "prompts", + "is_input": null, + "is_output": null, + "is_composition": null, + "base_classes": [ + "Text", + "str", + "object" + ], + "name": "", + "display_name": "Prompt", + "documentation": "", + "custom_fields": { + "template": [ + "context", + "user_message" + ] + }, + "output_types": [ + "Text" + ], + "full_path": null, + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false, + "error": null + }, + "id": "Prompt-ODkUx", + "description": "A component for creating prompt templates using dynamic variables.", + "display_name": "Prompt" + }, + "selected": false, + "width": 384, + "height": 477, + "dragging": false, + "positionAbsolute": { + "x": 1894.594426342426, + "y": 753.3797365481901 + } + }, + { + "id": "OpenAIModel-9RykF", + "type": "genericNode", + "position": { + "x": 2561.5850334731617, + "y": 553.2745131130916 + }, + "data": { + "type": "OpenAIModel", + "node": { + "template": { + "input_value": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Input", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional\n\nfrom langchain_openai import ChatOpenAI\n\nfrom langflow.base.constants import STREAM_INFO_TEXT\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.field_typing import NestedDict, Text\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n\n field_order = [\n \"max_tokens\",\n \"model_kwargs\",\n \"model_name\",\n \"openai_api_base\",\n \"openai_api_key\",\n \"temperature\",\n \"input_value\",\n \"system_message\",\n \"stream\",\n ]\n\n def build_config(self):\n return {\n \"input_value\": {\"display_name\": \"Input\"},\n \"max_tokens\": {\n \"display_name\": \"Max Tokens\",\n \"advanced\": True,\n },\n \"model_kwargs\": {\n \"display_name\": \"Model Kwargs\",\n \"advanced\": True,\n },\n \"model_name\": {\n \"display_name\": \"Model Name\",\n \"advanced\": False,\n \"options\": [\n \"gpt-4-turbo-preview\",\n \"gpt-3.5-turbo\",\n \"gpt-4-0125-preview\",\n \"gpt-4-1106-preview\",\n \"gpt-4-vision-preview\",\n \"gpt-3.5-turbo-0125\",\n \"gpt-3.5-turbo-1106\",\n ],\n \"value\": \"gpt-4-turbo-preview\",\n },\n \"openai_api_base\": {\n \"display_name\": \"OpenAI API Base\",\n \"advanced\": True,\n \"info\": (\n \"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\n\"\n \"You can change this to use other APIs like JinaChat, LocalAI and Prem.\"\n ),\n },\n \"openai_api_key\": {\n \"display_name\": \"OpenAI API Key\",\n \"info\": \"The OpenAI API Key to use for the OpenAI model.\",\n \"advanced\": False,\n \"password\": True,\n },\n \"temperature\": {\n \"display_name\": \"Temperature\",\n \"advanced\": False,\n \"value\": 0.1,\n },\n \"stream\": {\n \"display_name\": \"Stream\",\n \"info\": STREAM_INFO_TEXT,\n \"advanced\": True,\n },\n \"system_message\": {\n \"display_name\": \"System Message\",\n \"info\": \"System message to pass to the model.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n input_value: Text,\n openai_api_key: str,\n temperature: float,\n model_name: str,\n max_tokens: Optional[int] = 256,\n model_kwargs: NestedDict = {},\n openai_api_base: Optional[str] = None,\n stream: bool = False,\n system_message: Optional[str] = None,\n ) -> Text:\n if not openai_api_base:\n openai_api_base = \"https://api.openai.com/v1\"\n output = ChatOpenAI(\n max_tokens=max_tokens,\n model_kwargs=model_kwargs,\n model=model_name,\n base_url=openai_api_base,\n api_key=openai_api_key,\n temperature=temperature,\n )\n\n return self.get_chat_result(output, stream, input_value, system_message)\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "max_tokens": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 256, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "max_tokens", + "display_name": "Max Tokens", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "model_kwargs": { + "type": "NestedDict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": {}, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "model_kwargs", + "display_name": "Model Kwargs", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "model_name": { + "type": "str", + "required": true, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "gpt-4-1106-preview", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "gpt-4-turbo-preview", + "gpt-3.5-turbo", + "gpt-4-0125-preview", + "gpt-4-1106-preview", + "gpt-4-vision-preview", + "gpt-3.5-turbo-0125", + "gpt-3.5-turbo-1106" + ], + "name": "model_name", + "display_name": "Model Name", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_api_base": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "openai_api_base", + "display_name": "OpenAI API Base", + "advanced": true, + "dynamic": false, + "info": "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_api_key": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": true, + "name": "openai_api_key", + "display_name": "OpenAI API Key", + "advanced": false, + "dynamic": false, + "info": "The OpenAI API Key to use for the OpenAI model.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ], + "value": "" + }, + "stream": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "stream", + "display_name": "Stream", + "advanced": true, + "dynamic": false, + "info": "Stream the response from the model. Streaming works only in Chat.", + "load_from_db": false, + "title_case": false + }, + "system_message": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "system_message", + "display_name": "System Message", + "advanced": true, + "dynamic": false, + "info": "System message to pass to the model.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "temperature": { + "type": "float", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "0.2", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "temperature", + "display_name": "Temperature", + "advanced": false, + "dynamic": false, + "info": "", + "rangeSpec": { + "step_type": "float", + "min": -1, + "max": 1, + "step": 0.1 + }, + "load_from_db": false, + "title_case": false + }, + "_type": "CustomComponent" + }, + "description": "Generates text using OpenAI LLMs.", + "icon": "OpenAI", + "base_classes": [ + "str", + "object", + "Text" + ], + "display_name": "OpenAI", + "documentation": "", + "custom_fields": { + "input_value": null, + "openai_api_key": null, + "temperature": null, + "model_name": null, + "max_tokens": null, + "model_kwargs": null, + "openai_api_base": null, + "stream": null, + "system_message": null + }, + "output_types": [ + "Text" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [ + "max_tokens", + "model_kwargs", + "model_name", + "openai_api_base", + "openai_api_key", + "temperature", + "input_value", + "system_message", + "stream" + ], + "beta": false + }, + "id": "OpenAIModel-9RykF" + }, + "selected": false, + "width": 384, + "height": 563, + "positionAbsolute": { + "x": 2561.5850334731617, + "y": 553.2745131130916 + }, + "dragging": false + }, + { + "id": "TextOutput-vrs6T", + "type": "genericNode", + "position": { + "x": 1911.4785906252087, + "y": 247.39079954376987 + }, + "data": { + "type": "TextOutput", + "node": { + "template": { + "input_value": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Value", + "advanced": false, + "input_types": [ + "Record", + "Text" + ], + "dynamic": false, + "info": "Text or Record to be passed as output.", + "load_from_db": false, + "title_case": false + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional\n\nfrom langflow.base.io.text import TextComponent\nfrom langflow.field_typing import Text\n\n\nclass TextOutput(TextComponent):\n display_name = \"Text Output\"\n description = \"Display a text output in the Interaction Panel.\"\n icon = \"type\"\n\n def build_config(self):\n return {\n \"input_value\": {\n \"display_name\": \"Value\",\n \"input_types\": [\"Record\", \"Text\"],\n \"info\": \"Text or Record to be passed as output.\",\n },\n \"record_template\": {\n \"display_name\": \"Record Template\",\n \"multiline\": True,\n \"info\": \"Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.\",\n \"advanced\": True,\n },\n }\n\n def build(self, input_value: Optional[Text] = \"\", record_template: str = \"\") -> Text:\n return super().build(input_value=input_value, record_template=record_template)\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "record_template": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "record_template", + "display_name": "Record Template", + "advanced": true, + "dynamic": false, + "info": "Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "_type": "CustomComponent" + }, + "description": "Display a text output in the Interaction Panel.", + "icon": "type", + "base_classes": [ + "str", + "object", + "Text" + ], + "display_name": "Inspect Memory", + "documentation": "", + "custom_fields": { + "input_value": null, + "record_template": null + }, + "output_types": [ + "Text" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "TextOutput-vrs6T" + }, + "selected": false, + "width": 384, + "height": 289, + "positionAbsolute": { + "x": 1911.4785906252087, + "y": 247.39079954376987 + }, + "dragging": false + } + ], + "edges": [ + { + "source": "MemoryComponent-cdA1J", + "sourceHandle": "{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œMemoryComponentœ,œidœ:œMemoryComponent-cdA1Jœ}", + "target": "Prompt-ODkUx", + "targetHandle": "{œfieldNameœ:œcontextœ,œidœ:œPrompt-ODkUxœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "context", + "type": "str", + "id": "Prompt-ODkUx", + "inputTypes": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ] + }, + "sourceHandle": { + "baseClasses": [ + "str", + "Text", + "object" + ], + "dataType": "MemoryComponent", + "id": "MemoryComponent-cdA1J" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-MemoryComponent-cdA1J{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œMemoryComponentœ,œidœ:œMemoryComponent-cdA1Jœ}-Prompt-ODkUx{œfieldNameœ:œcontextœ,œidœ:œPrompt-ODkUxœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", + "selected": false + }, + { + "source": "ChatInput-t7F8v", + "sourceHandle": "{œbaseClassesœ:[œTextœ,œobjectœ,œRecordœ,œstrœ],œdataTypeœ:œChatInputœ,œidœ:œChatInput-t7F8vœ}", + "target": "Prompt-ODkUx", + "targetHandle": "{œfieldNameœ:œuser_messageœ,œidœ:œPrompt-ODkUxœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "user_message", + "type": "str", + "id": "Prompt-ODkUx", + "inputTypes": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ] + }, + "sourceHandle": { + "baseClasses": [ + "Text", + "object", + "Record", + "str" + ], + "dataType": "ChatInput", + "id": "ChatInput-t7F8v" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-ChatInput-t7F8v{œbaseClassesœ:[œTextœ,œobjectœ,œRecordœ,œstrœ],œdataTypeœ:œChatInputœ,œidœ:œChatInput-t7F8vœ}-Prompt-ODkUx{œfieldNameœ:œuser_messageœ,œidœ:œPrompt-ODkUxœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", + "selected": false + }, + { + "source": "Prompt-ODkUx", + "sourceHandle": "{œbaseClassesœ:[œTextœ,œstrœ,œobjectœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-ODkUxœ}", + "target": "OpenAIModel-9RykF", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-9RykFœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "input_value", + "id": "OpenAIModel-9RykF", + "inputTypes": [ + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "Text", + "str", + "object" + ], + "dataType": "Prompt", + "id": "Prompt-ODkUx" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-Prompt-ODkUx{œbaseClassesœ:[œTextœ,œstrœ,œobjectœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-ODkUxœ}-OpenAIModel-9RykF{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-9RykFœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}" + }, + { + "source": "OpenAIModel-9RykF", + "sourceHandle": "{œbaseClassesœ:[œstrœ,œobjectœ,œTextœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-9RykFœ}", + "target": "ChatOutput-P1jEe", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-P1jEeœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "input_value", + "id": "ChatOutput-P1jEe", + "inputTypes": [ + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "str", + "object", + "Text" + ], + "dataType": "OpenAIModel", + "id": "OpenAIModel-9RykF" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-OpenAIModel-9RykF{œbaseClassesœ:[œstrœ,œobjectœ,œTextœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-9RykFœ}-ChatOutput-P1jEe{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-P1jEeœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}" + }, + { + "source": "MemoryComponent-cdA1J", + "sourceHandle": "{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œMemoryComponentœ,œidœ:œMemoryComponent-cdA1Jœ}", + "target": "TextOutput-vrs6T", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œTextOutput-vrs6Tœ,œinputTypesœ:[œRecordœ,œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "input_value", + "id": "TextOutput-vrs6T", + "inputTypes": [ + "Record", + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "str", + "Text", + "object" + ], + "dataType": "MemoryComponent", + "id": "MemoryComponent-cdA1J" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-foreground stroke-connection", + "id": "reactflow__edge-MemoryComponent-cdA1J{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œMemoryComponentœ,œidœ:œMemoryComponent-cdA1Jœ}-TextOutput-vrs6T{œfieldNameœ:œinput_valueœ,œidœ:œTextOutput-vrs6Tœ,œinputTypesœ:[œRecordœ,œTextœ],œtypeœ:œstrœ}" + } + ], + "viewport": { + "x": -569.862554459756, + "y": -42.08339711050985, + "zoom": 0.4868590524514978 + } +}, + "description": "This project can be used as a starting point for building a Chat experience with user specific memory. You can set a different Session ID to start a new message history.", + "name": "Memory Chatbot", + "last_tested_version": "1.0.0a0", + "is_component": false +} \ No newline at end of file diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Langflow Prompt Chaining.json b/src/backend/base/langflow/initial_setup/starter_projects/Langflow Prompt Chaining.json new file mode 100644 index 000000000..43e8d729c --- /dev/null +++ b/src/backend/base/langflow/initial_setup/starter_projects/Langflow Prompt Chaining.json @@ -0,0 +1,1773 @@ +{ + "id": "85392e54-20f3-4ab5-a179-cb4bef16f639", + "data": { + "nodes": [ + { + "id": "Prompt-amqBu", + "type": "genericNode", + "position": { + "x": 2191.5837146441663, + "y": 1047.9307944451873 + }, + "data": { + "type": "Prompt", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from langchain_core.prompts import PromptTemplate\n\nfrom langflow.field_typing import Prompt, TemplateField, Text\nfrom langflow.interface.custom.custom_component import CustomComponent\n\n\nclass PromptComponent(CustomComponent):\n display_name: str = \"Prompt\"\n description: str = \"Create a prompt template with dynamic variables.\"\n icon = \"prompts\"\n\n def build_config(self):\n return {\n \"template\": TemplateField(display_name=\"Template\"),\n \"code\": TemplateField(advanced=True),\n }\n\n def build(\n self,\n template: Prompt,\n **kwargs,\n ) -> Text:\n from langflow.base.prompts.utils import dict_values_to_string\n\n prompt_template = PromptTemplate.from_template(Text(template))\n kwargs = dict_values_to_string(kwargs)\n kwargs = {k: \"\\n\".join(v) if isinstance(v, list) else v for k, v in kwargs.items()}\n try:\n formated_prompt = prompt_template.format(**kwargs)\n except Exception as exc:\n raise ValueError(f\"Error formatting prompt: {exc}\") from exc\n self.status = f'Prompt:\\n\"{formated_prompt}\"'\n return formated_prompt\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "template": { + "type": "prompt", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "You are a helpful assistant. Given a long document, your task is to create a concise summary that captures the main points and key details. The summary should be clear, accurate, and succinct. Please provide the summary in the format below:\n####\n{document}\n####\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "template", + "display_name": "Template", + "advanced": false, + "input_types": [ + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "_type": "CustomComponent", + "document": { + "field_type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "document", + "display_name": "document", + "advanced": false, + "input_types": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "type": "str" + } + }, + "description": "Create a prompt template with dynamic variables.", + "icon": "prompts", + "is_input": null, + "is_output": null, + "is_composition": null, + "base_classes": [ + "object", + "str", + "Text" + ], + "name": "", + "display_name": "Prompt", + "documentation": "", + "custom_fields": { + "template": [ + "document" + ] + }, + "output_types": [ + "Text" + ], + "full_path": null, + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false, + "error": null + }, + "id": "Prompt-amqBu", + "description": "Create a prompt template with dynamic variables.", + "display_name": "Prompt" + }, + "selected": false, + "width": 384, + "height": 385, + "positionAbsolute": { + "x": 2191.5837146441663, + "y": 1047.9307944451873 + }, + "dragging": false + }, + { + "id": "Prompt-gTNiz", + "type": "genericNode", + "position": { + "x": 3731.0813766902447, + "y": 799.631909121391 + }, + "data": { + "type": "Prompt", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from langchain_core.prompts import PromptTemplate\n\nfrom langflow.field_typing import Prompt, TemplateField, Text\nfrom langflow.interface.custom.custom_component import CustomComponent\n\n\nclass PromptComponent(CustomComponent):\n display_name: str = \"Prompt\"\n description: str = \"Create a prompt template with dynamic variables.\"\n icon = \"prompts\"\n\n def build_config(self):\n return {\n \"template\": TemplateField(display_name=\"Template\"),\n \"code\": TemplateField(advanced=True),\n }\n\n def build(\n self,\n template: Prompt,\n **kwargs,\n ) -> Text:\n from langflow.base.prompts.utils import dict_values_to_string\n\n prompt_template = PromptTemplate.from_template(Text(template))\n kwargs = dict_values_to_string(kwargs)\n kwargs = {k: \"\\n\".join(v) if isinstance(v, list) else v for k, v in kwargs.items()}\n try:\n formated_prompt = prompt_template.format(**kwargs)\n except Exception as exc:\n raise ValueError(f\"Error formatting prompt: {exc}\") from exc\n self.status = f'Prompt:\\n\"{formated_prompt}\"'\n return formated_prompt\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "template": { + "type": "prompt", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "Given a summary of an article, please create two multiple-choice questions that cover the key points and details mentioned. Ensure the questions are clear and provide three options (A, B, C), with one correct answer.\n####\n{summary}\n####", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "template", + "display_name": "Template", + "advanced": false, + "input_types": [ + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "_type": "CustomComponent", + "summary": { + "field_type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "summary", + "display_name": "summary", + "advanced": false, + "input_types": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "type": "str" + } + }, + "description": "Create a prompt template with dynamic variables.", + "icon": "prompts", + "is_input": null, + "is_output": null, + "is_composition": null, + "base_classes": [ + "object", + "str", + "Text" + ], + "name": "", + "display_name": "Prompt", + "documentation": "", + "custom_fields": { + "template": [ + "summary" + ] + }, + "output_types": [ + "Text" + ], + "full_path": null, + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false, + "error": null + }, + "id": "Prompt-gTNiz", + "description": "Create a prompt template with dynamic variables.", + "display_name": "Prompt" + }, + "selected": false, + "width": 384, + "height": 385, + "dragging": false + }, + { + "id": "ChatOutput-EJkG3", + "type": "genericNode", + "position": { + "x": 3722.1747844849388, + "y": 1283.413553222214 + }, + "data": { + "type": "ChatOutput", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional, Union\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.schema import Record\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Interaction Panel.\"\n icon = \"ChatOutput\"\n\n def build(\n self,\n sender: Optional[str] = \"Machine\",\n sender_name: Optional[str] = \"AI\",\n input_value: Optional[str] = None,\n session_id: Optional[str] = None,\n return_record: Optional[bool] = False,\n record_template: Optional[str] = \"{text}\",\n ) -> Union[Text, Record]:\n return super().build(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n session_id=session_id,\n return_record=return_record,\n record_template=record_template,\n )\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "input_value": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Message", + "advanced": false, + "input_types": [ + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "record_template": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "{text}", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "record_template", + "display_name": "Record Template", + "advanced": true, + "dynamic": false, + "info": "In case of Message being a Record, this template will be used to convert it to text.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "return_record": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "return_record", + "display_name": "Return Record", + "advanced": true, + "dynamic": false, + "info": "Return the message as a record containing the sender, sender_name, and session_id.", + "load_from_db": false, + "title_case": false + }, + "sender": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "Machine", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "Machine", + "User" + ], + "name": "sender", + "display_name": "Sender Type", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "sender_name": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "Summarizer", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "sender_name", + "display_name": "Sender Name", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "session_id": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "session_id", + "display_name": "Session ID", + "advanced": true, + "dynamic": false, + "info": "If provided, the message will be stored in the memory.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "_type": "CustomComponent" + }, + "description": "Display a chat message in the Interaction Panel.", + "icon": "ChatOutput", + "base_classes": [ + "object", + "Record", + "Text", + "str" + ], + "display_name": "Chat Output", + "documentation": "", + "custom_fields": { + "sender": null, + "sender_name": null, + "input_value": null, + "session_id": null, + "return_record": null, + "record_template": null + }, + "output_types": [ + "Text", + "Record" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "ChatOutput-EJkG3" + }, + "selected": false, + "width": 384, + "height": 385, + "dragging": false + }, + { + "id": "ChatOutput-DNmvg", + "type": "genericNode", + "position": { + "x": 5077.71285886074, + "y": 1232.9152769735522 + }, + "data": { + "type": "ChatOutput", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional, Union\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.schema import Record\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Interaction Panel.\"\n icon = \"ChatOutput\"\n\n def build(\n self,\n sender: Optional[str] = \"Machine\",\n sender_name: Optional[str] = \"AI\",\n input_value: Optional[str] = None,\n session_id: Optional[str] = None,\n return_record: Optional[bool] = False,\n record_template: Optional[str] = \"{text}\",\n ) -> Union[Text, Record]:\n return super().build(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n session_id=session_id,\n return_record=return_record,\n record_template=record_template,\n )\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "input_value": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Message", + "advanced": false, + "input_types": [ + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "record_template": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "{text}", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "record_template", + "display_name": "Record Template", + "advanced": true, + "dynamic": false, + "info": "In case of Message being a Record, this template will be used to convert it to text.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "return_record": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "return_record", + "display_name": "Return Record", + "advanced": true, + "dynamic": false, + "info": "Return the message as a record containing the sender, sender_name, and session_id.", + "load_from_db": false, + "title_case": false + }, + "sender": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "Machine", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "Machine", + "User" + ], + "name": "sender", + "display_name": "Sender Type", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "sender_name": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "Question Generator", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "sender_name", + "display_name": "Sender Name", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "session_id": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "session_id", + "display_name": "Session ID", + "advanced": true, + "dynamic": false, + "info": "If provided, the message will be stored in the memory.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "_type": "CustomComponent" + }, + "description": "Display a chat message in the Interaction Panel.", + "icon": "ChatOutput", + "base_classes": [ + "object", + "Record", + "Text", + "str" + ], + "display_name": "Chat Output", + "documentation": "", + "custom_fields": { + "sender": null, + "sender_name": null, + "input_value": null, + "session_id": null, + "return_record": null, + "record_template": null + }, + "output_types": [ + "Text", + "Record" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "ChatOutput-DNmvg" + }, + "selected": false, + "width": 384, + "height": 385 + }, + { + "id": "TextInput-sptaH", + "type": "genericNode", + "position": { + "x": 1700.5624822024752, + "y": 1039.603088937466 + }, + "data": { + "type": "TextInput", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional\n\nfrom langflow.base.io.text import TextComponent\nfrom langflow.field_typing import Text\n\n\nclass TextInput(TextComponent):\n display_name = \"Text Input\"\n description = \"Get text inputs from the Interaction Panel.\"\n icon = \"type\"\n\n def build_config(self):\n return {\n \"input_value\": {\n \"display_name\": \"Value\",\n \"input_types\": [\"Record\", \"Text\"],\n \"info\": \"Text or Record to be passed as input.\",\n },\n \"record_template\": {\n \"display_name\": \"Record Template\",\n \"multiline\": True,\n \"info\": \"Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n input_value: Optional[str] = \"\",\n record_template: Optional[str] = \"\",\n ) -> Text:\n return super().build(input_value=input_value, record_template=record_template)\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "input_value": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "Revolutionary Nano-Battery Technology Unveiled In a groundbreaking announcement yesterday, researchers from the fictional Tech Innovations Institute revealed the development of a new nano-battery technology that promises to revolutionize energy storage. The new battery, dubbed the \"EnerGCell\", uses advanced nanomaterials to achieve unprecedented efficiency and storage capacities. According to lead researcher Dr. Ada Byron, the EnerGCell can store up to ten times more energy than the best lithium-ion batteries available today, while charging in just a fraction of the time. \"We're talking about charging your electric vehicle in just five minutes for a range of over 1,000 miles,\" Dr. Byron stated during the press conference. The technology behind the EnerGCell involves a complex arrangement of nanostructured electrodes that allow for rapid ion transfer and extremely high energy density. This breakthrough was achieved after a decade of research into nanomaterials and their applications in energy storage. The implications of this technology are vast, promising to accelerate the adoption of renewable energy by making it more practical and affordable to store wind and solar power. It could also lead to significant advancements in electric vehicles, mobile devices, and any other technology that relies on batteries. Despite the excitement, some experts are calling for patience, noting that the EnerGCell is still in its early stages of development and may take several years before it's commercially available. However, the potential impact of such a technology on the environment and the global economy is undeniable. Tech Innovations Institute plans to continue refining the EnerGCell and begin pilot projects with select partners in the coming year. If successful, this nano-battery technology could indeed be the breakthrough needed to usher in a new era of clean energy and technology.", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Value", + "advanced": false, + "input_types": [ + "Record", + "Text" + ], + "dynamic": false, + "info": "Text or Record to be passed as input.", + "load_from_db": false, + "title_case": false + }, + "record_template": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "record_template", + "display_name": "Record Template", + "advanced": true, + "dynamic": false, + "info": "Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "_type": "CustomComponent" + }, + "description": "Get text inputs from the Interaction Panel.", + "icon": "type", + "base_classes": [ + "str", + "Text", + "object" + ], + "display_name": "Text Input", + "documentation": "", + "custom_fields": { + "input_value": null, + "record_template": null + }, + "output_types": [ + "Text" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "TextInput-sptaH" + }, + "selected": false, + "width": 384, + "height": 290, + "positionAbsolute": { + "x": 1700.5624822024752, + "y": 1039.603088937466 + }, + "dragging": false + }, + { + "id": "TextOutput-2MS4a", + "type": "genericNode", + "position": { + "x": 2917.216113690115, + "y": 513.0058511435552 + }, + "data": { + "type": "TextOutput", + "node": { + "template": { + "input_value": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Value", + "advanced": false, + "input_types": [ + "Record", + "Text" + ], + "dynamic": false, + "info": "Text or Record to be passed as output.", + "load_from_db": false, + "title_case": false + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional\n\nfrom langflow.base.io.text import TextComponent\nfrom langflow.field_typing import Text\n\n\nclass TextOutput(TextComponent):\n display_name = \"Text Output\"\n description = \"Display a text output in the Interaction Panel.\"\n icon = \"type\"\n\n def build_config(self):\n return {\n \"input_value\": {\n \"display_name\": \"Value\",\n \"input_types\": [\"Record\", \"Text\"],\n \"info\": \"Text or Record to be passed as output.\",\n },\n \"record_template\": {\n \"display_name\": \"Record Template\",\n \"multiline\": True,\n \"info\": \"Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.\",\n \"advanced\": True,\n },\n }\n\n def build(self, input_value: Optional[Text] = \"\", record_template: str = \"\") -> Text:\n return super().build(input_value=input_value, record_template=record_template)\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "record_template": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "record_template", + "display_name": "Record Template", + "advanced": true, + "dynamic": false, + "info": "Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "_type": "CustomComponent" + }, + "description": "Display a text output in the Interaction Panel.", + "icon": "type", + "base_classes": [ + "str", + "Text", + "object" + ], + "display_name": "First Prompt", + "documentation": "", + "custom_fields": { + "input_value": null, + "record_template": null + }, + "output_types": [ + "Text" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "TextOutput-2MS4a" + }, + "selected": false, + "width": 384, + "height": 290, + "positionAbsolute": { + "x": 2917.216113690115, + "y": 513.0058511435552 + }, + "dragging": false + }, + { + "id": "OpenAIModel-uYXZJ", + "type": "genericNode", + "position": { + "x": 2925.784767523062, + "y": 933.6465680967775 + }, + "data": { + "type": "OpenAIModel", + "node": { + "template": { + "input_value": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Input", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional\n\nfrom langchain_openai import ChatOpenAI\n\nfrom langflow.base.constants import STREAM_INFO_TEXT\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.field_typing import NestedDict, Text\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n\n field_order = [\n \"max_tokens\",\n \"model_kwargs\",\n \"model_name\",\n \"openai_api_base\",\n \"openai_api_key\",\n \"temperature\",\n \"input_value\",\n \"system_message\",\n \"stream\",\n ]\n\n def build_config(self):\n return {\n \"input_value\": {\"display_name\": \"Input\"},\n \"max_tokens\": {\n \"display_name\": \"Max Tokens\",\n \"advanced\": True,\n },\n \"model_kwargs\": {\n \"display_name\": \"Model Kwargs\",\n \"advanced\": True,\n },\n \"model_name\": {\n \"display_name\": \"Model Name\",\n \"advanced\": False,\n \"options\": [\n \"gpt-4-turbo-preview\",\n \"gpt-3.5-turbo\",\n \"gpt-4-0125-preview\",\n \"gpt-4-1106-preview\",\n \"gpt-4-vision-preview\",\n \"gpt-3.5-turbo-0125\",\n \"gpt-3.5-turbo-1106\",\n ],\n \"value\": \"gpt-4-turbo-preview\",\n },\n \"openai_api_base\": {\n \"display_name\": \"OpenAI API Base\",\n \"advanced\": True,\n \"info\": (\n \"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\n\"\n \"You can change this to use other APIs like JinaChat, LocalAI and Prem.\"\n ),\n },\n \"openai_api_key\": {\n \"display_name\": \"OpenAI API Key\",\n \"info\": \"The OpenAI API Key to use for the OpenAI model.\",\n \"advanced\": False,\n \"password\": True,\n },\n \"temperature\": {\n \"display_name\": \"Temperature\",\n \"advanced\": False,\n \"value\": 0.1,\n },\n \"stream\": {\n \"display_name\": \"Stream\",\n \"info\": STREAM_INFO_TEXT,\n \"advanced\": True,\n },\n \"system_message\": {\n \"display_name\": \"System Message\",\n \"info\": \"System message to pass to the model.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n input_value: Text,\n openai_api_key: str,\n temperature: float,\n model_name: str,\n max_tokens: Optional[int] = 256,\n model_kwargs: NestedDict = {},\n openai_api_base: Optional[str] = None,\n stream: bool = False,\n system_message: Optional[str] = None,\n ) -> Text:\n if not openai_api_base:\n openai_api_base = \"https://api.openai.com/v1\"\n output = ChatOpenAI(\n max_tokens=max_tokens,\n model_kwargs=model_kwargs,\n model=model_name,\n base_url=openai_api_base,\n api_key=openai_api_key,\n temperature=temperature,\n )\n\n return self.get_chat_result(output, stream, input_value, system_message)\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "max_tokens": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 256, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "max_tokens", + "display_name": "Max Tokens", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "model_kwargs": { + "type": "NestedDict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": {}, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "model_kwargs", + "display_name": "Model Kwargs", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "model_name": { + "type": "str", + "required": true, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "gpt-4-turbo-preview", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "gpt-4-turbo-preview", + "gpt-3.5-turbo", + "gpt-4-0125-preview", + "gpt-4-1106-preview", + "gpt-4-vision-preview", + "gpt-3.5-turbo-0125", + "gpt-3.5-turbo-1106" + ], + "name": "model_name", + "display_name": "Model Name", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_api_base": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "openai_api_base", + "display_name": "OpenAI API Base", + "advanced": true, + "dynamic": false, + "info": "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_api_key": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": true, + "name": "openai_api_key", + "display_name": "OpenAI API Key", + "advanced": false, + "dynamic": false, + "info": "The OpenAI API Key to use for the OpenAI model.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ], + "value": "" + }, + "stream": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "stream", + "display_name": "Stream", + "advanced": true, + "dynamic": false, + "info": "Stream the response from the model. Streaming works only in Chat.", + "load_from_db": false, + "title_case": false + }, + "system_message": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "system_message", + "display_name": "System Message", + "advanced": true, + "dynamic": false, + "info": "System message to pass to the model.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "temperature": { + "type": "float", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 0.1, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "temperature", + "display_name": "Temperature", + "advanced": false, + "dynamic": false, + "info": "", + "rangeSpec": { + "step_type": "float", + "min": -1, + "max": 1, + "step": 0.1 + }, + "load_from_db": false, + "title_case": false + }, + "_type": "CustomComponent" + }, + "description": "Generates text using OpenAI LLMs.", + "icon": "OpenAI", + "base_classes": [ + "str", + "Text", + "object" + ], + "display_name": "OpenAI", + "documentation": "", + "custom_fields": { + "input_value": null, + "openai_api_key": null, + "temperature": null, + "model_name": null, + "max_tokens": null, + "model_kwargs": null, + "openai_api_base": null, + "stream": null, + "system_message": null + }, + "output_types": [ + "Text" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [ + "max_tokens", + "model_kwargs", + "model_name", + "openai_api_base", + "openai_api_key", + "temperature", + "input_value", + "system_message", + "stream" + ], + "beta": false + }, + "id": "OpenAIModel-uYXZJ" + }, + "selected": false, + "width": 384, + "height": 565, + "positionAbsolute": { + "x": 2925.784767523062, + "y": 933.6465680967775 + }, + "dragging": false + }, + { + "id": "TextOutput-MUDOR", + "type": "genericNode", + "position": { + "x": 4446.064323520379, + "y": 633.833297518702 + }, + "data": { + "type": "TextOutput", + "node": { + "template": { + "input_value": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Value", + "advanced": false, + "input_types": [ + "Record", + "Text" + ], + "dynamic": false, + "info": "Text or Record to be passed as output.", + "load_from_db": false, + "title_case": false + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional\n\nfrom langflow.base.io.text import TextComponent\nfrom langflow.field_typing import Text\n\n\nclass TextOutput(TextComponent):\n display_name = \"Text Output\"\n description = \"Display a text output in the Interaction Panel.\"\n icon = \"type\"\n\n def build_config(self):\n return {\n \"input_value\": {\n \"display_name\": \"Value\",\n \"input_types\": [\"Record\", \"Text\"],\n \"info\": \"Text or Record to be passed as output.\",\n },\n \"record_template\": {\n \"display_name\": \"Record Template\",\n \"multiline\": True,\n \"info\": \"Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.\",\n \"advanced\": True,\n },\n }\n\n def build(self, input_value: Optional[Text] = \"\", record_template: str = \"\") -> Text:\n return super().build(input_value=input_value, record_template=record_template)\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "record_template": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "record_template", + "display_name": "Record Template", + "advanced": true, + "dynamic": false, + "info": "Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "_type": "CustomComponent" + }, + "description": "Display a text output in the Interaction Panel.", + "icon": "type", + "base_classes": [ + "str", + "Text", + "object" + ], + "display_name": "Second Prompt", + "documentation": "", + "custom_fields": { + "input_value": null, + "record_template": null + }, + "output_types": [ + "Text" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "TextOutput-MUDOR" + }, + "selected": false, + "width": 384, + "height": 290, + "dragging": false, + "positionAbsolute": { + "x": 4446.064323520379, + "y": 633.833297518702 + } + }, + { + "id": "OpenAIModel-XawYB", + "type": "genericNode", + "position": { + "x": 4500.152018344182, + "y": 1027.7382026227656 + }, + "data": { + "type": "OpenAIModel", + "node": { + "template": { + "input_value": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Input", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional\n\nfrom langchain_openai import ChatOpenAI\n\nfrom langflow.base.constants import STREAM_INFO_TEXT\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.field_typing import NestedDict, Text\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n\n field_order = [\n \"max_tokens\",\n \"model_kwargs\",\n \"model_name\",\n \"openai_api_base\",\n \"openai_api_key\",\n \"temperature\",\n \"input_value\",\n \"system_message\",\n \"stream\",\n ]\n\n def build_config(self):\n return {\n \"input_value\": {\"display_name\": \"Input\"},\n \"max_tokens\": {\n \"display_name\": \"Max Tokens\",\n \"advanced\": True,\n },\n \"model_kwargs\": {\n \"display_name\": \"Model Kwargs\",\n \"advanced\": True,\n },\n \"model_name\": {\n \"display_name\": \"Model Name\",\n \"advanced\": False,\n \"options\": [\n \"gpt-4-turbo-preview\",\n \"gpt-3.5-turbo\",\n \"gpt-4-0125-preview\",\n \"gpt-4-1106-preview\",\n \"gpt-4-vision-preview\",\n \"gpt-3.5-turbo-0125\",\n \"gpt-3.5-turbo-1106\",\n ],\n \"value\": \"gpt-4-turbo-preview\",\n },\n \"openai_api_base\": {\n \"display_name\": \"OpenAI API Base\",\n \"advanced\": True,\n \"info\": (\n \"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\n\"\n \"You can change this to use other APIs like JinaChat, LocalAI and Prem.\"\n ),\n },\n \"openai_api_key\": {\n \"display_name\": \"OpenAI API Key\",\n \"info\": \"The OpenAI API Key to use for the OpenAI model.\",\n \"advanced\": False,\n \"password\": True,\n },\n \"temperature\": {\n \"display_name\": \"Temperature\",\n \"advanced\": False,\n \"value\": 0.1,\n },\n \"stream\": {\n \"display_name\": \"Stream\",\n \"info\": STREAM_INFO_TEXT,\n \"advanced\": True,\n },\n \"system_message\": {\n \"display_name\": \"System Message\",\n \"info\": \"System message to pass to the model.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n input_value: Text,\n openai_api_key: str,\n temperature: float,\n model_name: str,\n max_tokens: Optional[int] = 256,\n model_kwargs: NestedDict = {},\n openai_api_base: Optional[str] = None,\n stream: bool = False,\n system_message: Optional[str] = None,\n ) -> Text:\n if not openai_api_base:\n openai_api_base = \"https://api.openai.com/v1\"\n output = ChatOpenAI(\n max_tokens=max_tokens,\n model_kwargs=model_kwargs,\n model=model_name,\n base_url=openai_api_base,\n api_key=openai_api_key,\n temperature=temperature,\n )\n\n return self.get_chat_result(output, stream, input_value, system_message)\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "max_tokens": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 256, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "max_tokens", + "display_name": "Max Tokens", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "model_kwargs": { + "type": "NestedDict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": {}, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "model_kwargs", + "display_name": "Model Kwargs", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "model_name": { + "type": "str", + "required": true, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "gpt-4-turbo-preview", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "gpt-4-turbo-preview", + "gpt-3.5-turbo", + "gpt-4-0125-preview", + "gpt-4-1106-preview", + "gpt-4-vision-preview", + "gpt-3.5-turbo-0125", + "gpt-3.5-turbo-1106" + ], + "name": "model_name", + "display_name": "Model Name", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_api_base": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "openai_api_base", + "display_name": "OpenAI API Base", + "advanced": true, + "dynamic": false, + "info": "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_api_key": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": true, + "name": "openai_api_key", + "display_name": "OpenAI API Key", + "advanced": false, + "dynamic": false, + "info": "The OpenAI API Key to use for the OpenAI model.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ], + "value": "" + }, + "stream": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "stream", + "display_name": "Stream", + "advanced": true, + "dynamic": false, + "info": "Stream the response from the model. Streaming works only in Chat.", + "load_from_db": false, + "title_case": false + }, + "system_message": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "system_message", + "display_name": "System Message", + "advanced": true, + "dynamic": false, + "info": "System message to pass to the model.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "temperature": { + "type": "float", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 0.1, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "temperature", + "display_name": "Temperature", + "advanced": false, + "dynamic": false, + "info": "", + "rangeSpec": { + "step_type": "float", + "min": -1, + "max": 1, + "step": 0.1 + }, + "load_from_db": false, + "title_case": false + }, + "_type": "CustomComponent" + }, + "description": "Generates text using OpenAI LLMs.", + "icon": "OpenAI", + "base_classes": [ + "str", + "Text", + "object" + ], + "display_name": "OpenAI", + "documentation": "", + "custom_fields": { + "input_value": null, + "openai_api_key": null, + "temperature": null, + "model_name": null, + "max_tokens": null, + "model_kwargs": null, + "openai_api_base": null, + "stream": null, + "system_message": null + }, + "output_types": [ + "Text" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [ + "max_tokens", + "model_kwargs", + "model_name", + "openai_api_base", + "openai_api_key", + "temperature", + "input_value", + "system_message", + "stream" + ], + "beta": false + }, + "id": "OpenAIModel-XawYB" + }, + "selected": false, + "width": 384, + "height": 565, + "positionAbsolute": { + "x": 4500.152018344182, + "y": 1027.7382026227656 + }, + "dragging": false + } + ], + "edges": [ + { + "source": "TextInput-sptaH", + "sourceHandle": "{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œTextInputœ,œidœ:œTextInput-sptaHœ}", + "target": "Prompt-amqBu", + "targetHandle": "{œfieldNameœ:œdocumentœ,œidœ:œPrompt-amqBuœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "document", + "id": "Prompt-amqBu", + "inputTypes": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "str", + "Text", + "object" + ], + "dataType": "TextInput", + "id": "TextInput-sptaH" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-TextInput-sptaH{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œTextInputœ,œidœ:œTextInput-sptaHœ}-Prompt-amqBu{œfieldNameœ:œdocumentœ,œidœ:œPrompt-amqBuœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}" + }, + { + "source": "Prompt-amqBu", + "sourceHandle": "{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-amqBuœ}", + "target": "TextOutput-2MS4a", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œTextOutput-2MS4aœ,œinputTypesœ:[œRecordœ,œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "input_value", + "id": "TextOutput-2MS4a", + "inputTypes": [ + "Record", + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "object", + "str", + "Text" + ], + "dataType": "Prompt", + "id": "Prompt-amqBu" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-Prompt-amqBu{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-amqBuœ}-TextOutput-2MS4a{œfieldNameœ:œinput_valueœ,œidœ:œTextOutput-2MS4aœ,œinputTypesœ:[œRecordœ,œTextœ],œtypeœ:œstrœ}" + }, + { + "source": "Prompt-amqBu", + "sourceHandle": "{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-amqBuœ}", + "target": "OpenAIModel-uYXZJ", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-uYXZJœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "input_value", + "id": "OpenAIModel-uYXZJ", + "inputTypes": [ + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "object", + "str", + "Text" + ], + "dataType": "Prompt", + "id": "Prompt-amqBu" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-Prompt-amqBu{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-amqBuœ}-OpenAIModel-uYXZJ{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-uYXZJœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}" + }, + { + "source": "OpenAIModel-uYXZJ", + "sourceHandle": "{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-uYXZJœ}", + "target": "Prompt-gTNiz", + "targetHandle": "{œfieldNameœ:œsummaryœ,œidœ:œPrompt-gTNizœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "summary", + "id": "Prompt-gTNiz", + "inputTypes": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "str", + "Text", + "object" + ], + "dataType": "OpenAIModel", + "id": "OpenAIModel-uYXZJ" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-OpenAIModel-uYXZJ{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-uYXZJœ}-Prompt-gTNiz{œfieldNameœ:œsummaryœ,œidœ:œPrompt-gTNizœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}" + }, + { + "source": "OpenAIModel-uYXZJ", + "sourceHandle": "{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-uYXZJœ}", + "target": "ChatOutput-EJkG3", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-EJkG3œ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "input_value", + "id": "ChatOutput-EJkG3", + "inputTypes": [ + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "str", + "Text", + "object" + ], + "dataType": "OpenAIModel", + "id": "OpenAIModel-uYXZJ" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-OpenAIModel-uYXZJ{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-uYXZJœ}-ChatOutput-EJkG3{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-EJkG3œ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}" + }, + { + "source": "Prompt-gTNiz", + "sourceHandle": "{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-gTNizœ}", + "target": "TextOutput-MUDOR", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œTextOutput-MUDORœ,œinputTypesœ:[œRecordœ,œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "input_value", + "id": "TextOutput-MUDOR", + "inputTypes": [ + "Record", + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "object", + "str", + "Text" + ], + "dataType": "Prompt", + "id": "Prompt-gTNiz" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-Prompt-gTNiz{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-gTNizœ}-TextOutput-MUDOR{œfieldNameœ:œinput_valueœ,œidœ:œTextOutput-MUDORœ,œinputTypesœ:[œRecordœ,œTextœ],œtypeœ:œstrœ}" + }, + { + "source": "Prompt-gTNiz", + "sourceHandle": "{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-gTNizœ}", + "target": "OpenAIModel-XawYB", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-XawYBœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "input_value", + "id": "OpenAIModel-XawYB", + "inputTypes": [ + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "object", + "str", + "Text" + ], + "dataType": "Prompt", + "id": "Prompt-gTNiz" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-Prompt-gTNiz{œbaseClassesœ:[œobjectœ,œstrœ,œTextœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-gTNizœ}-OpenAIModel-XawYB{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-XawYBœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}" + }, + { + "source": "OpenAIModel-XawYB", + "sourceHandle": "{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-XawYBœ}", + "target": "ChatOutput-DNmvg", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-DNmvgœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "input_value", + "id": "ChatOutput-DNmvg", + "inputTypes": [ + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "str", + "Text", + "object" + ], + "dataType": "OpenAIModel", + "id": "OpenAIModel-XawYB" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-OpenAIModel-XawYB{œbaseClassesœ:[œstrœ,œTextœ,œobjectœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-XawYBœ}-ChatOutput-DNmvg{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-DNmvgœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}" + } + ], + "viewport": { + "x": -383.7251879618552, + "y": 69.19813933800037, + "zoom": 0.3105753483695743 + } + }, + "description": "The Prompt Chaining flow chains prompts with LLMs, refining outputs through iterative stages.", + "name": "Prompt Chaining", + "last_tested_version": "1.0.0a0", + "is_component": false +} \ No newline at end of file diff --git a/src/backend/base/langflow/initial_setup/starter_projects/VectorStore-RAG-Flows.json b/src/backend/base/langflow/initial_setup/starter_projects/VectorStore-RAG-Flows.json new file mode 100644 index 000000000..5706a0fbf --- /dev/null +++ b/src/backend/base/langflow/initial_setup/starter_projects/VectorStore-RAG-Flows.json @@ -0,0 +1,3403 @@ +{ + "id": "51e2b78a-199b-4054-9f32-e288eef6924c", + "data": { + "nodes": [ + { + "id": "ChatInput-yxMKE", + "type": "genericNode", + "position": { + "x": 1195.5276981160775, + "y": 209.421875 + }, + "data": { + "type": "ChatInput", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional, Union\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.schema import Record\n\n\nclass ChatInput(ChatComponent):\n display_name = \"Chat Input\"\n description = \"Get chat inputs from the Interaction Panel.\"\n icon = \"ChatInput\"\n\n def build_config(self):\n build_config = super().build_config()\n build_config[\"input_value\"] = {\n \"input_types\": [],\n \"display_name\": \"Message\",\n \"multiline\": True,\n }\n\n return build_config\n\n def build(\n self,\n sender: Optional[str] = \"User\",\n sender_name: Optional[str] = \"User\",\n input_value: Optional[str] = None,\n session_id: Optional[str] = None,\n return_record: Optional[bool] = False,\n ) -> Union[Text, Record]:\n return super().build(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n session_id=session_id,\n return_record=return_record,\n )\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "input_value": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Message", + "advanced": false, + "input_types": [], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "value": "what is a line" + }, + "return_record": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "return_record", + "display_name": "Return Record", + "advanced": true, + "dynamic": false, + "info": "Return the message as a record containing the sender, sender_name, and session_id.", + "load_from_db": false, + "title_case": false + }, + "sender": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "User", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "Machine", + "User" + ], + "name": "sender", + "display_name": "Sender Type", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "sender_name": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "User", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "sender_name", + "display_name": "Sender Name", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "session_id": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "session_id", + "display_name": "Session ID", + "advanced": true, + "dynamic": false, + "info": "If provided, the message will be stored in the memory.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "_type": "CustomComponent" + }, + "description": "Get chat inputs from the Interaction Panel.", + "icon": "ChatInput", + "base_classes": [ + "Text", + "str", + "object", + "Record" + ], + "display_name": "Chat Input", + "documentation": "", + "custom_fields": { + "sender": null, + "sender_name": null, + "input_value": null, + "session_id": null, + "return_record": null + }, + "output_types": [ + "Text", + "Record" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "ChatInput-yxMKE" + }, + "selected": false, + "width": 384, + "height": 383 + }, + { + "id": "TextOutput-BDknO", + "type": "genericNode", + "position": { + "x": 2322.600672827879, + "y": 604.9467307442569 + }, + "data": { + "type": "TextOutput", + "node": { + "template": { + "input_value": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Value", + "advanced": false, + "input_types": [ + "Record", + "Text" + ], + "dynamic": false, + "info": "Text or Record to be passed as output.", + "load_from_db": false, + "title_case": false + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional\n\nfrom langflow.base.io.text import TextComponent\nfrom langflow.field_typing import Text\n\n\nclass TextOutput(TextComponent):\n display_name = \"Text Output\"\n description = \"Display a text output in the Interaction Panel.\"\n icon = \"type\"\n\n def build_config(self):\n return {\n \"input_value\": {\n \"display_name\": \"Value\",\n \"input_types\": [\"Record\", \"Text\"],\n \"info\": \"Text or Record to be passed as output.\",\n },\n \"record_template\": {\n \"display_name\": \"Record Template\",\n \"multiline\": True,\n \"info\": \"Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.\",\n \"advanced\": True,\n },\n }\n\n def build(self, input_value: Optional[Text] = \"\", record_template: str = \"\") -> Text:\n return super().build(input_value=input_value, record_template=record_template)\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "record_template": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "{text}", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "record_template", + "display_name": "Record Template", + "advanced": true, + "dynamic": false, + "info": "Template to convert Record to Text. If left empty, it will be dynamically set to the Record's text key.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "_type": "CustomComponent" + }, + "description": "Display a text output in the Interaction Panel.", + "icon": "type", + "base_classes": [ + "object", + "Text", + "str" + ], + "display_name": "Extracted Chunks", + "documentation": "", + "custom_fields": { + "input_value": null, + "record_template": null + }, + "output_types": [ + "Text" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "TextOutput-BDknO" + }, + "selected": false, + "width": 384, + "height": 289, + "positionAbsolute": { + "x": 2322.600672827879, + "y": 604.9467307442569 + }, + "dragging": false + }, + { + "id": "OpenAIEmbeddings-ZlOk1", + "type": "genericNode", + "position": { + "x": 1183.667250865064, + "y": 687.3171828430261 + }, + "data": { + "type": "OpenAIEmbeddings", + "node": { + "template": { + "allowed_special": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": [], + "fileTypes": [], + "file_path": "", + "password": false, + "name": "allowed_special", + "display_name": "Allowed Special", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "chunk_size": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 1000, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "chunk_size", + "display_name": "Chunk Size", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "client": { + "type": "Any", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "client", + "display_name": "Client", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Any, Dict, List, Optional\n\nfrom langchain_openai.embeddings.base import OpenAIEmbeddings\n\nfrom langflow.field_typing import Embeddings, NestedDict\nfrom langflow.interface.custom.custom_component import CustomComponent\n\n\nclass OpenAIEmbeddingsComponent(CustomComponent):\n display_name = \"OpenAI Embeddings\"\n description = \"Generate embeddings using OpenAI models.\"\n\n def build_config(self):\n return {\n \"allowed_special\": {\n \"display_name\": \"Allowed Special\",\n \"advanced\": True,\n \"field_type\": \"str\",\n \"is_list\": True,\n },\n \"default_headers\": {\n \"display_name\": \"Default Headers\",\n \"advanced\": True,\n \"field_type\": \"dict\",\n },\n \"default_query\": {\n \"display_name\": \"Default Query\",\n \"advanced\": True,\n \"field_type\": \"NestedDict\",\n },\n \"disallowed_special\": {\n \"display_name\": \"Disallowed Special\",\n \"advanced\": True,\n \"field_type\": \"str\",\n \"is_list\": True,\n },\n \"chunk_size\": {\"display_name\": \"Chunk Size\", \"advanced\": True},\n \"client\": {\"display_name\": \"Client\", \"advanced\": True},\n \"deployment\": {\"display_name\": \"Deployment\", \"advanced\": True},\n \"embedding_ctx_length\": {\n \"display_name\": \"Embedding Context Length\",\n \"advanced\": True,\n },\n \"max_retries\": {\"display_name\": \"Max Retries\", \"advanced\": True},\n \"model\": {\n \"display_name\": \"Model\",\n \"advanced\": False,\n \"options\": [\n \"text-embedding-3-small\",\n \"text-embedding-3-large\",\n \"text-embedding-ada-002\",\n ],\n },\n \"model_kwargs\": {\"display_name\": \"Model Kwargs\", \"advanced\": True},\n \"openai_api_base\": {\n \"display_name\": \"OpenAI API Base\",\n \"password\": True,\n \"advanced\": True,\n },\n \"openai_api_key\": {\"display_name\": \"OpenAI API Key\", \"password\": True},\n \"openai_api_type\": {\n \"display_name\": \"OpenAI API Type\",\n \"advanced\": True,\n \"password\": True,\n },\n \"openai_api_version\": {\n \"display_name\": \"OpenAI API Version\",\n \"advanced\": True,\n },\n \"openai_organization\": {\n \"display_name\": \"OpenAI Organization\",\n \"advanced\": True,\n },\n \"openai_proxy\": {\"display_name\": \"OpenAI Proxy\", \"advanced\": True},\n \"request_timeout\": {\"display_name\": \"Request Timeout\", \"advanced\": True},\n \"show_progress_bar\": {\n \"display_name\": \"Show Progress Bar\",\n \"advanced\": True,\n },\n \"skip_empty\": {\"display_name\": \"Skip Empty\", \"advanced\": True},\n \"tiktoken_model_name\": {\n \"display_name\": \"TikToken Model Name\",\n \"advanced\": True,\n },\n \"tiktoken_enable\": {\"display_name\": \"TikToken Enable\", \"advanced\": True},\n }\n\n def build(\n self,\n openai_api_key: str,\n default_headers: Optional[Dict[str, str]] = None,\n default_query: Optional[NestedDict] = {},\n allowed_special: List[str] = [],\n disallowed_special: List[str] = [\"all\"],\n chunk_size: int = 1000,\n client: Optional[Any] = None,\n deployment: str = \"text-embedding-ada-002\",\n embedding_ctx_length: int = 8191,\n max_retries: int = 6,\n model: str = \"text-embedding-ada-002\",\n model_kwargs: NestedDict = {},\n openai_api_base: Optional[str] = None,\n openai_api_type: Optional[str] = None,\n openai_api_version: Optional[str] = None,\n openai_organization: Optional[str] = None,\n openai_proxy: Optional[str] = None,\n request_timeout: Optional[float] = None,\n show_progress_bar: bool = False,\n skip_empty: bool = False,\n tiktoken_enable: bool = True,\n tiktoken_model_name: Optional[str] = None,\n ) -> Embeddings:\n # This is to avoid errors with Vector Stores (e.g Chroma)\n if disallowed_special == [\"all\"]:\n disallowed_special = \"all\" # type: ignore\n\n return OpenAIEmbeddings(\n tiktoken_enabled=tiktoken_enable,\n default_headers=default_headers,\n default_query=default_query,\n allowed_special=set(allowed_special),\n disallowed_special=\"all\",\n chunk_size=chunk_size,\n client=client,\n deployment=deployment,\n embedding_ctx_length=embedding_ctx_length,\n max_retries=max_retries,\n model=model,\n model_kwargs=model_kwargs,\n base_url=openai_api_base,\n api_key=openai_api_key,\n openai_api_type=openai_api_type,\n api_version=openai_api_version,\n organization=openai_organization,\n openai_proxy=openai_proxy,\n timeout=request_timeout,\n show_progress_bar=show_progress_bar,\n skip_empty=skip_empty,\n tiktoken_model_name=tiktoken_model_name,\n )\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "default_headers": { + "type": "dict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "default_headers", + "display_name": "Default Headers", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "default_query": { + "type": "NestedDict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": {}, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "default_query", + "display_name": "Default Query", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "deployment": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "text-embedding-ada-002", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "deployment", + "display_name": "Deployment", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "disallowed_special": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": [ + "all" + ], + "fileTypes": [], + "file_path": "", + "password": false, + "name": "disallowed_special", + "display_name": "Disallowed Special", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "embedding_ctx_length": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 8191, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "embedding_ctx_length", + "display_name": "Embedding Context Length", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "max_retries": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 6, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "max_retries", + "display_name": "Max Retries", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "model": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "text-embedding-ada-002", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "text-embedding-3-small", + "text-embedding-3-large", + "text-embedding-ada-002" + ], + "name": "model", + "display_name": "Model", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "model_kwargs": { + "type": "NestedDict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": {}, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "model_kwargs", + "display_name": "Model Kwargs", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "openai_api_base": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": true, + "name": "openai_api_base", + "display_name": "OpenAI API Base", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_api_key": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": true, + "name": "openai_api_key", + "display_name": "OpenAI API Key", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ], + "value": "" + }, + "openai_api_type": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": true, + "name": "openai_api_type", + "display_name": "OpenAI API Type", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_api_version": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "openai_api_version", + "display_name": "OpenAI API Version", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_organization": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "openai_organization", + "display_name": "OpenAI Organization", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_proxy": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "openai_proxy", + "display_name": "OpenAI Proxy", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "request_timeout": { + "type": "float", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "request_timeout", + "display_name": "Request Timeout", + "advanced": true, + "dynamic": false, + "info": "", + "rangeSpec": { + "step_type": "float", + "min": -1, + "max": 1, + "step": 0.1 + }, + "load_from_db": false, + "title_case": false + }, + "show_progress_bar": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "show_progress_bar", + "display_name": "Show Progress Bar", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "skip_empty": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "skip_empty", + "display_name": "Skip Empty", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "tiktoken_enable": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": true, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "tiktoken_enable", + "display_name": "TikToken Enable", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "tiktoken_model_name": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "tiktoken_model_name", + "display_name": "TikToken Model Name", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "_type": "CustomComponent" + }, + "description": "Generate embeddings using OpenAI models.", + "base_classes": [ + "Embeddings" + ], + "display_name": "OpenAI Embeddings", + "documentation": "", + "custom_fields": { + "openai_api_key": null, + "default_headers": null, + "default_query": null, + "allowed_special": null, + "disallowed_special": null, + "chunk_size": null, + "client": null, + "deployment": null, + "embedding_ctx_length": null, + "max_retries": null, + "model": null, + "model_kwargs": null, + "openai_api_base": null, + "openai_api_type": null, + "openai_api_version": null, + "openai_organization": null, + "openai_proxy": null, + "request_timeout": null, + "show_progress_bar": null, + "skip_empty": null, + "tiktoken_enable": null, + "tiktoken_model_name": null + }, + "output_types": [ + "Embeddings" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "OpenAIEmbeddings-ZlOk1" + }, + "selected": false, + "width": 384, + "height": 383, + "dragging": false + }, + { + "id": "OpenAIModel-EjXlN", + "type": "genericNode", + "position": { + "x": 3410.117202077183, + "y": 431.2038048137648 + }, + "data": { + "type": "OpenAIModel", + "node": { + "template": { + "input_value": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Input", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional\n\nfrom langchain_openai import ChatOpenAI\n\nfrom langflow.base.constants import STREAM_INFO_TEXT\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.field_typing import NestedDict, Text\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n\n field_order = [\n \"max_tokens\",\n \"model_kwargs\",\n \"model_name\",\n \"openai_api_base\",\n \"openai_api_key\",\n \"temperature\",\n \"input_value\",\n \"system_message\",\n \"stream\",\n ]\n\n def build_config(self):\n return {\n \"input_value\": {\"display_name\": \"Input\"},\n \"max_tokens\": {\n \"display_name\": \"Max Tokens\",\n \"advanced\": True,\n },\n \"model_kwargs\": {\n \"display_name\": \"Model Kwargs\",\n \"advanced\": True,\n },\n \"model_name\": {\n \"display_name\": \"Model Name\",\n \"advanced\": False,\n \"options\": [\n \"gpt-4-turbo-preview\",\n \"gpt-3.5-turbo\",\n \"gpt-4-0125-preview\",\n \"gpt-4-1106-preview\",\n \"gpt-4-vision-preview\",\n \"gpt-3.5-turbo-0125\",\n \"gpt-3.5-turbo-1106\",\n ],\n \"value\": \"gpt-4-turbo-preview\",\n },\n \"openai_api_base\": {\n \"display_name\": \"OpenAI API Base\",\n \"advanced\": True,\n \"info\": (\n \"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\n\"\n \"You can change this to use other APIs like JinaChat, LocalAI and Prem.\"\n ),\n },\n \"openai_api_key\": {\n \"display_name\": \"OpenAI API Key\",\n \"info\": \"The OpenAI API Key to use for the OpenAI model.\",\n \"advanced\": False,\n \"password\": True,\n },\n \"temperature\": {\n \"display_name\": \"Temperature\",\n \"advanced\": False,\n \"value\": 0.1,\n },\n \"stream\": {\n \"display_name\": \"Stream\",\n \"info\": STREAM_INFO_TEXT,\n \"advanced\": True,\n },\n \"system_message\": {\n \"display_name\": \"System Message\",\n \"info\": \"System message to pass to the model.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n input_value: Text,\n openai_api_key: str,\n temperature: float,\n model_name: str,\n max_tokens: Optional[int] = 256,\n model_kwargs: NestedDict = {},\n openai_api_base: Optional[str] = None,\n stream: bool = False,\n system_message: Optional[str] = None,\n ) -> Text:\n if not openai_api_base:\n openai_api_base = \"https://api.openai.com/v1\"\n output = ChatOpenAI(\n max_tokens=max_tokens,\n model_kwargs=model_kwargs,\n model=model_name,\n base_url=openai_api_base,\n api_key=openai_api_key,\n temperature=temperature,\n )\n\n return self.get_chat_result(output, stream, input_value, system_message)\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "max_tokens": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 256, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "max_tokens", + "display_name": "Max Tokens", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "model_kwargs": { + "type": "NestedDict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": {}, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "model_kwargs", + "display_name": "Model Kwargs", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "model_name": { + "type": "str", + "required": true, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "gpt-3.5-turbo", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "gpt-4-turbo-preview", + "gpt-3.5-turbo", + "gpt-4-0125-preview", + "gpt-4-1106-preview", + "gpt-4-vision-preview", + "gpt-3.5-turbo-0125", + "gpt-3.5-turbo-1106" + ], + "name": "model_name", + "display_name": "Model Name", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_api_base": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "openai_api_base", + "display_name": "OpenAI API Base", + "advanced": true, + "dynamic": false, + "info": "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_api_key": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": true, + "name": "openai_api_key", + "display_name": "OpenAI API Key", + "advanced": false, + "dynamic": false, + "info": "The OpenAI API Key to use for the OpenAI model.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ], + "value": "" + }, + "stream": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "stream", + "display_name": "Stream", + "advanced": true, + "dynamic": false, + "info": "Stream the response from the model. Streaming works only in Chat.", + "load_from_db": false, + "title_case": false + }, + "system_message": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "system_message", + "display_name": "System Message", + "advanced": true, + "dynamic": false, + "info": "System message to pass to the model.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "temperature": { + "type": "float", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 0.1, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "temperature", + "display_name": "Temperature", + "advanced": false, + "dynamic": false, + "info": "", + "rangeSpec": { + "step_type": "float", + "min": -1, + "max": 1, + "step": 0.1 + }, + "load_from_db": false, + "title_case": false + }, + "_type": "CustomComponent" + }, + "description": "Generates text using OpenAI LLMs.", + "icon": "OpenAI", + "base_classes": [ + "object", + "Text", + "str" + ], + "display_name": "OpenAI", + "documentation": "", + "custom_fields": { + "input_value": null, + "openai_api_key": null, + "temperature": null, + "model_name": null, + "max_tokens": null, + "model_kwargs": null, + "openai_api_base": null, + "stream": null, + "system_message": null + }, + "output_types": [ + "Text" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [ + "max_tokens", + "model_kwargs", + "model_name", + "openai_api_base", + "openai_api_key", + "temperature", + "input_value", + "system_message", + "stream" + ], + "beta": false + }, + "id": "OpenAIModel-EjXlN" + }, + "selected": true, + "width": 384, + "height": 563, + "positionAbsolute": { + "x": 3410.117202077183, + "y": 431.2038048137648 + }, + "dragging": false + }, + { + "id": "Prompt-xeI6K", + "type": "genericNode", + "position": { + "x": 2969.0261961391298, + "y": 442.1613649809069 + }, + "data": { + "type": "Prompt", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from langchain_core.prompts import PromptTemplate\n\nfrom langflow.field_typing import Prompt, TemplateField, Text\nfrom langflow.interface.custom.custom_component import CustomComponent\n\n\nclass PromptComponent(CustomComponent):\n display_name: str = \"Prompt\"\n description: str = \"Create a prompt template with dynamic variables.\"\n icon = \"prompts\"\n\n def build_config(self):\n return {\n \"template\": TemplateField(display_name=\"Template\"),\n \"code\": TemplateField(advanced=True),\n }\n\n def build(\n self,\n template: Prompt,\n **kwargs,\n ) -> Text:\n from langflow.base.prompts.utils import dict_values_to_string\n\n prompt_template = PromptTemplate.from_template(Text(template))\n kwargs = dict_values_to_string(kwargs)\n kwargs = {k: \"\\n\".join(v) if isinstance(v, list) else v for k, v in kwargs.items()}\n try:\n formated_prompt = prompt_template.format(**kwargs)\n except Exception as exc:\n raise ValueError(f\"Error formatting prompt: {exc}\") from exc\n self.status = f'Prompt:\\n\"{formated_prompt}\"'\n return formated_prompt\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "template": { + "type": "prompt", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "{context}\n\n---\n\nGiven the context above, answer the question as best as possible.\n\nQuestion: {question}\n\nAnswer: ", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "template", + "display_name": "Template", + "advanced": false, + "input_types": [ + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "_type": "CustomComponent", + "context": { + "field_type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "context", + "display_name": "context", + "advanced": false, + "input_types": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "type": "str" + }, + "question": { + "field_type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "question", + "display_name": "question", + "advanced": false, + "input_types": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "type": "str" + } + }, + "description": "Create a prompt template with dynamic variables.", + "icon": "prompts", + "is_input": null, + "is_output": null, + "is_composition": null, + "base_classes": [ + "object", + "Text", + "str" + ], + "name": "", + "display_name": "Prompt", + "documentation": "", + "custom_fields": { + "template": [ + "context", + "question" + ] + }, + "output_types": [ + "Text" + ], + "full_path": null, + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false, + "error": null + }, + "id": "Prompt-xeI6K", + "description": "Create a prompt template with dynamic variables.", + "display_name": "Prompt" + }, + "selected": false, + "width": 384, + "height": 477, + "positionAbsolute": { + "x": 2969.0261961391298, + "y": 442.1613649809069 + }, + "dragging": false + }, + { + "id": "ChatOutput-Q39I8", + "type": "genericNode", + "position": { + "x": 3887.2073667611485, + "y": 588.4801225794856 + }, + "data": { + "type": "ChatOutput", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional, Union\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.schema import Record\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Interaction Panel.\"\n icon = \"ChatOutput\"\n\n def build(\n self,\n sender: Optional[str] = \"Machine\",\n sender_name: Optional[str] = \"AI\",\n input_value: Optional[str] = None,\n session_id: Optional[str] = None,\n return_record: Optional[bool] = False,\n record_template: Optional[str] = \"{text}\",\n ) -> Union[Text, Record]:\n return super().build(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n session_id=session_id,\n return_record=return_record,\n record_template=record_template,\n )\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "input_value": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Message", + "advanced": false, + "input_types": [ + "Text" + ], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "record_template": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "{text}", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "record_template", + "display_name": "Record Template", + "advanced": true, + "dynamic": false, + "info": "In case of Message being a Record, this template will be used to convert it to text.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "return_record": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "return_record", + "display_name": "Return Record", + "advanced": true, + "dynamic": false, + "info": "Return the message as a record containing the sender, sender_name, and session_id.", + "load_from_db": false, + "title_case": false + }, + "sender": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "Machine", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "Machine", + "User" + ], + "name": "sender", + "display_name": "Sender Type", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "sender_name": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "AI", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "sender_name", + "display_name": "Sender Name", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "session_id": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "session_id", + "display_name": "Session ID", + "advanced": true, + "dynamic": false, + "info": "If provided, the message will be stored in the memory.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "_type": "CustomComponent" + }, + "description": "Display a chat message in the Interaction Panel.", + "icon": "ChatOutput", + "base_classes": [ + "object", + "Text", + "Record", + "str" + ], + "display_name": "Chat Output", + "documentation": "", + "custom_fields": { + "sender": null, + "sender_name": null, + "input_value": null, + "session_id": null, + "return_record": null, + "record_template": null + }, + "output_types": [ + "Text", + "Record" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "ChatOutput-Q39I8" + }, + "selected": false, + "width": 384, + "height": 383, + "positionAbsolute": { + "x": 3887.2073667611485, + "y": 588.4801225794856 + }, + "dragging": false + }, + { + "id": "File-t0a6a", + "type": "genericNode", + "position": { + "x": 2257.233450682836, + "y": 1747.5389618367233 + }, + "data": { + "type": "File", + "node": { + "template": { + "path": { + "type": "file", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [ + ".txt", + ".md", + ".mdx", + ".csv", + ".json", + ".yaml", + ".yml", + ".xml", + ".html", + ".htm", + ".pdf", + ".docx" + ], + "file_path": "51e2b78a-199b-4054-9f32-e288eef6924c/Langflow conversation.pdf", + "password": false, + "name": "path", + "display_name": "Path", + "advanced": false, + "dynamic": false, + "info": "Supported file types: txt, md, mdx, csv, json, yaml, yml, xml, html, htm, pdf, docx", + "load_from_db": false, + "title_case": false, + "value": "" + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from pathlib import Path\nfrom typing import Any, Dict\n\nfrom langflow.base.data.utils import TEXT_FILE_TYPES, parse_text_file_to_record\nfrom langflow.interface.custom.custom_component import CustomComponent\nfrom langflow.schema import Record\n\n\nclass FileComponent(CustomComponent):\n display_name = \"File\"\n description = \"A generic file loader.\"\n icon = \"file-text\"\n\n def build_config(self) -> Dict[str, Any]:\n return {\n \"path\": {\n \"display_name\": \"Path\",\n \"field_type\": \"file\",\n \"file_types\": TEXT_FILE_TYPES,\n \"info\": f\"Supported file types: {', '.join(TEXT_FILE_TYPES)}\",\n },\n \"silent_errors\": {\n \"display_name\": \"Silent Errors\",\n \"advanced\": True,\n \"info\": \"If true, errors will not raise an exception.\",\n },\n }\n\n def load_file(self, path: str, silent_errors: bool = False) -> Record:\n resolved_path = self.resolve_path(path)\n path_obj = Path(resolved_path)\n extension = path_obj.suffix[1:].lower()\n if extension == \"doc\":\n raise ValueError(\"doc files are not supported. Please save as .docx\")\n if extension not in TEXT_FILE_TYPES:\n raise ValueError(f\"Unsupported file type: {extension}\")\n record = parse_text_file_to_record(resolved_path, silent_errors)\n self.status = record if record else \"No data\"\n return record or Record()\n\n def build(\n self,\n path: str,\n silent_errors: bool = False,\n ) -> Record:\n record = self.load_file(path, silent_errors)\n self.status = record\n return record\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "silent_errors": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "silent_errors", + "display_name": "Silent Errors", + "advanced": true, + "dynamic": false, + "info": "If true, errors will not raise an exception.", + "load_from_db": false, + "title_case": false + }, + "_type": "CustomComponent" + }, + "description": "A generic file loader.", + "icon": "file-text", + "base_classes": [ + "Record" + ], + "display_name": "File", + "documentation": "", + "custom_fields": { + "path": null, + "silent_errors": null + }, + "output_types": [ + "Record" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "File-t0a6a" + }, + "selected": false, + "width": 384, + "height": 281, + "positionAbsolute": { + "x": 2257.233450682836, + "y": 1747.5389618367233 + }, + "dragging": false + }, + { + "id": "RecursiveCharacterTextSplitter-tR9QM", + "type": "genericNode", + "position": { + "x": 2791.013514133929, + "y": 1462.9588953494142 + }, + "data": { + "type": "RecursiveCharacterTextSplitter", + "node": { + "template": { + "inputs": { + "type": "Document", + "required": true, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "inputs", + "display_name": "Input", + "advanced": false, + "input_types": [ + "Document", + "Record" + ], + "dynamic": false, + "info": "The texts to split.", + "load_from_db": false, + "title_case": false + }, + "chunk_overlap": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 200, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "chunk_overlap", + "display_name": "Chunk Overlap", + "advanced": false, + "dynamic": false, + "info": "The amount of overlap between chunks.", + "load_from_db": false, + "title_case": false + }, + "chunk_size": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 1000, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "chunk_size", + "display_name": "Chunk Size", + "advanced": false, + "dynamic": false, + "info": "The maximum length of each chunk.", + "load_from_db": false, + "title_case": false + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional\n\nfrom langchain.text_splitter import RecursiveCharacterTextSplitter\nfrom langchain_core.documents import Document\n\nfrom langflow.interface.custom.custom_component import CustomComponent\nfrom langflow.schema import Record\nfrom langflow.utils.util import build_loader_repr_from_records, unescape_string\n\n\nclass RecursiveCharacterTextSplitterComponent(CustomComponent):\n display_name: str = \"Recursive Character Text Splitter\"\n description: str = \"Split text into chunks of a specified length.\"\n documentation: str = \"https://docs.langflow.org/components/text-splitters#recursivecharactertextsplitter\"\n\n def build_config(self):\n return {\n \"inputs\": {\n \"display_name\": \"Input\",\n \"info\": \"The texts to split.\",\n \"input_types\": [\"Document\", \"Record\"],\n },\n \"separators\": {\n \"display_name\": \"Separators\",\n \"info\": 'The characters to split on.\\nIf left empty defaults to [\"\\\\n\\\\n\", \"\\\\n\", \" \", \"\"].',\n \"is_list\": True,\n },\n \"chunk_size\": {\n \"display_name\": \"Chunk Size\",\n \"info\": \"The maximum length of each chunk.\",\n \"field_type\": \"int\",\n \"value\": 1000,\n },\n \"chunk_overlap\": {\n \"display_name\": \"Chunk Overlap\",\n \"info\": \"The amount of overlap between chunks.\",\n \"field_type\": \"int\",\n \"value\": 200,\n },\n \"code\": {\"show\": False},\n }\n\n def build(\n self,\n inputs: list[Document],\n separators: Optional[list[str]] = None,\n chunk_size: Optional[int] = 1000,\n chunk_overlap: Optional[int] = 200,\n ) -> list[Record]:\n \"\"\"\n Split text into chunks of a specified length.\n\n Args:\n separators (list[str]): The characters to split on.\n chunk_size (int): The maximum length of each chunk.\n chunk_overlap (int): The amount of overlap between chunks.\n length_function (function): The function to use to calculate the length of the text.\n\n Returns:\n list[str]: The chunks of text.\n \"\"\"\n\n if separators == \"\":\n separators = None\n elif separators:\n # check if the separators list has escaped characters\n # if there are escaped characters, unescape them\n separators = [unescape_string(x) for x in separators]\n\n # Make sure chunk_size and chunk_overlap are ints\n if isinstance(chunk_size, str):\n chunk_size = int(chunk_size)\n if isinstance(chunk_overlap, str):\n chunk_overlap = int(chunk_overlap)\n splitter = RecursiveCharacterTextSplitter(\n separators=separators,\n chunk_size=chunk_size,\n chunk_overlap=chunk_overlap,\n )\n documents = []\n for _input in inputs:\n if isinstance(_input, Record):\n documents.append(_input.to_lc_document())\n else:\n documents.append(_input)\n docs = splitter.split_documents(documents)\n records = self.to_records(docs)\n self.repr_value = build_loader_repr_from_records(records)\n return records\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "separators": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "separators", + "display_name": "Separators", + "advanced": false, + "dynamic": false, + "info": "The characters to split on.\nIf left empty defaults to [\"\\n\\n\", \"\\n\", \" \", \"\"].", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ], + "value": [ + "" + ] + }, + "_type": "CustomComponent" + }, + "description": "Split text into chunks of a specified length.", + "base_classes": [ + "Record" + ], + "display_name": "Recursive Character Text Splitter", + "documentation": "https://docs.langflow.org/components/text-splitters#recursivecharactertextsplitter", + "custom_fields": { + "inputs": null, + "separators": null, + "chunk_size": null, + "chunk_overlap": null + }, + "output_types": [ + "Record" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "RecursiveCharacterTextSplitter-tR9QM" + }, + "selected": false, + "width": 384, + "height": 501, + "positionAbsolute": { + "x": 2791.013514133929, + "y": 1462.9588953494142 + }, + "dragging": false + }, + { + "id": "AstraDBSearch-41nRz", + "type": "genericNode", + "position": { + "x": 1723.976434815103, + "y": 277.03317407245913 + }, + "data": { + "type": "AstraDBSearch", + "node": { + "template": { + "embedding": { + "type": "Embeddings", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "embedding", + "display_name": "Embedding", + "advanced": false, + "dynamic": false, + "info": "Embedding to use", + "load_from_db": false, + "title_case": false + }, + "input_value": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Input Value", + "advanced": false, + "dynamic": false, + "info": "Input value to search", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "api_endpoint": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "api_endpoint", + "display_name": "API Endpoint", + "advanced": false, + "dynamic": false, + "info": "API endpoint URL for the Astra DB service.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ], + "value": "" + }, + "batch_size": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "batch_size", + "display_name": "Batch Size", + "advanced": true, + "dynamic": false, + "info": "Optional number of records to process in a single batch.", + "load_from_db": false, + "title_case": false + }, + "bulk_delete_concurrency": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "bulk_delete_concurrency", + "display_name": "Bulk Delete Concurrency", + "advanced": true, + "dynamic": false, + "info": "Optional concurrency level for bulk delete operations.", + "load_from_db": false, + "title_case": false + }, + "bulk_insert_batch_concurrency": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "bulk_insert_batch_concurrency", + "display_name": "Bulk Insert Batch Concurrency", + "advanced": true, + "dynamic": false, + "info": "Optional concurrency level for bulk insert operations.", + "load_from_db": false, + "title_case": false + }, + "bulk_insert_overwrite_concurrency": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "bulk_insert_overwrite_concurrency", + "display_name": "Bulk Insert Overwrite Concurrency", + "advanced": true, + "dynamic": false, + "info": "Optional concurrency level for bulk insert operations that overwrite existing records.", + "load_from_db": false, + "title_case": false + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import List, Optional\n\nfrom langflow.components.vectorstores.AstraDB import AstraDBVectorStoreComponent\nfrom langflow.components.vectorstores.base.model import LCVectorStoreComponent\nfrom langflow.field_typing import Embeddings, Text\nfrom langflow.schema import Record\n\n\nclass AstraDBSearchComponent(LCVectorStoreComponent):\n display_name = \"Astra DB Search\"\n description = \"Searches an existing Astra DB Vector Store.\"\n icon = \"AstraDB\"\n field_order = [\"token\", \"api_endpoint\", \"collection_name\", \"input_value\", \"embedding\"]\n\n def build_config(self):\n return {\n \"search_type\": {\n \"display_name\": \"Search Type\",\n \"options\": [\"Similarity\", \"MMR\"],\n },\n \"input_value\": {\n \"display_name\": \"Input Value\",\n \"info\": \"Input value to search\",\n },\n \"embedding\": {\"display_name\": \"Embedding\", \"info\": \"Embedding to use\"},\n \"collection_name\": {\n \"display_name\": \"Collection Name\",\n \"info\": \"The name of the collection within Astra DB where the vectors will be stored.\",\n },\n \"token\": {\n \"display_name\": \"Token\",\n \"info\": \"Authentication token for accessing Astra DB.\",\n \"password\": True,\n },\n \"api_endpoint\": {\n \"display_name\": \"API Endpoint\",\n \"info\": \"API endpoint URL for the Astra DB service.\",\n },\n \"namespace\": {\n \"display_name\": \"Namespace\",\n \"info\": \"Optional namespace within Astra DB to use for the collection.\",\n \"advanced\": True,\n },\n \"metric\": {\n \"display_name\": \"Metric\",\n \"info\": \"Optional distance metric for vector comparisons in the vector store.\",\n \"advanced\": True,\n },\n \"batch_size\": {\n \"display_name\": \"Batch Size\",\n \"info\": \"Optional number of records to process in a single batch.\",\n \"advanced\": True,\n },\n \"bulk_insert_batch_concurrency\": {\n \"display_name\": \"Bulk Insert Batch Concurrency\",\n \"info\": \"Optional concurrency level for bulk insert operations.\",\n \"advanced\": True,\n },\n \"bulk_insert_overwrite_concurrency\": {\n \"display_name\": \"Bulk Insert Overwrite Concurrency\",\n \"info\": \"Optional concurrency level for bulk insert operations that overwrite existing records.\",\n \"advanced\": True,\n },\n \"bulk_delete_concurrency\": {\n \"display_name\": \"Bulk Delete Concurrency\",\n \"info\": \"Optional concurrency level for bulk delete operations.\",\n \"advanced\": True,\n },\n \"setup_mode\": {\n \"display_name\": \"Setup Mode\",\n \"info\": \"Configuration mode for setting up the vector store, with options like “Sync”, “Async”, or “Off”.\",\n \"options\": [\"Sync\", \"Async\", \"Off\"],\n \"advanced\": True,\n },\n \"pre_delete_collection\": {\n \"display_name\": \"Pre Delete Collection\",\n \"info\": \"Boolean flag to determine whether to delete the collection before creating a new one.\",\n \"advanced\": True,\n },\n \"metadata_indexing_include\": {\n \"display_name\": \"Metadata Indexing Include\",\n \"info\": \"Optional list of metadata fields to include in the indexing.\",\n \"advanced\": True,\n },\n \"metadata_indexing_exclude\": {\n \"display_name\": \"Metadata Indexing Exclude\",\n \"info\": \"Optional list of metadata fields to exclude from the indexing.\",\n \"advanced\": True,\n },\n \"collection_indexing_policy\": {\n \"display_name\": \"Collection Indexing Policy\",\n \"info\": \"Optional dictionary defining the indexing policy for the collection.\",\n \"advanced\": True,\n },\n \"number_of_results\": {\n \"display_name\": \"Number of Results\",\n \"info\": \"Number of results to return.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n embedding: Embeddings,\n collection_name: str,\n input_value: Text,\n token: str,\n api_endpoint: str,\n search_type: str = \"Similarity\",\n number_of_results: int = 4,\n namespace: Optional[str] = None,\n metric: Optional[str] = None,\n batch_size: Optional[int] = None,\n bulk_insert_batch_concurrency: Optional[int] = None,\n bulk_insert_overwrite_concurrency: Optional[int] = None,\n bulk_delete_concurrency: Optional[int] = None,\n setup_mode: str = \"Sync\",\n pre_delete_collection: bool = False,\n metadata_indexing_include: Optional[List[str]] = None,\n metadata_indexing_exclude: Optional[List[str]] = None,\n collection_indexing_policy: Optional[dict] = None,\n ) -> List[Record]:\n vector_store = AstraDBVectorStoreComponent().build(\n embedding=embedding,\n collection_name=collection_name,\n token=token,\n api_endpoint=api_endpoint,\n namespace=namespace,\n metric=metric,\n batch_size=batch_size,\n bulk_insert_batch_concurrency=bulk_insert_batch_concurrency,\n bulk_insert_overwrite_concurrency=bulk_insert_overwrite_concurrency,\n bulk_delete_concurrency=bulk_delete_concurrency,\n setup_mode=setup_mode,\n pre_delete_collection=pre_delete_collection,\n metadata_indexing_include=metadata_indexing_include,\n metadata_indexing_exclude=metadata_indexing_exclude,\n collection_indexing_policy=collection_indexing_policy,\n )\n try:\n return self.search_with_vector_store(input_value, search_type, vector_store, k=number_of_results)\n except KeyError as e:\n if \"content\" in str(e):\n raise ValueError(\n \"You should ingest data through Langflow (or LangChain) to query it in Langflow. Your collection does not contain a field name 'content'.\"\n )\n else:\n raise e\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "collection_indexing_policy": { + "type": "dict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "collection_indexing_policy", + "display_name": "Collection Indexing Policy", + "advanced": true, + "dynamic": false, + "info": "Optional dictionary defining the indexing policy for the collection.", + "load_from_db": false, + "title_case": false + }, + "collection_name": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "collection_name", + "display_name": "Collection Name", + "advanced": false, + "dynamic": false, + "info": "The name of the collection within Astra DB where the vectors will be stored.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ], + "value": "langflow" + }, + "metadata_indexing_exclude": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "metadata_indexing_exclude", + "display_name": "Metadata Indexing Exclude", + "advanced": true, + "dynamic": false, + "info": "Optional list of metadata fields to exclude from the indexing.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "metadata_indexing_include": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "metadata_indexing_include", + "display_name": "Metadata Indexing Include", + "advanced": true, + "dynamic": false, + "info": "Optional list of metadata fields to include in the indexing.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "metric": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "metric", + "display_name": "Metric", + "advanced": true, + "dynamic": false, + "info": "Optional distance metric for vector comparisons in the vector store.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "namespace": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "namespace", + "display_name": "Namespace", + "advanced": true, + "dynamic": false, + "info": "Optional namespace within Astra DB to use for the collection.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "number_of_results": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 4, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "number_of_results", + "display_name": "Number of Results", + "advanced": true, + "dynamic": false, + "info": "Number of results to return.", + "load_from_db": false, + "title_case": false + }, + "pre_delete_collection": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "pre_delete_collection", + "display_name": "Pre Delete Collection", + "advanced": true, + "dynamic": false, + "info": "Boolean flag to determine whether to delete the collection before creating a new one.", + "load_from_db": false, + "title_case": false + }, + "search_type": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "Similarity", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "Similarity", + "MMR" + ], + "name": "search_type", + "display_name": "Search Type", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "setup_mode": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "Sync", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "Sync", + "Async", + "Off" + ], + "name": "setup_mode", + "display_name": "Setup Mode", + "advanced": true, + "dynamic": false, + "info": "Configuration mode for setting up the vector store, with options like “Sync”, “Async”, or “Off”.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "token": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": true, + "name": "token", + "display_name": "Token", + "advanced": false, + "dynamic": false, + "info": "Authentication token for accessing Astra DB.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ], + "value": "" + }, + "_type": "CustomComponent" + }, + "description": "Searches an existing Astra DB Vector Store.", + "icon": "AstraDB", + "base_classes": [ + "Record" + ], + "display_name": "Astra DB Search", + "documentation": "", + "custom_fields": { + "embedding": null, + "collection_name": null, + "input_value": null, + "token": null, + "api_endpoint": null, + "search_type": null, + "number_of_results": null, + "namespace": null, + "metric": null, + "batch_size": null, + "bulk_insert_batch_concurrency": null, + "bulk_insert_overwrite_concurrency": null, + "bulk_delete_concurrency": null, + "setup_mode": null, + "pre_delete_collection": null, + "metadata_indexing_include": null, + "metadata_indexing_exclude": null, + "collection_indexing_policy": null + }, + "output_types": [ + "Record" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [ + "token", + "api_endpoint", + "collection_name", + "input_value", + "embedding" + ], + "beta": false + }, + "id": "AstraDBSearch-41nRz" + }, + "selected": false, + "width": 384, + "height": 713, + "dragging": false, + "positionAbsolute": { + "x": 1723.976434815103, + "y": 277.03317407245913 + } + }, + { + "id": "AstraDB-eUCSS", + "type": "genericNode", + "position": { + "x": 3372.04958055989, + "y": 1611.0742035495277 + }, + "data": { + "type": "AstraDB", + "node": { + "template": { + "embedding": { + "type": "Embeddings", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "embedding", + "display_name": "Embedding", + "advanced": false, + "dynamic": false, + "info": "Embedding to use", + "load_from_db": false, + "title_case": false + }, + "inputs": { + "type": "Record", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "inputs", + "display_name": "Inputs", + "advanced": false, + "dynamic": false, + "info": "Optional list of records to be processed and stored in the vector store.", + "load_from_db": false, + "title_case": false + }, + "api_endpoint": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "api_endpoint", + "display_name": "API Endpoint", + "advanced": false, + "dynamic": false, + "info": "API endpoint URL for the Astra DB service.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ], + "value": "" + }, + "batch_size": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "batch_size", + "display_name": "Batch Size", + "advanced": true, + "dynamic": false, + "info": "Optional number of records to process in a single batch.", + "load_from_db": false, + "title_case": false + }, + "bulk_delete_concurrency": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "bulk_delete_concurrency", + "display_name": "Bulk Delete Concurrency", + "advanced": true, + "dynamic": false, + "info": "Optional concurrency level for bulk delete operations.", + "load_from_db": false, + "title_case": false + }, + "bulk_insert_batch_concurrency": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "bulk_insert_batch_concurrency", + "display_name": "Bulk Insert Batch Concurrency", + "advanced": true, + "dynamic": false, + "info": "Optional concurrency level for bulk insert operations.", + "load_from_db": false, + "title_case": false + }, + "bulk_insert_overwrite_concurrency": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "bulk_insert_overwrite_concurrency", + "display_name": "Bulk Insert Overwrite Concurrency", + "advanced": true, + "dynamic": false, + "info": "Optional concurrency level for bulk insert operations that overwrite existing records.", + "load_from_db": false, + "title_case": false + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import List, Optional\n\nfrom langchain_astradb import AstraDBVectorStore\nfrom langchain_astradb.utils.astradb import SetupMode\n\nfrom langflow.custom import CustomComponent\nfrom langflow.field_typing import Embeddings, VectorStore\nfrom langflow.schema import Record\n\n\nclass AstraDBVectorStoreComponent(CustomComponent):\n display_name = \"Astra DB\"\n description = \"Builds or loads an Astra DB Vector Store.\"\n icon = \"AstraDB\"\n field_order = [\"token\", \"api_endpoint\", \"collection_name\", \"inputs\", \"embedding\"]\n\n def build_config(self):\n return {\n \"inputs\": {\n \"display_name\": \"Inputs\",\n \"info\": \"Optional list of records to be processed and stored in the vector store.\",\n },\n \"embedding\": {\"display_name\": \"Embedding\", \"info\": \"Embedding to use\"},\n \"collection_name\": {\n \"display_name\": \"Collection Name\",\n \"info\": \"The name of the collection within Astra DB where the vectors will be stored.\",\n },\n \"token\": {\n \"display_name\": \"Token\",\n \"info\": \"Authentication token for accessing Astra DB.\",\n \"password\": True,\n },\n \"api_endpoint\": {\n \"display_name\": \"API Endpoint\",\n \"info\": \"API endpoint URL for the Astra DB service.\",\n },\n \"namespace\": {\n \"display_name\": \"Namespace\",\n \"info\": \"Optional namespace within Astra DB to use for the collection.\",\n \"advanced\": True,\n },\n \"metric\": {\n \"display_name\": \"Metric\",\n \"info\": \"Optional distance metric for vector comparisons in the vector store.\",\n \"advanced\": True,\n },\n \"batch_size\": {\n \"display_name\": \"Batch Size\",\n \"info\": \"Optional number of records to process in a single batch.\",\n \"advanced\": True,\n },\n \"bulk_insert_batch_concurrency\": {\n \"display_name\": \"Bulk Insert Batch Concurrency\",\n \"info\": \"Optional concurrency level for bulk insert operations.\",\n \"advanced\": True,\n },\n \"bulk_insert_overwrite_concurrency\": {\n \"display_name\": \"Bulk Insert Overwrite Concurrency\",\n \"info\": \"Optional concurrency level for bulk insert operations that overwrite existing records.\",\n \"advanced\": True,\n },\n \"bulk_delete_concurrency\": {\n \"display_name\": \"Bulk Delete Concurrency\",\n \"info\": \"Optional concurrency level for bulk delete operations.\",\n \"advanced\": True,\n },\n \"setup_mode\": {\n \"display_name\": \"Setup Mode\",\n \"info\": \"Configuration mode for setting up the vector store, with options like “Sync”, “Async”, or “Off”.\",\n \"options\": [\"Sync\", \"Async\", \"Off\"],\n \"advanced\": True,\n },\n \"pre_delete_collection\": {\n \"display_name\": \"Pre Delete Collection\",\n \"info\": \"Boolean flag to determine whether to delete the collection before creating a new one.\",\n \"advanced\": True,\n },\n \"metadata_indexing_include\": {\n \"display_name\": \"Metadata Indexing Include\",\n \"info\": \"Optional list of metadata fields to include in the indexing.\",\n \"advanced\": True,\n },\n \"metadata_indexing_exclude\": {\n \"display_name\": \"Metadata Indexing Exclude\",\n \"info\": \"Optional list of metadata fields to exclude from the indexing.\",\n \"advanced\": True,\n },\n \"collection_indexing_policy\": {\n \"display_name\": \"Collection Indexing Policy\",\n \"info\": \"Optional dictionary defining the indexing policy for the collection.\",\n \"advanced\": True,\n },\n }\n\n def build(\n self,\n embedding: Embeddings,\n token: str,\n api_endpoint: str,\n collection_name: str,\n inputs: Optional[List[Record]] = None,\n namespace: Optional[str] = None,\n metric: Optional[str] = None,\n batch_size: Optional[int] = None,\n bulk_insert_batch_concurrency: Optional[int] = None,\n bulk_insert_overwrite_concurrency: Optional[int] = None,\n bulk_delete_concurrency: Optional[int] = None,\n setup_mode: str = \"Async\",\n pre_delete_collection: bool = False,\n metadata_indexing_include: Optional[List[str]] = None,\n metadata_indexing_exclude: Optional[List[str]] = None,\n collection_indexing_policy: Optional[dict] = None,\n ) -> VectorStore:\n try:\n setup_mode_value = SetupMode[setup_mode.upper()]\n except KeyError:\n raise ValueError(f\"Invalid setup mode: {setup_mode}\")\n if inputs:\n documents = [_input.to_lc_document() for _input in inputs]\n\n vector_store = AstraDBVectorStore.from_documents(\n documents=documents,\n embedding=embedding,\n collection_name=collection_name,\n token=token,\n api_endpoint=api_endpoint,\n namespace=namespace,\n metric=metric,\n batch_size=batch_size,\n bulk_insert_batch_concurrency=bulk_insert_batch_concurrency,\n bulk_insert_overwrite_concurrency=bulk_insert_overwrite_concurrency,\n bulk_delete_concurrency=bulk_delete_concurrency,\n setup_mode=setup_mode_value,\n pre_delete_collection=pre_delete_collection,\n metadata_indexing_include=metadata_indexing_include,\n metadata_indexing_exclude=metadata_indexing_exclude,\n collection_indexing_policy=collection_indexing_policy,\n )\n else:\n vector_store = AstraDBVectorStore(\n embedding=embedding,\n collection_name=collection_name,\n token=token,\n api_endpoint=api_endpoint,\n namespace=namespace,\n metric=metric,\n batch_size=batch_size,\n bulk_insert_batch_concurrency=bulk_insert_batch_concurrency,\n bulk_insert_overwrite_concurrency=bulk_insert_overwrite_concurrency,\n bulk_delete_concurrency=bulk_delete_concurrency,\n setup_mode=setup_mode_value,\n pre_delete_collection=pre_delete_collection,\n metadata_indexing_include=metadata_indexing_include,\n metadata_indexing_exclude=metadata_indexing_exclude,\n collection_indexing_policy=collection_indexing_policy,\n )\n\n return vector_store\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "collection_indexing_policy": { + "type": "dict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "collection_indexing_policy", + "display_name": "Collection Indexing Policy", + "advanced": true, + "dynamic": false, + "info": "Optional dictionary defining the indexing policy for the collection.", + "load_from_db": false, + "title_case": false + }, + "collection_name": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "collection_name", + "display_name": "Collection Name", + "advanced": false, + "dynamic": false, + "info": "The name of the collection within Astra DB where the vectors will be stored.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ], + "value": "langflow" + }, + "metadata_indexing_exclude": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "metadata_indexing_exclude", + "display_name": "Metadata Indexing Exclude", + "advanced": true, + "dynamic": false, + "info": "Optional list of metadata fields to exclude from the indexing.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "metadata_indexing_include": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "metadata_indexing_include", + "display_name": "Metadata Indexing Include", + "advanced": true, + "dynamic": false, + "info": "Optional list of metadata fields to include in the indexing.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "metric": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "metric", + "display_name": "Metric", + "advanced": true, + "dynamic": false, + "info": "Optional distance metric for vector comparisons in the vector store.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "namespace": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "namespace", + "display_name": "Namespace", + "advanced": true, + "dynamic": false, + "info": "Optional namespace within Astra DB to use for the collection.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "pre_delete_collection": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "pre_delete_collection", + "display_name": "Pre Delete Collection", + "advanced": true, + "dynamic": false, + "info": "Boolean flag to determine whether to delete the collection before creating a new one.", + "load_from_db": false, + "title_case": false + }, + "setup_mode": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "Async", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "Sync", + "Async", + "Off" + ], + "name": "setup_mode", + "display_name": "Setup Mode", + "advanced": true, + "dynamic": false, + "info": "Configuration mode for setting up the vector store, with options like “Sync”, “Async”, or “Off”.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "token": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": true, + "name": "token", + "display_name": "Token", + "advanced": false, + "dynamic": false, + "info": "Authentication token for accessing Astra DB.", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ], + "value": "" + }, + "_type": "CustomComponent" + }, + "description": "Builds or loads an Astra DB Vector Store.", + "icon": "AstraDB", + "base_classes": [ + "VectorStore" + ], + "display_name": "Astra DB", + "documentation": "", + "custom_fields": { + "embedding": null, + "token": null, + "api_endpoint": null, + "collection_name": null, + "inputs": null, + "namespace": null, + "metric": null, + "batch_size": null, + "bulk_insert_batch_concurrency": null, + "bulk_insert_overwrite_concurrency": null, + "bulk_delete_concurrency": null, + "setup_mode": null, + "pre_delete_collection": null, + "metadata_indexing_include": null, + "metadata_indexing_exclude": null, + "collection_indexing_policy": null + }, + "output_types": [ + "VectorStore" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [ + "token", + "api_endpoint", + "collection_name", + "inputs", + "embedding" + ], + "beta": false + }, + "id": "AstraDB-eUCSS" + }, + "selected": false, + "width": 384, + "height": 573, + "positionAbsolute": { + "x": 3372.04958055989, + "y": 1611.0742035495277 + }, + "dragging": false + }, + { + "id": "OpenAIEmbeddings-9TPjc", + "type": "genericNode", + "position": { + "x": 2814.0402191223047, + "y": 1955.9268168273086 + }, + "data": { + "type": "OpenAIEmbeddings", + "node": { + "template": { + "allowed_special": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": [], + "fileTypes": [], + "file_path": "", + "password": false, + "name": "allowed_special", + "display_name": "Allowed Special", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "chunk_size": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 1000, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "chunk_size", + "display_name": "Chunk Size", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "client": { + "type": "Any", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "client", + "display_name": "Client", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Any, Dict, List, Optional\n\nfrom langchain_openai.embeddings.base import OpenAIEmbeddings\n\nfrom langflow.field_typing import Embeddings, NestedDict\nfrom langflow.interface.custom.custom_component import CustomComponent\n\n\nclass OpenAIEmbeddingsComponent(CustomComponent):\n display_name = \"OpenAI Embeddings\"\n description = \"Generate embeddings using OpenAI models.\"\n\n def build_config(self):\n return {\n \"allowed_special\": {\n \"display_name\": \"Allowed Special\",\n \"advanced\": True,\n \"field_type\": \"str\",\n \"is_list\": True,\n },\n \"default_headers\": {\n \"display_name\": \"Default Headers\",\n \"advanced\": True,\n \"field_type\": \"dict\",\n },\n \"default_query\": {\n \"display_name\": \"Default Query\",\n \"advanced\": True,\n \"field_type\": \"NestedDict\",\n },\n \"disallowed_special\": {\n \"display_name\": \"Disallowed Special\",\n \"advanced\": True,\n \"field_type\": \"str\",\n \"is_list\": True,\n },\n \"chunk_size\": {\"display_name\": \"Chunk Size\", \"advanced\": True},\n \"client\": {\"display_name\": \"Client\", \"advanced\": True},\n \"deployment\": {\"display_name\": \"Deployment\", \"advanced\": True},\n \"embedding_ctx_length\": {\n \"display_name\": \"Embedding Context Length\",\n \"advanced\": True,\n },\n \"max_retries\": {\"display_name\": \"Max Retries\", \"advanced\": True},\n \"model\": {\n \"display_name\": \"Model\",\n \"advanced\": False,\n \"options\": [\n \"text-embedding-3-small\",\n \"text-embedding-3-large\",\n \"text-embedding-ada-002\",\n ],\n },\n \"model_kwargs\": {\"display_name\": \"Model Kwargs\", \"advanced\": True},\n \"openai_api_base\": {\n \"display_name\": \"OpenAI API Base\",\n \"password\": True,\n \"advanced\": True,\n },\n \"openai_api_key\": {\"display_name\": \"OpenAI API Key\", \"password\": True},\n \"openai_api_type\": {\n \"display_name\": \"OpenAI API Type\",\n \"advanced\": True,\n \"password\": True,\n },\n \"openai_api_version\": {\n \"display_name\": \"OpenAI API Version\",\n \"advanced\": True,\n },\n \"openai_organization\": {\n \"display_name\": \"OpenAI Organization\",\n \"advanced\": True,\n },\n \"openai_proxy\": {\"display_name\": \"OpenAI Proxy\", \"advanced\": True},\n \"request_timeout\": {\"display_name\": \"Request Timeout\", \"advanced\": True},\n \"show_progress_bar\": {\n \"display_name\": \"Show Progress Bar\",\n \"advanced\": True,\n },\n \"skip_empty\": {\"display_name\": \"Skip Empty\", \"advanced\": True},\n \"tiktoken_model_name\": {\n \"display_name\": \"TikToken Model Name\",\n \"advanced\": True,\n },\n \"tiktoken_enable\": {\"display_name\": \"TikToken Enable\", \"advanced\": True},\n }\n\n def build(\n self,\n openai_api_key: str,\n default_headers: Optional[Dict[str, str]] = None,\n default_query: Optional[NestedDict] = {},\n allowed_special: List[str] = [],\n disallowed_special: List[str] = [\"all\"],\n chunk_size: int = 1000,\n client: Optional[Any] = None,\n deployment: str = \"text-embedding-ada-002\",\n embedding_ctx_length: int = 8191,\n max_retries: int = 6,\n model: str = \"text-embedding-ada-002\",\n model_kwargs: NestedDict = {},\n openai_api_base: Optional[str] = None,\n openai_api_type: Optional[str] = None,\n openai_api_version: Optional[str] = None,\n openai_organization: Optional[str] = None,\n openai_proxy: Optional[str] = None,\n request_timeout: Optional[float] = None,\n show_progress_bar: bool = False,\n skip_empty: bool = False,\n tiktoken_enable: bool = True,\n tiktoken_model_name: Optional[str] = None,\n ) -> Embeddings:\n # This is to avoid errors with Vector Stores (e.g Chroma)\n if disallowed_special == [\"all\"]:\n disallowed_special = \"all\" # type: ignore\n\n return OpenAIEmbeddings(\n tiktoken_enabled=tiktoken_enable,\n default_headers=default_headers,\n default_query=default_query,\n allowed_special=set(allowed_special),\n disallowed_special=\"all\",\n chunk_size=chunk_size,\n client=client,\n deployment=deployment,\n embedding_ctx_length=embedding_ctx_length,\n max_retries=max_retries,\n model=model,\n model_kwargs=model_kwargs,\n base_url=openai_api_base,\n api_key=openai_api_key,\n openai_api_type=openai_api_type,\n api_version=openai_api_version,\n organization=openai_organization,\n openai_proxy=openai_proxy,\n timeout=request_timeout,\n show_progress_bar=show_progress_bar,\n skip_empty=skip_empty,\n tiktoken_model_name=tiktoken_model_name,\n )\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "default_headers": { + "type": "dict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "default_headers", + "display_name": "Default Headers", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "default_query": { + "type": "NestedDict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": {}, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "default_query", + "display_name": "Default Query", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "deployment": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "text-embedding-ada-002", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "deployment", + "display_name": "Deployment", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "disallowed_special": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": [ + "all" + ], + "fileTypes": [], + "file_path": "", + "password": false, + "name": "disallowed_special", + "display_name": "Disallowed Special", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "embedding_ctx_length": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 8191, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "embedding_ctx_length", + "display_name": "Embedding Context Length", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "max_retries": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 6, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "max_retries", + "display_name": "Max Retries", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "model": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "text-embedding-ada-002", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "text-embedding-3-small", + "text-embedding-3-large", + "text-embedding-ada-002" + ], + "name": "model", + "display_name": "Model", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "model_kwargs": { + "type": "NestedDict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": {}, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "model_kwargs", + "display_name": "Model Kwargs", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "openai_api_base": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": true, + "name": "openai_api_base", + "display_name": "OpenAI API Base", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_api_key": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": true, + "name": "openai_api_key", + "display_name": "OpenAI API Key", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ], + "value": "" + }, + "openai_api_type": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": true, + "name": "openai_api_type", + "display_name": "OpenAI API Type", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_api_version": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "openai_api_version", + "display_name": "OpenAI API Version", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_organization": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "openai_organization", + "display_name": "OpenAI Organization", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "openai_proxy": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "openai_proxy", + "display_name": "OpenAI Proxy", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "request_timeout": { + "type": "float", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "request_timeout", + "display_name": "Request Timeout", + "advanced": true, + "dynamic": false, + "info": "", + "rangeSpec": { + "step_type": "float", + "min": -1, + "max": 1, + "step": 0.1 + }, + "load_from_db": false, + "title_case": false + }, + "show_progress_bar": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "show_progress_bar", + "display_name": "Show Progress Bar", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "skip_empty": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "skip_empty", + "display_name": "Skip Empty", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "tiktoken_enable": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": true, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "tiktoken_enable", + "display_name": "TikToken Enable", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "tiktoken_model_name": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "tiktoken_model_name", + "display_name": "TikToken Model Name", + "advanced": true, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": [ + "Text" + ] + }, + "_type": "CustomComponent" + }, + "description": "Generate embeddings using OpenAI models.", + "base_classes": [ + "Embeddings" + ], + "display_name": "OpenAI Embeddings", + "documentation": "", + "custom_fields": { + "openai_api_key": null, + "default_headers": null, + "default_query": null, + "allowed_special": null, + "disallowed_special": null, + "chunk_size": null, + "client": null, + "deployment": null, + "embedding_ctx_length": null, + "max_retries": null, + "model": null, + "model_kwargs": null, + "openai_api_base": null, + "openai_api_type": null, + "openai_api_version": null, + "openai_organization": null, + "openai_proxy": null, + "request_timeout": null, + "show_progress_bar": null, + "skip_empty": null, + "tiktoken_enable": null, + "tiktoken_model_name": null + }, + "output_types": [ + "Embeddings" + ], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "OpenAIEmbeddings-9TPjc" + }, + "selected": false, + "width": 384, + "height": 383, + "positionAbsolute": { + "x": 2814.0402191223047, + "y": 1955.9268168273086 + }, + "dragging": false + } + ], + "edges": [ + { + "source": "TextOutput-BDknO", + "target": "Prompt-xeI6K", + "sourceHandle": "{œbaseClassesœ:[œobjectœ,œTextœ,œstrœ],œdataTypeœ:œTextOutputœ,œidœ:œTextOutput-BDknOœ}", + "targetHandle": "{œfieldNameœ:œcontextœ,œidœ:œPrompt-xeI6Kœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-TextOutput-BDknO{œbaseClassesœ:[œobjectœ,œTextœ,œstrœ],œdataTypeœ:œTextOutputœ,œidœ:œTextOutput-BDknOœ}-Prompt-xeI6K{œfieldNameœ:œcontextœ,œidœ:œPrompt-xeI6Kœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "context", + "id": "Prompt-xeI6K", + "inputTypes": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "object", + "Text", + "str" + ], + "dataType": "TextOutput", + "id": "TextOutput-BDknO" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "selected": false + }, + { + "source": "ChatInput-yxMKE", + "target": "Prompt-xeI6K", + "sourceHandle": "{œbaseClassesœ:[œTextœ,œstrœ,œobjectœ,œRecordœ],œdataTypeœ:œChatInputœ,œidœ:œChatInput-yxMKEœ}", + "targetHandle": "{œfieldNameœ:œquestionœ,œidœ:œPrompt-xeI6Kœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-ChatInput-yxMKE{œbaseClassesœ:[œTextœ,œstrœ,œobjectœ,œRecordœ],œdataTypeœ:œChatInputœ,œidœ:œChatInput-yxMKEœ}-Prompt-xeI6K{œfieldNameœ:œquestionœ,œidœ:œPrompt-xeI6Kœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ,œRecordœ,œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "question", + "id": "Prompt-xeI6K", + "inputTypes": [ + "Document", + "BaseOutputParser", + "Record", + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "Text", + "str", + "object", + "Record" + ], + "dataType": "ChatInput", + "id": "ChatInput-yxMKE" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "selected": false + }, + { + "source": "Prompt-xeI6K", + "target": "OpenAIModel-EjXlN", + "sourceHandle": "{œbaseClassesœ:[œobjectœ,œTextœ,œstrœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-xeI6Kœ}", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-EjXlNœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-Prompt-xeI6K{œbaseClassesœ:[œobjectœ,œTextœ,œstrœ],œdataTypeœ:œPromptœ,œidœ:œPrompt-xeI6Kœ}-OpenAIModel-EjXlN{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-EjXlNœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "input_value", + "id": "OpenAIModel-EjXlN", + "inputTypes": [ + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "object", + "Text", + "str" + ], + "dataType": "Prompt", + "id": "Prompt-xeI6K" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "selected": false + }, + { + "source": "OpenAIModel-EjXlN", + "target": "ChatOutput-Q39I8", + "sourceHandle": "{œbaseClassesœ:[œobjectœ,œTextœ,œstrœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-EjXlNœ}", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-Q39I8œ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-OpenAIModel-EjXlN{œbaseClassesœ:[œobjectœ,œTextœ,œstrœ],œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-EjXlNœ}-ChatOutput-Q39I8{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-Q39I8œ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "input_value", + "id": "ChatOutput-Q39I8", + "inputTypes": [ + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "object", + "Text", + "str" + ], + "dataType": "OpenAIModel", + "id": "OpenAIModel-EjXlN" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "selected": false + }, + { + "source": "File-t0a6a", + "target": "RecursiveCharacterTextSplitter-tR9QM", + "sourceHandle": "{œbaseClassesœ:[œRecordœ],œdataTypeœ:œFileœ,œidœ:œFile-t0a6aœ}", + "targetHandle": "{œfieldNameœ:œinputsœ,œidœ:œRecursiveCharacterTextSplitter-tR9QMœ,œinputTypesœ:[œDocumentœ,œRecordœ],œtypeœ:œDocumentœ}", + "id": "reactflow__edge-File-t0a6a{œbaseClassesœ:[œRecordœ],œdataTypeœ:œFileœ,œidœ:œFile-t0a6aœ}-RecursiveCharacterTextSplitter-tR9QM{œfieldNameœ:œinputsœ,œidœ:œRecursiveCharacterTextSplitter-tR9QMœ,œinputTypesœ:[œDocumentœ,œRecordœ],œtypeœ:œDocumentœ}", + "data": { + "targetHandle": { + "fieldName": "inputs", + "id": "RecursiveCharacterTextSplitter-tR9QM", + "inputTypes": [ + "Document", + "Record" + ], + "type": "Document" + }, + "sourceHandle": { + "baseClasses": [ + "Record" + ], + "dataType": "File", + "id": "File-t0a6a" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "selected": false + }, + { + "source": "OpenAIEmbeddings-ZlOk1", + "sourceHandle": "{œbaseClassesœ:[œEmbeddingsœ],œdataTypeœ:œOpenAIEmbeddingsœ,œidœ:œOpenAIEmbeddings-ZlOk1œ}", + "target": "AstraDBSearch-41nRz", + "targetHandle": "{œfieldNameœ:œembeddingœ,œidœ:œAstraDBSearch-41nRzœ,œinputTypesœ:null,œtypeœ:œEmbeddingsœ}", + "data": { + "targetHandle": { + "fieldName": "embedding", + "id": "AstraDBSearch-41nRz", + "inputTypes": null, + "type": "Embeddings" + }, + "sourceHandle": { + "baseClasses": [ + "Embeddings" + ], + "dataType": "OpenAIEmbeddings", + "id": "OpenAIEmbeddings-ZlOk1" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-OpenAIEmbeddings-ZlOk1{œbaseClassesœ:[œEmbeddingsœ],œdataTypeœ:œOpenAIEmbeddingsœ,œidœ:œOpenAIEmbeddings-ZlOk1œ}-AstraDBSearch-41nRz{œfieldNameœ:œembeddingœ,œidœ:œAstraDBSearch-41nRzœ,œinputTypesœ:null,œtypeœ:œEmbeddingsœ}" + }, + { + "source": "ChatInput-yxMKE", + "sourceHandle": "{œbaseClassesœ:[œTextœ,œstrœ,œobjectœ,œRecordœ],œdataTypeœ:œChatInputœ,œidœ:œChatInput-yxMKEœ}", + "target": "AstraDBSearch-41nRz", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œAstraDBSearch-41nRzœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "input_value", + "id": "AstraDBSearch-41nRz", + "inputTypes": [ + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "Text", + "str", + "object", + "Record" + ], + "dataType": "ChatInput", + "id": "ChatInput-yxMKE" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-ChatInput-yxMKE{œbaseClassesœ:[œTextœ,œstrœ,œobjectœ,œRecordœ],œdataTypeœ:œChatInputœ,œidœ:œChatInput-yxMKEœ}-AstraDBSearch-41nRz{œfieldNameœ:œinput_valueœ,œidœ:œAstraDBSearch-41nRzœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}" + }, + { + "source": "RecursiveCharacterTextSplitter-tR9QM", + "sourceHandle": "{œbaseClassesœ:[œRecordœ],œdataTypeœ:œRecursiveCharacterTextSplitterœ,œidœ:œRecursiveCharacterTextSplitter-tR9QMœ}", + "target": "AstraDB-eUCSS", + "targetHandle": "{œfieldNameœ:œinputsœ,œidœ:œAstraDB-eUCSSœ,œinputTypesœ:null,œtypeœ:œRecordœ}", + "data": { + "targetHandle": { + "fieldName": "inputs", + "id": "AstraDB-eUCSS", + "inputTypes": null, + "type": "Record" + }, + "sourceHandle": { + "baseClasses": [ + "Record" + ], + "dataType": "RecursiveCharacterTextSplitter", + "id": "RecursiveCharacterTextSplitter-tR9QM" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-RecursiveCharacterTextSplitter-tR9QM{œbaseClassesœ:[œRecordœ],œdataTypeœ:œRecursiveCharacterTextSplitterœ,œidœ:œRecursiveCharacterTextSplitter-tR9QMœ}-AstraDB-eUCSS{œfieldNameœ:œinputsœ,œidœ:œAstraDB-eUCSSœ,œinputTypesœ:null,œtypeœ:œRecordœ}", + "selected": false + }, + { + "source": "OpenAIEmbeddings-9TPjc", + "sourceHandle": "{œbaseClassesœ:[œEmbeddingsœ],œdataTypeœ:œOpenAIEmbeddingsœ,œidœ:œOpenAIEmbeddings-9TPjcœ}", + "target": "AstraDB-eUCSS", + "targetHandle": "{œfieldNameœ:œembeddingœ,œidœ:œAstraDB-eUCSSœ,œinputTypesœ:null,œtypeœ:œEmbeddingsœ}", + "data": { + "targetHandle": { + "fieldName": "embedding", + "id": "AstraDB-eUCSS", + "inputTypes": null, + "type": "Embeddings" + }, + "sourceHandle": { + "baseClasses": [ + "Embeddings" + ], + "dataType": "OpenAIEmbeddings", + "id": "OpenAIEmbeddings-9TPjc" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-OpenAIEmbeddings-9TPjc{œbaseClassesœ:[œEmbeddingsœ],œdataTypeœ:œOpenAIEmbeddingsœ,œidœ:œOpenAIEmbeddings-9TPjcœ}-AstraDB-eUCSS{œfieldNameœ:œembeddingœ,œidœ:œAstraDB-eUCSSœ,œinputTypesœ:null,œtypeœ:œEmbeddingsœ}", + "selected": false + }, + { + "source": "AstraDBSearch-41nRz", + "sourceHandle": "{œbaseClassesœ:[œRecordœ],œdataTypeœ:œAstraDBSearchœ,œidœ:œAstraDBSearch-41nRzœ}", + "target": "TextOutput-BDknO", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œTextOutput-BDknOœ,œinputTypesœ:[œRecordœ,œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "input_value", + "id": "TextOutput-BDknO", + "inputTypes": [ + "Record", + "Text" + ], + "type": "str" + }, + "sourceHandle": { + "baseClasses": [ + "Record" + ], + "dataType": "AstraDBSearch", + "id": "AstraDBSearch-41nRz" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-AstraDBSearch-41nRz{œbaseClassesœ:[œRecordœ],œdataTypeœ:œAstraDBSearchœ,œidœ:œAstraDBSearch-41nRzœ}-TextOutput-BDknO{œfieldNameœ:œinput_valueœ,œidœ:œTextOutput-BDknOœ,œinputTypesœ:[œRecordœ,œTextœ],œtypeœ:œstrœ}" + } + ], + "viewport": { + "x": -259.6782520315529, + "y": 90.3428735006047, + "zoom": 0.2687057134854984 + } + }, + "description": "Visit https://pre-release.langflow.org/guides/rag-with-astradb for a detailed guide of this project.\nThis project give you both Ingestion and RAG in a single file. You'll need to visit https://astra.datastax.com/ to create an Astra DB instance, your Token and grab an API Endpoint.\nRunning this project requires you to add a file in the Files component, then define a Collection Name and click on the Play icon on the Astra DB component. \n\nAfter the ingestion ends you are ready to click on the Run button at the lower left corner and start asking questions about your data.", + "name": "Vector Store RAG", + "last_tested_version": "1.0.0a0", + "is_component": false +} \ No newline at end of file diff --git a/src/backend/langflow/services/database/__init__.py b/src/backend/base/langflow/interface/__init__.py similarity index 100% rename from src/backend/langflow/services/database/__init__.py rename to src/backend/base/langflow/interface/__init__.py diff --git a/src/backend/langflow/interface/agents/__init__.py b/src/backend/base/langflow/interface/agents/__init__.py similarity index 100% rename from src/backend/langflow/interface/agents/__init__.py rename to src/backend/base/langflow/interface/agents/__init__.py diff --git a/src/backend/langflow/interface/agents/base.py b/src/backend/base/langflow/interface/agents/base.py similarity index 97% rename from src/backend/langflow/interface/agents/base.py rename to src/backend/base/langflow/interface/agents/base.py index 9c0210b27..5d50b3aff 100644 --- a/src/backend/langflow/interface/agents/base.py +++ b/src/backend/base/langflow/interface/agents/base.py @@ -1,14 +1,13 @@ from typing import ClassVar, Dict, List, Optional from langchain.agents import types +from loguru import logger -from langflow.custom.customs import get_custom_nodes from langflow.interface.agents.custom import CUSTOM_AGENTS from langflow.interface.base import LangChainTypeCreator +from langflow.legacy_custom.customs import get_custom_nodes from langflow.services.deps import get_settings_service - from langflow.template.frontend_node.agents import AgentFrontendNode -from loguru import logger from langflow.utils.util import build_template_from_class, build_template_from_method diff --git a/src/backend/langflow/interface/agents/custom.py b/src/backend/base/langflow/interface/agents/custom.py similarity index 98% rename from src/backend/langflow/interface/agents/custom.py rename to src/backend/base/langflow/interface/agents/custom.py index 608a98a9b..142b77139 100644 --- a/src/backend/langflow/interface/agents/custom.py +++ b/src/backend/base/langflow/interface/agents/custom.py @@ -1,11 +1,7 @@ from typing import Any, Optional from langchain.agents import AgentExecutor, ZeroShotAgent -from langchain.agents.agent_toolkits import ( - VectorStoreInfo, - VectorStoreRouterToolkit, - VectorStoreToolkit, -) +from langchain.agents.agent_toolkits import VectorStoreInfo, VectorStoreRouterToolkit, VectorStoreToolkit from langchain.agents.agent_toolkits.vectorstore.prompt import PREFIX as VECTORSTORE_PREFIX from langchain.agents.agent_toolkits.vectorstore.prompt import ROUTER_PREFIX as VECTORSTORE_ROUTER_PREFIX from langchain.agents.mrkl.prompt import FORMAT_INSTRUCTIONS diff --git a/src/backend/langflow/interface/agents/prebuilt.py b/src/backend/base/langflow/interface/agents/prebuilt.py similarity index 100% rename from src/backend/langflow/interface/agents/prebuilt.py rename to src/backend/base/langflow/interface/agents/prebuilt.py diff --git a/src/backend/langflow/interface/base.py b/src/backend/base/langflow/interface/base.py similarity index 100% rename from src/backend/langflow/interface/base.py rename to src/backend/base/langflow/interface/base.py index d535838ac..a300f12f2 100644 --- a/src/backend/langflow/interface/base.py +++ b/src/backend/base/langflow/interface/base.py @@ -1,15 +1,15 @@ from abc import ABC, abstractmethod from typing import Any, Dict, List, Optional, Type, Union -from langchain.chains.base import Chain + from langchain.agents import AgentExecutor -from langflow.services.deps import get_settings_service +from langchain.chains.base import Chain +from loguru import logger from pydantic import BaseModel +from langflow.services.deps import get_settings_service from langflow.template.field.base import TemplateField from langflow.template.frontend_node.base import FrontendNode from langflow.template.template.base import Template -from loguru import logger - # Assuming necessary imports for Field, Template, and FrontendNode classes diff --git a/src/backend/langflow/interface/chains/__init__.py b/src/backend/base/langflow/interface/chains/__init__.py similarity index 100% rename from src/backend/langflow/interface/chains/__init__.py rename to src/backend/base/langflow/interface/chains/__init__.py diff --git a/src/backend/langflow/interface/chains/base.py b/src/backend/base/langflow/interface/chains/base.py similarity index 98% rename from src/backend/langflow/interface/chains/base.py rename to src/backend/base/langflow/interface/chains/base.py index 8017902bd..fb008f0a7 100644 --- a/src/backend/langflow/interface/chains/base.py +++ b/src/backend/base/langflow/interface/chains/base.py @@ -1,15 +1,15 @@ from typing import Any, ClassVar, Dict, List, Optional, Type -from langflow.custom.customs import get_custom_nodes -from langflow.interface.base import LangChainTypeCreator -from langflow.interface.importing.utils import import_class -from langflow.services.deps import get_settings_service - -from langflow.template.frontend_node.chains import ChainFrontendNode -from loguru import logger -from langflow.utils.util import build_template_from_class, build_template_from_method from langchain import chains from langchain_experimental.sql import SQLDatabaseChain +from loguru import logger + +from langflow.interface.base import LangChainTypeCreator +from langflow.interface.importing.utils import import_class +from langflow.legacy_custom.customs import get_custom_nodes +from langflow.services.deps import get_settings_service +from langflow.template.frontend_node.chains import ChainFrontendNode +from langflow.utils.util import build_template_from_class, build_template_from_method # Assuming necessary imports for Field, Template, and FrontendNode classes diff --git a/src/backend/langflow/interface/chains/custom.py b/src/backend/base/langflow/interface/chains/custom.py similarity index 99% rename from src/backend/langflow/interface/chains/custom.py rename to src/backend/base/langflow/interface/chains/custom.py index 27ed646b2..2a72f3471 100644 --- a/src/backend/langflow/interface/chains/custom.py +++ b/src/backend/base/langflow/interface/chains/custom.py @@ -1,13 +1,14 @@ from typing import Dict, Optional, Type, Union +from langchain.base_language import BaseLanguageModel from langchain.chains import ConversationChain +from langchain.chains.question_answering import load_qa_chain from langchain.memory.buffer import ConversationBufferMemory from langchain.schema import BaseMemory -from langflow.interface.base import CustomChain from pydantic.v1 import Field, root_validator -from langchain.chains.question_answering import load_qa_chain + +from langflow.interface.base import CustomChain from langflow.interface.utils import extract_input_variables_from_prompt -from langchain.base_language import BaseLanguageModel DEFAULT_SUFFIX = """" Current conversation: diff --git a/src/backend/langflow/interface/custom/__init__.py b/src/backend/base/langflow/interface/custom/__init__.py similarity index 100% rename from src/backend/langflow/interface/custom/__init__.py rename to src/backend/base/langflow/interface/custom/__init__.py diff --git a/src/backend/base/langflow/interface/custom/attributes.py b/src/backend/base/langflow/interface/custom/attributes.py new file mode 100644 index 000000000..7bcfb5f4b --- /dev/null +++ b/src/backend/base/langflow/interface/custom/attributes.py @@ -0,0 +1,43 @@ +import warnings +from typing import Callable + +import emoji + + +def validate_icon(value: str, *args, **kwargs): + # we are going to use the emoji library to validate the emoji + # emojis can be defined using the :emoji_name: syntax + + if not value.startswith(":") and not value.endswith(":"): + return value + elif not value.startswith(":") or not value.endswith(":"): + # emoji should have both starting and ending colons + # so if one of them is missing, we will raise + raise ValueError(f"Invalid emoji. {value} is not a valid emoji.") + + emoji_value = emoji.emojize(value, variant="emoji_type") + if value == emoji_value: + warnings.warn(f"Invalid emoji. {value} is not a valid emoji.") + return value + return emoji_value + + +def getattr_return_str(value): + return str(value) if value else "" + + +def getattr_return_bool(value): + if isinstance(value, bool): + return value + + +ATTR_FUNC_MAPPING: dict[str, Callable] = { + "display_name": getattr_return_str, + "description": getattr_return_str, + "beta": getattr_return_bool, + "documentation": getattr_return_str, + "icon": validate_icon, + "frozen": getattr_return_bool, + "is_input": getattr_return_bool, + "is_output": getattr_return_bool, +} diff --git a/src/backend/langflow/interface/custom/base.py b/src/backend/base/langflow/interface/custom/base.py similarity index 85% rename from src/backend/langflow/interface/custom/base.py rename to src/backend/base/langflow/interface/custom/base.py index 45a3ea215..573eacba1 100644 --- a/src/backend/langflow/interface/custom/base.py +++ b/src/backend/base/langflow/interface/custom/base.py @@ -1,16 +1,12 @@ from typing import Any, Dict, List, Optional, Type +from loguru import logger from langflow.interface.base import LangChainTypeCreator # from langflow.interface.custom.custom import CustomComponent from langflow.interface.custom.custom_component import CustomComponent -from langflow.template.frontend_node.custom_components import ( - CustomComponentFrontendNode, -) -from loguru import logger - -# Assuming necessary imports for Field, Template, and FrontendNode classes +from langflow.template.frontend_node.custom_components import CustomComponentFrontendNode class CustomComponentCreator(LangChainTypeCreator): @@ -29,7 +25,7 @@ class CustomComponentCreator(LangChainTypeCreator): return self.type_dict def get_signature(self, name: str) -> Optional[Dict]: - from langflow.custom.customs import get_custom_nodes + from langflow.legacy_custom.customs import get_custom_nodes try: if name in get_custom_nodes(self.type_name).keys(): diff --git a/src/backend/langflow/interface/custom/code_parser/__init__.py b/src/backend/base/langflow/interface/custom/code_parser/__init__.py similarity index 100% rename from src/backend/langflow/interface/custom/code_parser/__init__.py rename to src/backend/base/langflow/interface/custom/code_parser/__init__.py diff --git a/src/backend/langflow/interface/custom/code_parser/code_parser.py b/src/backend/base/langflow/interface/custom/code_parser/code_parser.py similarity index 90% rename from src/backend/langflow/interface/custom/code_parser/code_parser.py rename to src/backend/base/langflow/interface/custom/code_parser/code_parser.py index 1ab1021b7..44dbbc1d9 100644 --- a/src/backend/langflow/interface/custom/code_parser/code_parser.py +++ b/src/backend/base/langflow/interface/custom/code_parser/code_parser.py @@ -6,9 +6,10 @@ from typing import Any, Dict, List, Type, Union from cachetools import TTLCache, cachedmethod, keys from fastapi import HTTPException +from loguru import logger - -from langflow.interface.custom.schema import CallableCodeDetails, ClassCodeDetails +from langflow.interface.custom.eval import eval_custom_component_code +from langflow.interface.custom.schema import CallableCodeDetails, ClassCodeDetails, MissingDefault class CodeSyntaxError(HTTPException): @@ -173,7 +174,7 @@ class CodeParser: args += self.parse_keyword_args(node) # Commented out because we don't want kwargs # showing up as fields in the frontend - # args += self.parse_kwargs(node) + args += self.parse_kwargs(node) return args @@ -184,7 +185,7 @@ class CodeParser: num_args = len(node.args.args) num_defaults = len(node.args.defaults) num_missing_defaults = num_args - num_defaults - missing_defaults = [None] * num_missing_defaults + missing_defaults = [MissingDefault()] * num_missing_defaults default_values = [ast.unparse(default).strip("'") if default else None for default in node.args.defaults] # Now check all default values to see if there # are any "None" values in the middle @@ -288,15 +289,28 @@ class CodeParser: method = self.parse_callable_details(stmt) return (method, True) if stmt.name == "__init__" else (method, False) + def get_base_classes(self): + """ + Returns the base classes of the custom component class. + """ + try: + bases = self.execute_and_inspect_classes(self.code) + except Exception as e: + # If the code cannot be executed, return an empty list + logger.exception(e) + bases = [] + raise e + return bases + def parse_classes(self, node: ast.ClassDef) -> None: """ Extracts "classes" from the code, including inheritance and init methods. """ - + bases = self.get_base_classes() or [ast.unparse(b) for b in node.bases] class_details = ClassCodeDetails( name=node.name, doc=ast.get_docstring(node), - bases=[ast.unparse(base) for base in node.bases], + bases=bases, attributes=[], methods=[], init=None, @@ -328,6 +342,18 @@ class CodeParser: } self.data["global_vars"].append(global_var) + def execute_and_inspect_classes(self, code: str): + custom_component_class = eval_custom_component_code(code) + custom_component = custom_component_class() + dunder_class = custom_component.__class__ + # Get the base classes at two levels of inheritance + bases = [] + for base in dunder_class.__bases__: + bases.append(base.__name__) + for bases_base in base.__bases__: + bases.append(bases_base.__name__) + return bases + def parse_code(self) -> Dict[str, Any]: """ Runs all parsing operations and returns the resulting data. diff --git a/src/backend/langflow/interface/custom/code_parser/utils.py b/src/backend/base/langflow/interface/custom/code_parser/utils.py similarity index 77% rename from src/backend/langflow/interface/custom/code_parser/utils.py rename to src/backend/base/langflow/interface/custom/code_parser/utils.py index d9b9def26..0f97b4c7b 100644 --- a/src/backend/langflow/interface/custom/code_parser/utils.py +++ b/src/backend/base/langflow/interface/custom/code_parser/utils.py @@ -14,11 +14,10 @@ def extract_inner_type(return_type: str) -> str: def extract_inner_type_from_generic_alias(return_type: GenericAlias) -> Any: """ - Extracts the inner type from a type hint that is a list. + Extracts the inner type from a type hint that is a list or a Optional. """ if return_type.__origin__ == list: return list(return_type.__args__) - return return_type @@ -36,4 +35,12 @@ def extract_union_types_from_generic_alias(return_type: GenericAlias) -> list: """ Extracts the inner type from a type hint that is a Union. """ + if isinstance(return_type, list): + return [ + _inner_arg + for _type in return_type + for _inner_arg in _type.__args__ + if _inner_arg not in set((Any, type(None), type(Any))) + ] + return list(return_type.__args__) diff --git a/src/backend/langflow/interface/custom/custom_component/__init__.py b/src/backend/base/langflow/interface/custom/custom_component/__init__.py similarity index 100% rename from src/backend/langflow/interface/custom/custom_component/__init__.py rename to src/backend/base/langflow/interface/custom/custom_component/__init__.py diff --git a/src/backend/langflow/interface/custom/custom_component/component.py b/src/backend/base/langflow/interface/custom/custom_component/component.py similarity index 56% rename from src/backend/langflow/interface/custom/custom_component/component.py rename to src/backend/base/langflow/interface/custom/custom_component/component.py index 9053dcb0f..470ebcde8 100644 --- a/src/backend/langflow/interface/custom/custom_component/component.py +++ b/src/backend/base/langflow/interface/custom/custom_component/component.py @@ -1,13 +1,13 @@ -import ast import operator import warnings from typing import Any, ClassVar, Optional -import emoji from cachetools import TTLCache, cachedmethod from fastapi import HTTPException +from langflow.interface.custom.attributes import ATTR_FUNC_MAPPING from langflow.interface.custom.code_parser import CodeParser +from langflow.interface.custom.eval import eval_custom_component_code from langflow.utils import validate @@ -36,10 +36,6 @@ class Component: else: setattr(self, key, value) - # Validate the emoji at the icon field - if hasattr(self, "icon") and self.icon: - self.icon = self.validate_icon(self.icon) - def __setattr__(self, key, value): if key == "_user_id" and hasattr(self, "_user_id"): warnings.warn("user_id is immutable and cannot be changed.") @@ -68,42 +64,27 @@ class Component: return validate.create_function(self.code, self._function_entrypoint_name) - def build_template_config(self, attributes) -> dict: + def build_template_config(self) -> dict: + """ + Builds the template configuration for the custom component. + + Returns: + A dictionary representing the template configuration. + """ + if not self.code: + return {} + + cc_class = eval_custom_component_code(self.code) + component_instance = cc_class() template_config = {} - for item in attributes: - item_name = item.get("name") - - if item_value := item.get("value"): - if "display_name" in item_name: - template_config["display_name"] = ast.literal_eval(item_value) - - elif "description" in item_name: - template_config["description"] = ast.literal_eval(item_value) - - elif "beta" in item_name: - template_config["beta"] = ast.literal_eval(item_value) - - elif "documentation" in item_name: - template_config["documentation"] = ast.literal_eval(item_value) - - elif "icon" in item_name: - icon_str = ast.literal_eval(item_value) - template_config["icon"] = self.validate_icon(icon_str) + for attribute, func in ATTR_FUNC_MAPPING.items(): + if hasattr(component_instance, attribute): + value = getattr(component_instance, attribute) + if value is not None: + template_config[attribute] = func(value=value) return template_config - def validate_icon(self, value: str): - # we are going to use the emoji library to validate the emoji - # emojis can be defined using the :emoji_name: syntax - if not value.startswith(":") or not value.endswith(":"): - warnings.warn("Invalid emoji. Please use the :emoji_name: syntax.") - return value - emoji_value = emoji.emojize(value, variant="emoji_type") - if value == emoji_value: - warnings.warn(f"Invalid emoji. {value} is not a valid emoji.") - return value - return emoji_value - def build(self, *args: Any, **kwargs: Any) -> Any: raise NotImplementedError diff --git a/src/backend/base/langflow/interface/custom/custom_component/custom_component.py b/src/backend/base/langflow/interface/custom/custom_component/custom_component.py new file mode 100644 index 000000000..e6f0c4652 --- /dev/null +++ b/src/backend/base/langflow/interface/custom/custom_component/custom_component.py @@ -0,0 +1,459 @@ +import operator +from pathlib import Path +from typing import TYPE_CHECKING, Any, Callable, ClassVar, List, Optional, Sequence, Union +from uuid import UUID + +import yaml +from cachetools import TTLCache, cachedmethod +from langchain_core.documents import Document +from pydantic import BaseModel + +from langflow.helpers.flow import list_flows, load_flow, run_flow +from langflow.interface.custom.code_parser.utils import ( + extract_inner_type_from_generic_alias, + extract_union_types_from_generic_alias, +) +from langflow.interface.custom.custom_component.component import Component +from langflow.schema import Record +from langflow.schema.dotdict import dotdict +from langflow.services.deps import get_storage_service, get_variable_service, session_scope +from langflow.services.storage.service import StorageService +from langflow.utils import validate + +if TYPE_CHECKING: + from langflow.graph.graph.base import Graph + from langflow.graph.vertex.base import Vertex + from langflow.services.storage.service import StorageService + + +class CustomComponent(Component): + """ + Represents a custom component in Langflow. + + Attributes: + display_name (Optional[str]): The display name of the custom component. + description (Optional[str]): The description of the custom component. + code (Optional[str]): The code of the custom component. + field_config (dict): The field configuration of the custom component. + code_class_base_inheritance (ClassVar[str]): The base class name for the custom component. + function_entrypoint_name (ClassVar[str]): The name of the function entrypoint for the custom component. + function (Optional[Callable]): The function associated with the custom component. + repr_value (Optional[Any]): The representation value of the custom component. + user_id (Optional[Union[UUID, str]]): The user ID associated with the custom component. + status (Optional[Any]): The status of the custom component. + _tree (Optional[dict]): The code tree of the custom component. + """ + + display_name: Optional[str] = None + """The display name of the component. Defaults to None.""" + description: Optional[str] = None + """The description of the component. Defaults to None.""" + icon: Optional[str] = None + """The icon of the component. It should be an emoji. Defaults to None.""" + is_input: Optional[bool] = None + """The input state of the component. Defaults to None. + If True, the component must have a field named 'input_value'.""" + is_output: Optional[bool] = None + """The output state of the component. Defaults to None. + If True, the component must have a field named 'input_value'.""" + code: Optional[str] = None + """The code of the component. Defaults to None.""" + field_config: dict = {} + """The field configuration of the component. Defaults to an empty dictionary.""" + field_order: Optional[List[str]] = None + """The field order of the component. Defaults to an empty list.""" + frozen: Optional[bool] = False + """The default frozen state of the component. Defaults to False.""" + build_parameters: Optional[dict] = None + """The build parameters of the component. Defaults to None.""" + selected_output_type: Optional[str] = None + """The selected output type of the component. Defaults to None.""" + vertex: Optional["Vertex"] = None + """The edge target parameter of the component. Defaults to None.""" + code_class_base_inheritance: ClassVar[str] = "CustomComponent" + function_entrypoint_name: ClassVar[str] = "build" + function: Optional[Callable] = None + repr_value: Optional[Any] = "" + user_id: Optional[Union[UUID, str]] = None + status: Optional[Any] = None + """The status of the component. This is displayed on the frontend. Defaults to None.""" + _flows_records: Optional[List[Record]] = None + + def update_state(self, name: str, value: Any): + if not self.vertex: + raise ValueError("Vertex is not set") + try: + self.vertex.graph.update_state(name=name, record=value, caller=self.vertex.id) + except Exception as e: + raise ValueError(f"Error updating state: {e}") + + def append_state(self, name: str, value: Any): + if not self.vertex: + raise ValueError("Vertex is not set") + try: + self.vertex.graph.append_state(name=name, record=value, caller=self.vertex.id) + except Exception as e: + raise ValueError(f"Error appending state: {e}") + + def get_state(self, name: str): + if not self.vertex: + raise ValueError("Vertex is not set") + try: + return self.vertex.graph.get_state(name=name) + except Exception as e: + raise ValueError(f"Error getting state: {e}") + + _tree: Optional[dict] = None + + def __init__(self, **data): + """ + Initializes a new instance of the CustomComponent class. + + Args: + **data: Additional keyword arguments to initialize the custom component. + """ + self.cache = TTLCache(maxsize=1024, ttl=60) + super().__init__(**data) + + @staticmethod + def resolve_path(path: str) -> str: + """Resolves the path to an absolute path.""" + path_object = Path(path) + if path_object.parts[0] == "~": + path_object = path_object.expanduser() + elif path_object.is_relative_to("."): + path_object = path_object.resolve() + return str(path_object) + + def get_full_path(self, path: str) -> str: + storage_svc: "StorageService" = get_storage_service() + + flow_id, file_name = path.split("/", 1) + return storage_svc.build_full_path(flow_id, file_name) + + @property + def graph(self): + return self.vertex.graph + + def _get_field_order(self): + return self.field_order or list(self.field_config.keys()) + + def custom_repr(self): + """ + Returns the custom representation of the custom component. + + Returns: + str: The custom representation of the custom component. + """ + if self.repr_value == "": + self.repr_value = self.status + if isinstance(self.repr_value, dict): + return yaml.dump(self.repr_value) + if isinstance(self.repr_value, str): + return self.repr_value + if isinstance(self.repr_value, BaseModel) and not isinstance(self.repr_value, Record): + return str(self.repr_value) + return self.repr_value + + def build_config(self): + """ + Builds the configuration for the custom component. + + Returns: + dict: The configuration for the custom component. + """ + return self.field_config + + def update_build_config( + self, + build_config: dotdict, + field_value: Any, + field_name: Optional[str] = None, + ): + build_config[field_name] = field_value + return build_config + + @property + def tree(self): + """ + Gets the code tree of the custom component. + + Returns: + dict: The code tree of the custom component. + """ + return self.get_code_tree(self.code or "") + + def to_records(self, data: Any, keys: Optional[List[str]] = None, silent_errors: bool = False) -> List[Record]: + """ + Converts input data into a list of Record objects. + + Args: + data (Any): The input data to be converted. It can be a single item or a sequence of items. + If the input data is a Langchain Document, text_key and data_key are ignored. + + keys (List[str], optional): The keys to access the text and data values in each item. + It should be a list of strings where the first element is the text key and the second element is the data key. + Defaults to None, in which case the default keys "text" and "data" are used. + + Returns: + List[Record]: A list of Record objects. + + Raises: + ValueError: If the input data is not of a valid type or if the specified keys are not found in the data. + + """ + if not keys: + keys = [] + records = [] + if not isinstance(data, Sequence): + data = [data] + for item in data: + data_dict = {} + if isinstance(item, Document): + data_dict = item.metadata + data_dict["text"] = item.page_content + elif isinstance(item, BaseModel): + model_dump = item.model_dump() + for key in keys: + if silent_errors: + data_dict[key] = model_dump.get(key, "") + else: + try: + data_dict[key] = model_dump[key] + except KeyError: + raise ValueError(f"Key {key} not found in {item}") + + elif isinstance(item, str): + data_dict = {"text": item} + elif isinstance(item, dict): + data_dict = item.copy() + else: + raise ValueError(f"Invalid data type: {type(item)}") + + records.append(Record(data=data_dict)) + + return records + + def create_references_from_records(self, records: List[Record], include_data: bool = False) -> str: + """ + Create references from a list of records. + + Args: + records (List[dict]): A list of records, where each record is a dictionary. + include_data (bool, optional): Whether to include data in the references. Defaults to False. + + Returns: + str: A string containing the references in markdown format. + """ + if not records: + return "" + markdown_string = "---\n" + for record in records: + markdown_string += f"- Text: {record.get_text()}" + if include_data: + markdown_string += f" Data: {record.data}" + markdown_string += "\n" + return markdown_string + + @property + def get_function_entrypoint_args(self) -> list: + """ + Gets the arguments of the function entrypoint for the custom component. + + Returns: + list: The arguments of the function entrypoint. + """ + build_method = self.get_build_method() + if not build_method: + return [] + + args = build_method["args"] + for arg in args: + if not arg.get("type") and arg.get("name") != "self": + # Set the type to Data + arg["type"] = "Data" + return args + + @cachedmethod(operator.attrgetter("cache")) + def get_build_method(self): + """ + Gets the build method for the custom component. + + Returns: + dict: The build method for the custom component. + """ + if not self.code: + return {} + + component_classes = [cls for cls in self.tree["classes"] if self.code_class_base_inheritance in cls["bases"]] + if not component_classes: + return {} + + # Assume the first Component class is the one we're interested in + component_class = component_classes[0] + build_methods = [ + method for method in component_class["methods"] if method["name"] == self.function_entrypoint_name + ] + + return build_methods[0] if build_methods else {} + + @property + def get_function_entrypoint_return_type(self) -> List[Any]: + """ + Gets the return type of the function entrypoint for the custom component. + + Returns: + List[Any]: The return type of the function entrypoint. + """ + build_method = self.get_build_method() + if not build_method or not build_method.get("has_return"): + return [] + return_type = build_method["return_type"] + + # If list or List is in the return type, then we remove it and return the inner type + if hasattr(return_type, "__origin__") and return_type.__origin__ in [ + list, + List, + ]: + return_type = extract_inner_type_from_generic_alias(return_type) + + # If the return type is not a Union, then we just return it as a list + inner_type = return_type[0] if isinstance(return_type, list) else return_type + if not hasattr(inner_type, "__origin__") or inner_type.__origin__ != Union: + return return_type if isinstance(return_type, list) else [return_type] + # If the return type is a Union, then we need to parse it + return_type = extract_union_types_from_generic_alias(return_type) + return return_type + + @property + def get_main_class_name(self): + """ + Gets the main class name of the custom component. + + Returns: + str: The main class name of the custom component. + """ + if not self.code: + return "" + + base_name = self.code_class_base_inheritance + method_name = self.function_entrypoint_name + + classes = [] + for item in self.tree.get("classes", []): + if base_name in item["bases"]: + method_names = [method["name"] for method in item["methods"]] + if method_name in method_names: + classes.append(item["name"]) + + # Get just the first item + return next(iter(classes), "") + + @property + def template_config(self): + """ + Gets the template configuration for the custom component. + + Returns: + dict: The template configuration for the custom component. + """ + return self.build_template_config() + + @property + def variables(self): + """ + Returns the variable for the current user with the specified name. + + Raises: + ValueError: If the user id is not set. + + Returns: + The variable for the current user with the specified name. + """ + + def get_variable(name: str): + if hasattr(self, "_user_id") and not self._user_id: + raise ValueError(f"User id is not set for {self.__class__.__name__}") + variable_service = get_variable_service() # Get service instance + # Retrieve and decrypt the variable by name for the current user + with session_scope() as session: + return variable_service.get_variable(user_id=self._user_id or "", name=name, session=session) + + return get_variable + + def list_key_names(self): + """ + Lists the names of the variables for the current user. + + Raises: + ValueError: If the user id is not set. + + Returns: + List[str]: The names of the variables for the current user. + """ + if hasattr(self, "_user_id") and not self._user_id: + raise ValueError(f"User id is not set for {self.__class__.__name__}") + variable_service = get_variable_service() + + with session_scope() as session: + return variable_service.list_variables(user_id=self._user_id, session=session) + + def index(self, value: int = 0): + """ + Returns a function that returns the value at the given index in the iterable. + + Args: + value (int): The index value. + + Returns: + Callable: A function that returns the value at the given index. + """ + + def get_index(iterable: List[Any]): + return iterable[value] if iterable else iterable + + return get_index + + def get_function(self): + """ + Gets the function associated with the custom component. + + Returns: + Callable: The function associated with the custom component. + """ + return validate.create_function(self.code, self.function_entrypoint_name) + + async def load_flow(self, flow_id: str, tweaks: Optional[dict] = None) -> "Graph": + if not self._user_id: + raise ValueError("Session is invalid") + return await load_flow(user_id=self._user_id, flow_id=flow_id, tweaks=tweaks) + + async def run_flow( + self, + inputs: Optional[Union[dict, List[dict]]] = None, + flow_id: Optional[str] = None, + flow_name: Optional[str] = None, + tweaks: Optional[dict] = None, + ) -> Any: + return await run_flow(inputs=inputs, flow_id=flow_id, flow_name=flow_name, tweaks=tweaks, user_id=self._user_id) + + def list_flows(self) -> List[Record]: + if not self._user_id: + raise ValueError("Session is invalid") + try: + return list_flows(user_id=self._user_id) + except Exception as e: + raise ValueError(f"Error listing flows: {e}") + + def build(self, *args: Any, **kwargs: Any) -> Any: + """ + Builds the custom component. + + Args: + *args: The positional arguments. + **kwargs: The keyword arguments. + + Returns: + Any: The result of the build process. + """ + raise NotImplementedError diff --git a/src/backend/langflow/interface/custom/directory_reader/__init__.py b/src/backend/base/langflow/interface/custom/directory_reader/__init__.py similarity index 100% rename from src/backend/langflow/interface/custom/directory_reader/__init__.py rename to src/backend/base/langflow/interface/custom/directory_reader/__init__.py diff --git a/src/backend/langflow/interface/custom/directory_reader/directory_reader.py b/src/backend/base/langflow/interface/custom/directory_reader/directory_reader.py similarity index 86% rename from src/backend/langflow/interface/custom/directory_reader/directory_reader.py rename to src/backend/base/langflow/interface/custom/directory_reader/directory_reader.py index 7bf55bec8..e9f3f6ceb 100644 --- a/src/backend/langflow/interface/custom/directory_reader/directory_reader.py +++ b/src/backend/base/langflow/interface/custom/directory_reader/directory_reader.py @@ -1,9 +1,11 @@ import ast import os import zlib +from pathlib import Path + +from loguru import logger from langflow.interface.custom.custom_component import CustomComponent -from loguru import logger class CustomComponentPathValueError(ValueError): @@ -76,7 +78,7 @@ class DirectoryReader: component_tuple = (*build_component(component), component) components.append(component_tuple) except Exception as e: - logger.error(f"Error while loading component: {e}") + logger.error(f"Error while loading component { component['name']}: {e}") continue items.append({"name": menu["name"], "path": menu["path"], "components": components}) filtered = [menu for menu in items if menu["components"]] @@ -105,8 +107,15 @@ class DirectoryReader: """ if not os.path.isfile(file_path): return None - with open(file_path, "r") as file: - return file.read() + with open(file_path, "r", encoding="utf-8") as file: + # UnicodeDecodeError: 'charmap' codec can't decode byte 0x9d in position 3069: character maps to + try: + return file.read() + except UnicodeDecodeError: + # This is happening in Windows, so we need to open the file in binary mode + # The file is always just a python file, so we can safely read it as utf-8 + with open(file_path, "rb") as file: + return file.read().decode("utf-8") def get_files(self): """ @@ -116,12 +125,15 @@ class DirectoryReader: raise CustomComponentPathValueError(f"The path needs to start with '{self.base_path}'.") file_list = [] - for root, _, files in os.walk(safe_path): - file_list.extend( - os.path.join(root, filename) - for filename in files - if filename.endswith(".py") and not filename.startswith("__") - ) + safe_path_obj = Path(safe_path) + for file_path in safe_path_obj.rglob("*.py"): + # The other condtion is that it should be + # in the safe_path/[folder]/[file].py format + # any folders below [folder] will be ignored + # basically the parent folder of the file should be a + # folder in the safe_path + if file_path.is_file() and file_path.parent.parent == safe_path_obj and not file_path.name.startswith("__"): + file_list.append(str(file_path)) return file_list def find_menu(self, response, menu_name): @@ -194,7 +206,12 @@ class DirectoryReader: Process a file by validating its content and returning the result and content/error message. """ - file_content = self.read_file_content(file_path) + try: + file_content = self.read_file_content(file_path) + except Exception as exc: + logger.exception(exc) + logger.error(f"Error while reading file {file_path}: {str(exc)}") + return False, f"Could not read {file_path}" if file_content is None: return False, f"Could not read {file_path}" @@ -226,10 +243,10 @@ class DirectoryReader: for file_path in file_paths: menu_name = os.path.basename(os.path.dirname(file_path)) - logger.debug(f"Menu name: {menu_name}") filename = os.path.basename(file_path) validation_result, result_content = self.process_file(file_path) - logger.debug(f"Validation result: {validation_result}") + if not validation_result: + logger.error(f"Error while processing file {file_path}") menu_result = self.find_menu(response, menu_name) or { "name": menu_name, @@ -256,7 +273,7 @@ class DirectoryReader: output_types = [component_name_camelcase] component_info = { - "name": "CustomComponent", + "name": component_name_camelcase, "output_types": output_types, "file": filename, "code": result_content if validation_result else "", @@ -264,7 +281,6 @@ class DirectoryReader: } menu_result["components"].append(component_info) - logger.debug(f"Component info: {component_info}") if menu_result not in response["menu"]: response["menu"].append(menu_result) logger.debug("-------------------- Component menu list built --------------------") @@ -277,5 +293,6 @@ class DirectoryReader: """ custom_component = CustomComponent(code=code) types_list = custom_component.get_function_entrypoint_return_type + # Get the name of types classes return [type_.__name__ for type_ in types_list if hasattr(type_, "__name__")] diff --git a/src/backend/langflow/interface/custom/directory_reader/utils.py b/src/backend/base/langflow/interface/custom/directory_reader/utils.py similarity index 91% rename from src/backend/langflow/interface/custom/directory_reader/utils.py rename to src/backend/base/langflow/interface/custom/directory_reader/utils.py index f1771b2d7..2772cb78c 100644 --- a/src/backend/langflow/interface/custom/directory_reader/utils.py +++ b/src/backend/base/langflow/interface/custom/directory_reader/utils.py @@ -1,6 +1,7 @@ +from loguru import logger + from langflow.interface.custom.directory_reader import DirectoryReader from langflow.template.frontend_node.custom_components import CustomComponentFrontendNode -from loguru import logger def merge_nested_dicts_with_renaming(dict1, dict2): @@ -124,21 +125,23 @@ def get_new_key(dictionary, original_key): def determine_component_name(component): """Determine the name of the component.""" - component_output_types = component["output_types"] - if len(component_output_types) == 1: - return component_output_types[0] - else: - file_name = component.get("file").split(".")[0] - return "".join(word.capitalize() for word in file_name.split("_")) if "_" in file_name else file_name + # component_output_types = component["output_types"] + # if len(component_output_types) == 1: + # return component_output_types[0] + # else: + # file_name = component.get("file").split(".")[0] + # return "".join(word.capitalize() for word in file_name.split("_")) if "_" in file_name else file_name + return component["name"] def build_menu_items(menu_item): """Build menu items for a given menu.""" menu_items = {} + logger.debug(f"Building menu items for {menu_item['name']}") + logger.debug(f"Loading {len(menu_item['components'])} components") for component_name, component_template, component in menu_item["components"]: try: menu_items[component_name] = component_template - logger.debug(f"Added {component_name} to valid menu.") except Exception as exc: logger.error(f"Error loading Component: {component['output_types']}") logger.exception(f"Error while building custom component {component['output_types']}: {exc}") diff --git a/src/backend/base/langflow/interface/custom/eval.py b/src/backend/base/langflow/interface/custom/eval.py new file mode 100644 index 000000000..b36f10d92 --- /dev/null +++ b/src/backend/base/langflow/interface/custom/eval.py @@ -0,0 +1,12 @@ +from typing import TYPE_CHECKING, Type + +from langflow.utils import validate + +if TYPE_CHECKING: + from langflow.interface.custom.custom_component import CustomComponent + + +def eval_custom_component_code(code: str) -> Type["CustomComponent"]: + """Evaluate custom component code""" + class_name = validate.extract_class_name(code) + return validate.create_class(code, class_name) diff --git a/src/backend/langflow/interface/custom/schema.py b/src/backend/base/langflow/interface/custom/schema.py similarity index 80% rename from src/backend/langflow/interface/custom/schema.py rename to src/backend/base/langflow/interface/custom/schema.py index 7c5975150..1636882ef 100644 --- a/src/backend/langflow/interface/custom/schema.py +++ b/src/backend/base/langflow/interface/custom/schema.py @@ -27,3 +27,12 @@ class CallableCodeDetails(BaseModel): body: list return_type: Optional[Any] = None has_return: bool = False + + +class MissingDefault: + """ + A class to represent a missing default value. + """ + + def __repr__(self): + return "MISSING" diff --git a/src/backend/langflow/interface/custom/utils.py b/src/backend/base/langflow/interface/custom/utils.py similarity index 66% rename from src/backend/langflow/interface/custom/utils.py rename to src/backend/base/langflow/interface/custom/utils.py index 2511c08ca..2935a363a 100644 --- a/src/backend/langflow/interface/custom/utils.py +++ b/src/backend/base/langflow/interface/custom/utils.py @@ -3,11 +3,15 @@ import contextlib import re import traceback import warnings -from typing import Any, Dict, List, Optional, Union +from typing import Any, Dict, List, Optional, Tuple, Union from uuid import UUID from fastapi import HTTPException +from loguru import logger +from pydantic import BaseModel + from langflow.field_typing.range_spec import RangeSpec +from langflow.interface.custom.attributes import ATTR_FUNC_MAPPING from langflow.interface.custom.code_parser.utils import extract_inner_type from langflow.interface.custom.custom_component import CustomComponent from langflow.interface.custom.directory_reader.utils import ( @@ -15,13 +19,17 @@ from langflow.interface.custom.directory_reader.utils import ( determine_component_name, merge_nested_dicts_with_renaming, ) -from langflow.interface.importing.utils import eval_custom_component_code +from langflow.interface.custom.eval import eval_custom_component_code +from langflow.interface.custom.schema import MissingDefault +from langflow.schema import dotdict from langflow.template.field.base import TemplateField -from langflow.template.frontend_node.custom_components import ( - CustomComponentFrontendNode, -) +from langflow.template.frontend_node.custom_components import CustomComponentFrontendNode +from langflow.utils import validate from langflow.utils.util import get_base_classes -from loguru import logger + + +class UpdateBuildConfigError(Exception): + pass def add_output_types(frontend_node: CustomComponentFrontendNode, return_types: List[str]): @@ -35,7 +43,9 @@ def add_output_types(frontend_node: CustomComponentFrontendNode, return_types: L "traceback": traceback.format_exc(), }, ) - if hasattr(return_type, "__name__"): + if return_type == str: + return_type = "Text" + elif hasattr(return_type, "__name__"): return_type = return_type.__name__ elif hasattr(return_type, "__class__"): return_type = return_type.__class__.__name__ @@ -58,6 +68,7 @@ def reorder_fields(frontend_node: CustomComponentFrontendNode, field_order: List if field.name not in field_order: reordered_fields.append(field) frontend_node.template.fields = reordered_fields + frontend_node.field_order = field_order def add_base_classes(frontend_node: CustomComponentFrontendNode, return_types: List[str]): @@ -73,6 +84,8 @@ def add_base_classes(frontend_node: CustomComponentFrontendNode, return_types: L ) base_classes = get_base_classes(return_type_instance) + if return_type_instance == str: + base_classes.append("Text") for base_class in base_classes: frontend_node.add_base_class(base_class) @@ -89,7 +102,7 @@ def extract_type_from_optional(field_type): str: The extracted type, or an empty string if no type was found. """ match = re.search(r"\[(.*?)\]$", field_type) - return match[1] if match else None + return match[1] if match else field_type def get_field_properties(extra_field): @@ -97,7 +110,11 @@ def get_field_properties(extra_field): field_name = extra_field["name"] field_type = extra_field.get("type", "str") field_value = extra_field.get("default", "") - field_required = "optional" not in field_type.lower() + # a required field is a field that does not contain + # optional in field_type + # and a field that does not have a default value + field_required = "optional" not in field_type.lower() and isinstance(field_value, MissingDefault) + field_value = field_value if not isinstance(field_value, MissingDefault) else None if not field_required: field_type = extract_type_from_optional(field_type) @@ -110,7 +127,13 @@ def get_field_properties(extra_field): def process_type(field_type: str): if field_type.startswith("list") or field_type.startswith("List"): return extract_inner_type(field_type) - return "prompt" if field_type == "Prompt" else field_type + + # field_type is a string can be Prompt or Code too + # so we just need to lower if it is the case + lowercase_type = field_type.lower() + if lowercase_type in ["prompt", "code"]: + return lowercase_type + return field_type def add_new_custom_field( @@ -130,13 +153,16 @@ def add_new_custom_field( field_value = field_config.pop("value", field_value) field_advanced = field_config.pop("advanced", False) + if field_type == "Dict": + field_type = "dict" + if field_type == "bool" and field_value is None: field_value = False # If options is a list, then it's a dropdown # If options is None, then it's a list of strings is_list = isinstance(field_config.get("options"), list) - field_config["is_list"] = is_list or field_config.get("is_list", False) or field_contains_list + field_config["is_list"] = is_list or field_config.get("list", False) or field_contains_list if "name" in field_config: warnings.warn("The 'name' key in field_config is used to build the object and can't be changed.") @@ -165,13 +191,21 @@ def add_extra_fields(frontend_node, field_config, function_args): """Add extra fields to the frontend node""" if not function_args: return + _field_config = field_config.copy() + function_args_names = [arg["name"] for arg in function_args] + # If kwargs is in the function_args and not all field_config keys are in function_args + # then we need to add the extra fields for extra_field in function_args: - if "name" not in extra_field or extra_field["name"] == "self": + if "name" not in extra_field or extra_field["name"] in [ + "self", + "kwargs", + "args", + ]: continue field_name, field_type, field_value, field_required = get_field_properties(extra_field) - config = field_config.get(field_name, {}) + config = _field_config.pop(field_name, {}) frontend_node = add_new_custom_field( frontend_node, field_name, @@ -180,25 +214,39 @@ def add_extra_fields(frontend_node, field_config, function_args): field_required, config, ) + if "kwargs" in function_args_names and not all(key in function_args_names for key in field_config.keys()): + for field_name, field_config in _field_config.copy().items(): + if "name" not in field_config or field_name == "code": + continue + config = _field_config.get(field_name, {}) + config = config.model_dump() if isinstance(config, BaseModel) else config + field_name, field_type, field_value, field_required = get_field_properties(extra_field=config) + frontend_node = add_new_custom_field( + frontend_node, + field_name, + field_type, + field_value, + field_required, + config, + ) def get_field_dict(field: Union[TemplateField, dict]): """Get the field dictionary from a TemplateField or a dict""" if isinstance(field, TemplateField): - return field.model_dump(by_alias=True, exclude_none=True) + return dotdict(field.model_dump(by_alias=True, exclude_none=True)) return field def run_build_config( custom_component: CustomComponent, user_id: Optional[Union[str, UUID]] = None, - update_field=None, -): +) -> Tuple[dict, CustomComponent]: """Build the field configuration for a custom component""" try: if custom_component.code is None: - return {} + raise ValueError("Code is None") elif isinstance(custom_component.code, str): custom_class = eval_custom_component_code(custom_component.code) else: @@ -217,43 +265,30 @@ def run_build_config( custom_instance = custom_class(user_id=user_id) build_config: Dict = custom_instance.build_config() - for field_name, field in build_config.items(): + for field_name, field in build_config.copy().items(): # Allow user to build TemplateField as well # as a dict with the same keys as TemplateField field_dict = get_field_dict(field) - if update_field is not None and field_name != update_field: - continue - try: - update_field_dict(field_dict) - build_config[field_name] = field_dict - except Exception as exc: - logger.error(f"Error while getting build_config: {str(exc)}") + # Let's check if "rangeSpec" is a RangeSpec object + if "rangeSpec" in field_dict and isinstance(field_dict["rangeSpec"], RangeSpec): + field_dict["rangeSpec"] = field_dict["rangeSpec"].model_dump() + build_config[field_name] = field_dict return build_config, custom_instance except Exception as exc: logger.error(f"Error while building field config: {str(exc)}") - raise HTTPException( - status_code=400, - detail={ - "error": ("Invalid type convertion. Please check your code and try again."), - "traceback": traceback.format_exc(), - }, - ) from exc + if hasattr(exc, "detail") and "traceback" in exc.detail: + logger.error(exc.detail["traceback"]) + + raise exc def sanitize_template_config(template_config): """Sanitize the template config""" - attributes = { - "display_name", - "description", - "beta", - "documentation", - "output_types", - "icon", - } + for key in template_config.copy(): - if key not in attributes: + if key not in ATTR_FUNC_MAPPING.keys(): template_config.pop(key, None) return template_config @@ -278,7 +313,7 @@ def add_code_field(frontend_node: CustomComponentFrontendNode, raw_code, field_c value=raw_code, password=False, name="code", - advanced=field_config.pop("advanced", False), + advanced=True, field_type="code", is_list=False, ) @@ -290,38 +325,35 @@ def add_code_field(frontend_node: CustomComponentFrontendNode, raw_code, field_c def build_custom_component_template( custom_component: CustomComponent, user_id: Optional[Union[str, UUID]] = None, - update_field: Optional[str] = None, -) -> Optional[Dict[str, Any]]: +) -> Tuple[Dict[str, Any], CustomComponent]: """Build a custom component template for the langchain""" try: - logger.debug("Building custom component template") frontend_node = build_frontend_node(custom_component.template_config) - logger.debug("Built base frontend node") + field_config, custom_instance = run_build_config( + custom_component, + user_id=user_id, + ) - logger.debug("Updated attributes") - field_config, custom_instance = run_build_config(custom_component, user_id=user_id, update_field=update_field) - logger.debug("Built field config") entrypoint_args = custom_component.get_function_entrypoint_args add_extra_fields(frontend_node, field_config, entrypoint_args) - logger.debug("Added extra fields") + frontend_node = add_code_field(frontend_node, custom_component.code, field_config.get("code", {})) - logger.debug("Added code field") + add_base_classes(frontend_node, custom_component.get_function_entrypoint_return_type) add_output_types(frontend_node, custom_component.get_function_entrypoint_return_type) - logger.debug("Added base classes") reorder_fields(frontend_node, custom_instance._get_field_order()) - return frontend_node.to_dict(add_name=False) + return frontend_node.to_dict(add_name=False), custom_instance except Exception as exc: if isinstance(exc, HTTPException): raise exc raise HTTPException( status_code=400, detail={ - "error": ("Invalid type convertion. Please check your code and try again."), + "error": (f"Something went wrong while building the custom component. Hints: {str(exc)}"), "traceback": traceback.format_exc(), }, ) from exc @@ -334,20 +366,22 @@ def create_component_template(component): component_extractor = CustomComponent(code=component_code) - component_template = build_custom_component_template(component_extractor) - component_template["output_types"] = component_output_types + component_template, _ = build_custom_component_template(component_extractor) + if not component_template["output_types"] and component_output_types: + component_template["output_types"] = component_output_types + return component_template -def build_custom_components(settings_service): +def build_custom_components(components_paths: List[str]): """Build custom components from the specified paths.""" - if not settings_service.settings.COMPONENTS_PATH: + if not components_paths: return {} - logger.info(f"Building custom components from {settings_service.settings.COMPONENTS_PATH}") - custom_components_from_file = {} + logger.info(f"Building custom components from {components_paths}") + custom_components_from_file: dict = {} processed_paths = set() - for path in settings_service.settings.COMPONENTS_PATH: + for path in components_paths: path_str = str(path) if path_str in processed_paths: continue @@ -364,24 +398,43 @@ def build_custom_components(settings_service): return custom_components_from_file -def update_field_dict(field_dict): +def update_field_dict( + custom_component_instance: "CustomComponent", + field_dict: Dict, + build_config: Dict, + update_field: Optional[str] = None, + update_field_value: Optional[Any] = None, + call: bool = False, +): """Update the field dictionary by calling options() or value() if they are callable""" - if "options" in field_dict and callable(field_dict["options"]): - field_dict["options"] = field_dict["options"]() - # Also update the "refresh" key - field_dict["refresh"] = True + if ("real_time_refresh" in field_dict or "refresh_button" in field_dict) and any( + ( + field_dict.get("real_time_refresh", False), + field_dict.get("refresh_button", False), + ) + ): + if call: + try: + dd_build_config = dotdict(build_config) + custom_component_instance.update_build_config( + build_config=dd_build_config, + field_value=update_field, + field_name=update_field_value, + ) + build_config = dd_build_config + except Exception as exc: + logger.error(f"Error while running update_build_config: {str(exc)}") + raise UpdateBuildConfigError(f"Error while running update_build_config: {str(exc)}") from exc - if "value" in field_dict and callable(field_dict["value"]): - field_dict["value"] = field_dict["value"]() - field_dict["refresh"] = True - - # Let's check if "range_spec" is a RangeSpec object - if "rangeSpec" in field_dict and isinstance(field_dict["rangeSpec"], RangeSpec): - field_dict["rangeSpec"] = field_dict["rangeSpec"].model_dump() + return build_config -def sanitize_field_config(field_config: Dict): +def sanitize_field_config(field_config: Union[Dict, TemplateField]): # If any of the already existing keys are in field_config, remove them + if isinstance(field_config, TemplateField): + field_dict = field_config.to_dict() + else: + field_dict = field_config for key in [ "name", "field_type", @@ -392,13 +445,20 @@ def sanitize_field_config(field_config: Dict): "advanced", "show", ]: - field_config.pop(key, None) - return field_config + field_dict.pop(key, None) + return field_dict def build_component(component): """Build a single component.""" - logger.debug(f"Building component: {component.get('name'), component.get('output_types')}") component_name = determine_component_name(component) component_template = create_component_template(component) + return component_name, component_template + + +def get_function(code): + """Get the function""" + function_name = validate.extract_function_name(code) + + return validate.create_function(code, function_name) diff --git a/src/backend/langflow/interface/custom_lists.py b/src/backend/base/langflow/interface/custom_lists.py similarity index 100% rename from src/backend/langflow/interface/custom_lists.py rename to src/backend/base/langflow/interface/custom_lists.py index 3cff26099..8f428ee11 100644 --- a/src/backend/langflow/interface/custom_lists.py +++ b/src/backend/base/langflow/interface/custom_lists.py @@ -2,8 +2,8 @@ import inspect from typing import Any from langchain import llms, memory, requests, text_splitter -from langchain_community.chat_models import AzureChatOpenAI, ChatAnthropic, ChatOpenAI, ChatVertexAI from langchain_community import agent_toolkits, document_loaders, embeddings +from langchain_community.chat_models import AzureChatOpenAI, ChatAnthropic, ChatOpenAI, ChatVertexAI from langflow.interface.agents.custom import CUSTOM_AGENTS from langflow.interface.chains.custom import CUSTOM_CHAINS diff --git a/src/backend/langflow/services/plugins/__init__.py b/src/backend/base/langflow/interface/document_loaders/__init__.py similarity index 100% rename from src/backend/langflow/services/plugins/__init__.py rename to src/backend/base/langflow/interface/document_loaders/__init__.py diff --git a/src/backend/langflow/interface/document_loaders/base.py b/src/backend/base/langflow/interface/document_loaders/base.py similarity index 100% rename from src/backend/langflow/interface/document_loaders/base.py rename to src/backend/base/langflow/interface/document_loaders/base.py index 6142d2fa2..24108c9b4 100644 --- a/src/backend/langflow/interface/document_loaders/base.py +++ b/src/backend/base/langflow/interface/document_loaders/base.py @@ -1,11 +1,11 @@ from typing import Dict, List, Optional, Type +from loguru import logger + from langflow.interface.base import LangChainTypeCreator +from langflow.interface.custom_lists import documentloaders_type_to_cls_dict from langflow.services.deps import get_settings_service from langflow.template.frontend_node.documentloaders import DocumentLoaderFrontNode -from langflow.interface.custom_lists import documentloaders_type_to_cls_dict - -from loguru import logger from langflow.utils.util import build_template_from_class diff --git a/src/backend/langflow/services/session/__init__.py b/src/backend/base/langflow/interface/embeddings/__init__.py similarity index 100% rename from src/backend/langflow/services/session/__init__.py rename to src/backend/base/langflow/interface/embeddings/__init__.py diff --git a/src/backend/langflow/interface/embeddings/base.py b/src/backend/base/langflow/interface/embeddings/base.py similarity index 100% rename from src/backend/langflow/interface/embeddings/base.py rename to src/backend/base/langflow/interface/embeddings/base.py index 834ea61fa..061321092 100644 --- a/src/backend/langflow/interface/embeddings/base.py +++ b/src/backend/base/langflow/interface/embeddings/base.py @@ -1,12 +1,12 @@ from typing import Dict, List, Optional, Type +from loguru import logger + from langflow.interface.base import LangChainTypeCreator from langflow.interface.custom_lists import embedding_type_to_cls_dict from langflow.services.deps import get_settings_service - from langflow.template.frontend_node.base import FrontendNode from langflow.template.frontend_node.embeddings import EmbeddingFrontendNode -from loguru import logger from langflow.utils.util import build_template_from_class diff --git a/src/backend/langflow/interface/importing/__init__.py b/src/backend/base/langflow/interface/importing/__init__.py similarity index 54% rename from src/backend/langflow/interface/importing/__init__.py rename to src/backend/base/langflow/interface/importing/__init__.py index 317849f8e..066653f49 100644 --- a/src/backend/langflow/interface/importing/__init__.py +++ b/src/backend/base/langflow/interface/importing/__init__.py @@ -1,5 +1,3 @@ -from langflow.interface.importing.utils import import_by_type # noqa: F401 - # This module is used to import any langchain class by name. ALL = [ diff --git a/src/backend/langflow/interface/importing/utils.py b/src/backend/base/langflow/interface/importing/utils.py similarity index 86% rename from src/backend/langflow/interface/importing/utils.py rename to src/backend/base/langflow/interface/importing/utils.py index 9d7305f16..24612df3c 100644 --- a/src/backend/langflow/interface/importing/utils.py +++ b/src/backend/base/langflow/interface/importing/utils.py @@ -9,9 +9,8 @@ from langchain.chains.base import Chain from langchain.prompts import PromptTemplate from langchain.tools import BaseTool from langchain_core.language_models.chat_models import BaseChatModel -from langflow.interface.custom.custom_component import CustomComponent + from langflow.interface.wrappers.base import wrapper_creator -from langflow.utils import validate def import_module(module_path: str) -> Any: @@ -35,7 +34,7 @@ def import_by_type(_type: str, name: str) -> Any: func_dict = { "agents": import_agent, "prompts": import_prompt, - "llms": {"llm": import_llm, "chat": import_chat_llm}, + "models": {"llm": import_llm, "chat": import_chat_llm}, "tools": import_tool, "chains": import_chain, "toolkits": import_toolkit, @@ -48,9 +47,8 @@ def import_by_type(_type: str, name: str) -> Any: "utilities": import_utility, "output_parsers": import_output_parser, "retrievers": import_retriever, - "custom_components": import_custom_component, } - if _type == "llms": + if _type == "models": key = "chat" if "chat" in name.lower() else "llm" loaded_func = func_dict[_type][key] # type: ignore else: @@ -59,11 +57,6 @@ def import_by_type(_type: str, name: str) -> Any: return loaded_func(name) -def import_custom_component(custom_component: str) -> CustomComponent: - """Import custom component from custom component name""" - return import_class("langflow.interface.custom.custom_component.CustomComponent") - - def import_output_parser(output_parser: str) -> Any: """Import output parser from output parser name""" return import_module(f"from langchain.output_parsers import {output_parser}") @@ -171,16 +164,3 @@ def import_utility(utility: str) -> Any: if utility == "SQLDatabase": return import_class(f"langchain_community.sql_database.{utility}") return import_class(f"langchain_community.utilities.{utility}") - - -def get_function(code): - """Get the function""" - function_name = validate.extract_function_name(code) - - return validate.create_function(code, function_name) - - -def eval_custom_component_code(code: str) -> Type[CustomComponent]: - """Evaluate custom component code""" - class_name = validate.extract_class_name(code) - return validate.create_class(code, class_name) diff --git a/src/backend/langflow/services/store/__init__.py b/src/backend/base/langflow/interface/initialize/__init__.py similarity index 100% rename from src/backend/langflow/services/store/__init__.py rename to src/backend/base/langflow/interface/initialize/__init__.py diff --git a/src/backend/langflow/interface/initialize/llm.py b/src/backend/base/langflow/interface/initialize/llm.py similarity index 100% rename from src/backend/langflow/interface/initialize/llm.py rename to src/backend/base/langflow/interface/initialize/llm.py diff --git a/src/backend/langflow/interface/initialize/loading.py b/src/backend/base/langflow/interface/initialize/loading.py similarity index 84% rename from src/backend/langflow/interface/initialize/loading.py rename to src/backend/base/langflow/interface/initialize/loading.py index 652cd1a0c..15045cd06 100644 --- a/src/backend/langflow/interface/initialize/loading.py +++ b/src/backend/base/langflow/interface/initialize/loading.py @@ -2,6 +2,7 @@ import inspect import json from typing import TYPE_CHECKING, Any, Callable, Dict, Sequence, Type + import orjson from langchain.agents import agent as agent_module from langchain.agents.agent import AgentExecutor @@ -14,8 +15,8 @@ from langchain_core.documents import Document from loguru import logger from pydantic import ValidationError -from langflow.interface.custom_lists import CUSTOM_NODES -from langflow.interface.importing.utils import eval_custom_component_code, get_function, import_by_type +from langflow.interface.custom.eval import eval_custom_component_code +from langflow.interface.importing.utils import import_by_type from langflow.interface.initialize.llm import initialize_vertexai from langflow.interface.initialize.utils import handle_format_kwargs, handle_node_type, handle_partial_variables from langflow.interface.initialize.vector_store import vecstore_initializer @@ -24,32 +25,49 @@ from langflow.interface.retrievers.base import retriever_creator from langflow.interface.toolkits.base import toolkits_creator from langflow.interface.utils import load_file_into_dict from langflow.interface.wrappers.base import wrapper_creator +from langflow.schema.schema import Record from langflow.utils import validate +from langflow.utils.util import unescape_string if TYPE_CHECKING: - from langflow import CustomComponent - - -def build_vertex_in_params(params: Dict) -> Dict: + from langflow.custom import CustomComponent from langflow.graph.vertex.base import Vertex - # If any of the values in params is a Vertex, we will build it - return {key: value.build() if isinstance(value, Vertex) else value for key, value in params.items()} - -async def instantiate_class(node_type: str, base_type: str, params: Dict, user_id=None) -> Any: +async def instantiate_class( + vertex: "Vertex", + user_id=None, +) -> Any: """Instantiate class from module type and key, and params""" + from langflow.interface.custom_lists import CUSTOM_NODES + + vertex_type = vertex.vertex_type + base_type = vertex.base_type + params = vertex.params params = convert_params_to_sets(params) params = convert_kwargs(params) - if node_type in CUSTOM_NODES: - if custom_node := CUSTOM_NODES.get(node_type): + if vertex_type in CUSTOM_NODES: + if custom_node := CUSTOM_NODES.get(vertex_type): if hasattr(custom_node, "initialize"): return custom_node.initialize(**params) - return custom_node(**params) - logger.debug(f"Instantiating {node_type} of type {base_type}") - class_object = import_by_type(_type=base_type, name=node_type) - return await instantiate_based_on_type(class_object, base_type, node_type, params, user_id=user_id) + if callable(custom_node): + return custom_node(**params) + raise ValueError(f"Custom node {vertex_type} is not callable") + logger.debug(f"Instantiating {vertex_type} of type {base_type}") + if not base_type: + raise ValueError("No base type provided for vertex") + if base_type == "custom_components": + return await instantiate_custom_component(params, user_id, vertex) + class_object = import_by_type(_type=base_type, name=vertex_type) + return await instantiate_based_on_type( + class_object=class_object, + base_type=base_type, + node_type=vertex_type, + params=params, + user_id=user_id, + vertex=vertex, + ) def convert_params_to_sets(params): @@ -76,7 +94,14 @@ def convert_kwargs(params): return params -async def instantiate_based_on_type(class_object, base_type, node_type, params, user_id): +async def instantiate_based_on_type( + class_object, + base_type, + node_type, + params, + user_id, + vertex, +): if base_type == "agents": return instantiate_agent(node_type, class_object, params) elif base_type == "prompts": @@ -103,24 +128,49 @@ async def instantiate_based_on_type(class_object, base_type, node_type, params, return instantiate_chains(node_type, class_object, params) elif base_type == "output_parsers": return instantiate_output_parser(node_type, class_object, params) - elif base_type == "llms": + elif base_type == "models": return instantiate_llm(node_type, class_object, params) elif base_type == "retrievers": return instantiate_retriever(node_type, class_object, params) elif base_type == "memory": return instantiate_memory(node_type, class_object, params) elif base_type == "custom_components": - return await instantiate_custom_component(node_type, class_object, params, user_id) + return await instantiate_custom_component( + params, + user_id, + vertex, + ) elif base_type == "wrappers": return instantiate_wrapper(node_type, class_object, params) else: return class_object(**params) -async def instantiate_custom_component(node_type, class_object, params, user_id): +def update_params_with_load_from_db_fields(custom_component: "CustomComponent", params, load_from_db_fields): + # For each field in load_from_db_fields, we will check if it's in the params + # and if it is, we will get the value from the custom_component.keys(name) + # and update the params with the value + for field in load_from_db_fields: + if field in params: + try: + key = custom_component.variables(params[field]) + params[field] = key if key else params[field] + except Exception as exc: + logger.error(f"Failed to get value for {field} from custom component. Error: {exc}") + pass + return params + + +async def instantiate_custom_component(params, user_id, vertex): params_copy = params.copy() - class_object: "CustomComponent" = eval_custom_component_code(params_copy.pop("code")) - custom_component = class_object(user_id=user_id) + class_object: Type["CustomComponent"] = eval_custom_component_code(params_copy.pop("code")) + custom_component: "CustomComponent" = class_object( + user_id=user_id, + parameters=params_copy, + vertex=vertex, + selected_output_type=vertex.selected_output_type, + ) + params_copy = update_params_with_load_from_db_fields(custom_component, params_copy, vertex.load_from_db_fields) if "retriever" in params_copy and hasattr(params_copy["retriever"], "as_retriever"): params_copy["retriever"] = params_copy["retriever"].as_retriever() @@ -130,12 +180,16 @@ async def instantiate_custom_component(node_type, class_object, params, user_id) if is_async: # Await the build method directly if it's async - built_object = await custom_component.build(**params_copy) + build_result = await custom_component.build(**params_copy) else: # Call the build method directly if it's sync - built_object = custom_component.build(**params_copy) - - return built_object, {"repr": custom_component.custom_repr()} + build_result = custom_component.build(**params_copy) + custom_repr = custom_component.custom_repr() + if not custom_repr and isinstance(build_result, (dict, Record, str)): + custom_repr = build_result + if not isinstance(custom_repr, str): + custom_repr = str(custom_repr) + return custom_component, build_result, {"repr": custom_repr} def instantiate_wrapper(node_type, class_object, params): @@ -252,6 +306,8 @@ def instantiate_tool(node_type, class_object: Type[BaseTool], params: Dict): raise ValueError("Invalid file") return class_object(**params) elif node_type == "PythonFunctionTool": + from langflow.interface.custom.utils import get_function + params["func"] = get_function(params.get("code")) return class_object(**params) elif node_type == "PythonFunction": @@ -367,7 +423,10 @@ def instantiate_textsplitter( # separators might come in as an escaped string like \\n # so we need to convert it to a string if "separators" in params: - params["separators"] = params["separators"].encode().decode("unicode-escape") + if isinstance(params["separators"], str): + params["separators"] = unescape_string(params["separators"]) + elif isinstance(params["separators"], list): + params["separators"] = [unescape_string(separator) for separator in params["separators"]] text_splitter = class_object(**params) else: from langchain.text_splitter import Language diff --git a/src/backend/langflow/interface/initialize/utils.py b/src/backend/base/langflow/interface/initialize/utils.py similarity index 100% rename from src/backend/langflow/interface/initialize/utils.py rename to src/backend/base/langflow/interface/initialize/utils.py diff --git a/src/backend/langflow/interface/initialize/vector_store.py b/src/backend/base/langflow/interface/initialize/vector_store.py similarity index 100% rename from src/backend/langflow/interface/initialize/vector_store.py rename to src/backend/base/langflow/interface/initialize/vector_store.py diff --git a/src/backend/langflow/interface/listing.py b/src/backend/base/langflow/interface/listing.py similarity index 89% rename from src/backend/langflow/interface/listing.py rename to src/backend/base/langflow/interface/listing.py index 79a7335d4..a831f1098 100644 --- a/src/backend/langflow/interface/listing.py +++ b/src/backend/base/langflow/interface/listing.py @@ -21,7 +21,7 @@ class AllTypesDict(LazyLoadDictBase): from langflow.interface.types import get_all_types_dict settings_service = get_settings_service() - return get_all_types_dict(settings_service=settings_service) + return get_all_types_dict(settings_service.settings.COMPONENTS_PATH) lazy_load_dict = AllTypesDict() diff --git a/src/backend/langflow/interface/llms/__init__.py b/src/backend/base/langflow/interface/llms/__init__.py similarity index 100% rename from src/backend/langflow/interface/llms/__init__.py rename to src/backend/base/langflow/interface/llms/__init__.py diff --git a/src/backend/langflow/interface/llms/base.py b/src/backend/base/langflow/interface/llms/base.py similarity index 97% rename from src/backend/langflow/interface/llms/base.py rename to src/backend/base/langflow/interface/llms/base.py index 4b0654a1a..ba611da8d 100644 --- a/src/backend/langflow/interface/llms/base.py +++ b/src/backend/base/langflow/interface/llms/base.py @@ -1,16 +1,16 @@ from typing import Dict, List, Optional, Type +from loguru import logger + from langflow.interface.base import LangChainTypeCreator from langflow.interface.custom_lists import llm_type_to_cls_dict from langflow.services.deps import get_settings_service - from langflow.template.frontend_node.llms import LLMFrontendNode -from loguru import logger from langflow.utils.util import build_template_from_class class LLMCreator(LangChainTypeCreator): - type_name: str = "llms" + type_name: str = "models" @property def frontend_node_class(self) -> Type[LLMFrontendNode]: diff --git a/src/backend/langflow/interface/memories/__init__.py b/src/backend/base/langflow/interface/memories/__init__.py similarity index 100% rename from src/backend/langflow/interface/memories/__init__.py rename to src/backend/base/langflow/interface/memories/__init__.py diff --git a/src/backend/langflow/interface/memories/base.py b/src/backend/base/langflow/interface/memories/base.py similarity index 97% rename from src/backend/langflow/interface/memories/base.py rename to src/backend/base/langflow/interface/memories/base.py index 7508d6d64..b63c7d3f0 100644 --- a/src/backend/langflow/interface/memories/base.py +++ b/src/backend/base/langflow/interface/memories/base.py @@ -1,14 +1,14 @@ from typing import ClassVar, Dict, List, Optional, Type +from loguru import logger + from langflow.interface.base import LangChainTypeCreator from langflow.interface.custom_lists import memory_type_to_cls_dict +from langflow.legacy_custom.customs import get_custom_nodes from langflow.services.deps import get_settings_service - from langflow.template.frontend_node.base import FrontendNode from langflow.template.frontend_node.memories import MemoryFrontendNode -from loguru import logger from langflow.utils.util import build_template_from_class, build_template_from_method -from langflow.custom.customs import get_custom_nodes class MemoryCreator(LangChainTypeCreator): diff --git a/src/backend/langflow/services/task/__init__.py b/src/backend/base/langflow/interface/output_parsers/__init__.py similarity index 100% rename from src/backend/langflow/services/task/__init__.py rename to src/backend/base/langflow/interface/output_parsers/__init__.py diff --git a/src/backend/langflow/interface/output_parsers/base.py b/src/backend/base/langflow/interface/output_parsers/base.py similarity index 99% rename from src/backend/langflow/interface/output_parsers/base.py rename to src/backend/base/langflow/interface/output_parsers/base.py index 3ae1e9d7b..503b47642 100644 --- a/src/backend/langflow/interface/output_parsers/base.py +++ b/src/backend/base/langflow/interface/output_parsers/base.py @@ -1,13 +1,12 @@ from typing import ClassVar, Dict, List, Optional, Type from langchain import output_parsers +from loguru import logger from langflow.interface.base import LangChainTypeCreator from langflow.interface.importing.utils import import_class from langflow.services.deps import get_settings_service - from langflow.template.frontend_node.output_parsers import OutputParserFrontendNode -from loguru import logger from langflow.utils.util import build_template_from_class, build_template_from_method diff --git a/src/backend/langflow/interface/prompts/__init__.py b/src/backend/base/langflow/interface/prompts/__init__.py similarity index 100% rename from src/backend/langflow/interface/prompts/__init__.py rename to src/backend/base/langflow/interface/prompts/__init__.py diff --git a/src/backend/langflow/interface/prompts/base.py b/src/backend/base/langflow/interface/prompts/base.py similarity index 97% rename from src/backend/langflow/interface/prompts/base.py rename to src/backend/base/langflow/interface/prompts/base.py index 164ea2b10..2b448c362 100644 --- a/src/backend/langflow/interface/prompts/base.py +++ b/src/backend/base/langflow/interface/prompts/base.py @@ -1,14 +1,13 @@ from typing import Dict, List, Optional, Type from langchain import prompts +from loguru import logger -from langflow.custom.customs import get_custom_nodes from langflow.interface.base import LangChainTypeCreator from langflow.interface.importing.utils import import_class +from langflow.legacy_custom.customs import get_custom_nodes from langflow.services.deps import get_settings_service - from langflow.template.frontend_node.prompts import PromptFrontendNode -from loguru import logger from langflow.utils.util import build_template_from_class diff --git a/src/backend/langflow/interface/prompts/custom.py b/src/backend/base/langflow/interface/prompts/custom.py similarity index 100% rename from src/backend/langflow/interface/prompts/custom.py rename to src/backend/base/langflow/interface/prompts/custom.py diff --git a/src/backend/langflow/services/task/backends/__init__.py b/src/backend/base/langflow/interface/retrievers/__init__.py similarity index 100% rename from src/backend/langflow/services/task/backends/__init__.py rename to src/backend/base/langflow/interface/retrievers/__init__.py diff --git a/src/backend/langflow/interface/retrievers/base.py b/src/backend/base/langflow/interface/retrievers/base.py similarity index 99% rename from src/backend/langflow/interface/retrievers/base.py rename to src/backend/base/langflow/interface/retrievers/base.py index a6813e76c..a0be56b9b 100644 --- a/src/backend/langflow/interface/retrievers/base.py +++ b/src/backend/base/langflow/interface/retrievers/base.py @@ -1,12 +1,13 @@ from typing import Any, ClassVar, Dict, List, Optional, Type from langchain_community import retrievers +from loguru import logger + from langflow.interface.base import LangChainTypeCreator from langflow.interface.importing.utils import import_class from langflow.services.deps import get_settings_service from langflow.template.frontend_node.retrievers import RetrieverFrontendNode from langflow.utils.util import build_template_from_class, build_template_from_method -from loguru import logger class RetrieverCreator(LangChainTypeCreator): diff --git a/src/backend/langflow/interface/run.py b/src/backend/base/langflow/interface/run.py similarity index 79% rename from src/backend/langflow/interface/run.py rename to src/backend/base/langflow/interface/run.py index 94cd922eb..aec602ac7 100644 --- a/src/backend/langflow/interface/run.py +++ b/src/backend/base/langflow/interface/run.py @@ -1,25 +1,19 @@ -from typing import Dict, Optional, Tuple, Union -from uuid import UUID +from typing import Dict, Tuple from loguru import logger from langflow.graph import Graph -async def build_sorted_vertices(data_graph, user_id: Optional[Union[str, UUID]] = None) -> Tuple[Graph, Dict]: +async def build_sorted_vertices(data_graph, flow_id: str) -> Tuple[Graph, Dict]: """ Build langchain object from data_graph. """ logger.debug("Building langchain object") - graph = Graph.from_payload(data_graph) - sorted_vertices = graph.topological_sort() - artifacts = {} - for vertex in sorted_vertices: - await vertex.build(user_id=user_id) - if vertex.artifacts: - artifacts.update(vertex.artifacts) - return graph, artifacts + graph = Graph.from_payload(data_graph, flow_id=flow_id) + + return graph, {} def get_memory_key(langchain_object): diff --git a/src/backend/langflow/interface/text_splitters/__init__.py b/src/backend/base/langflow/interface/text_splitters/__init__.py similarity index 100% rename from src/backend/langflow/interface/text_splitters/__init__.py rename to src/backend/base/langflow/interface/text_splitters/__init__.py diff --git a/src/backend/langflow/interface/text_splitters/base.py b/src/backend/base/langflow/interface/text_splitters/base.py similarity index 100% rename from src/backend/langflow/interface/text_splitters/base.py rename to src/backend/base/langflow/interface/text_splitters/base.py index 29c77a12f..497377cde 100644 --- a/src/backend/langflow/interface/text_splitters/base.py +++ b/src/backend/base/langflow/interface/text_splitters/base.py @@ -1,11 +1,11 @@ from typing import Dict, List, Optional, Type +from loguru import logger + from langflow.interface.base import LangChainTypeCreator +from langflow.interface.custom_lists import textsplitter_type_to_cls_dict from langflow.services.deps import get_settings_service from langflow.template.frontend_node.textsplitters import TextSplittersFrontendNode -from langflow.interface.custom_lists import textsplitter_type_to_cls_dict - -from loguru import logger from langflow.utils.util import build_template_from_class diff --git a/src/backend/langflow/template/__init__.py b/src/backend/base/langflow/interface/toolkits/__init__.py similarity index 100% rename from src/backend/langflow/template/__init__.py rename to src/backend/base/langflow/interface/toolkits/__init__.py diff --git a/src/backend/langflow/interface/toolkits/base.py b/src/backend/base/langflow/interface/toolkits/base.py similarity index 79% rename from src/backend/langflow/interface/toolkits/base.py rename to src/backend/base/langflow/interface/toolkits/base.py index 7c57579d1..efcfefaa4 100644 --- a/src/backend/langflow/interface/toolkits/base.py +++ b/src/backend/base/langflow/interface/toolkits/base.py @@ -1,12 +1,12 @@ +import warnings from typing import Callable, Dict, List, Optional from langchain.agents import agent_toolkits +from loguru import logger from langflow.interface.base import LangChainTypeCreator from langflow.interface.importing.utils import import_class, import_module from langflow.services.deps import get_settings_service - -from loguru import logger from langflow.utils.util import build_template_from_class @@ -30,13 +30,15 @@ class ToolkitCreator(LangChainTypeCreator): @property def type_to_loader_dict(self) -> Dict: if self.type_dict is None: - settings_service = get_settings_service() - self.type_dict = { - toolkit_name: import_class(f"langchain.agents.agent_toolkits.{toolkit_name}") - # if toolkit_name is not lower case it is a class - for toolkit_name in agent_toolkits.__all__ - if not toolkit_name.islower() and toolkit_name in settings_service.settings.TOOLKITS - } + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + settings_service = get_settings_service() + self.type_dict = { + toolkit_name: import_class(f"langchain.agents.agent_toolkits.{toolkit_name}") + # if toolkit_name is not lower case it is a class + for toolkit_name in agent_toolkits.__all__ + if not toolkit_name.islower() and toolkit_name in settings_service.settings.TOOLKITS + } return self.type_dict diff --git a/src/backend/langflow/interface/toolkits/custom.py b/src/backend/base/langflow/interface/toolkits/custom.py similarity index 100% rename from src/backend/langflow/interface/toolkits/custom.py rename to src/backend/base/langflow/interface/toolkits/custom.py diff --git a/src/backend/langflow/interface/tools/__init__.py b/src/backend/base/langflow/interface/tools/__init__.py similarity index 100% rename from src/backend/langflow/interface/tools/__init__.py rename to src/backend/base/langflow/interface/tools/__init__.py diff --git a/src/backend/langflow/interface/tools/base.py b/src/backend/base/langflow/interface/tools/base.py similarity index 95% rename from src/backend/langflow/interface/tools/base.py rename to src/backend/base/langflow/interface/tools/base.py index 875915a58..b4c933baa 100644 --- a/src/backend/langflow/interface/tools/base.py +++ b/src/backend/base/langflow/interface/tools/base.py @@ -1,27 +1,17 @@ from typing import Dict, List, Optional -from langchain.agents.load_tools import ( - _EXTRA_LLM_TOOLS, - _EXTRA_OPTIONAL_TOOLS, - _LLM_TOOLS, -) +from langchain.agents.load_tools import _EXTRA_LLM_TOOLS, _EXTRA_OPTIONAL_TOOLS, _LLM_TOOLS -from langflow.custom import customs from langflow.interface.base import LangChainTypeCreator -from langflow.interface.tools.constants import ( - ALL_TOOLS_NAMES, - CUSTOM_TOOLS, - FILE_TOOLS, - OTHER_TOOLS, -) +from langflow.interface.tools.constants import ALL_TOOLS_NAMES, CUSTOM_TOOLS, FILE_TOOLS, OTHER_TOOLS from langflow.interface.tools.util import get_tool_params +from langflow.legacy_custom import customs from langflow.services.deps import get_settings_service - from langflow.template.field.base import TemplateField from langflow.template.template.base import Template from langflow.utils import util -from langflow.utils.util import build_template_from_class from langflow.utils.logger import logger +from langflow.utils.util import build_template_from_class TOOL_INPUTS = { "str": TemplateField( diff --git a/src/backend/langflow/interface/tools/constants.py b/src/backend/base/langflow/interface/tools/constants.py similarity index 86% rename from src/backend/langflow/interface/tools/constants.py rename to src/backend/base/langflow/interface/tools/constants.py index 0ac37a0a4..7b07922e5 100644 --- a/src/backend/langflow/interface/tools/constants.py +++ b/src/backend/base/langflow/interface/tools/constants.py @@ -2,14 +2,14 @@ from langchain import tools from langchain.agents import Tool from langchain.agents.load_tools import _BASE_TOOLS, _EXTRA_LLM_TOOLS, _EXTRA_OPTIONAL_TOOLS, _LLM_TOOLS from langchain.tools.json.tool import JsonSpec + from langflow.interface.importing.utils import import_class -from langflow.interface.tools.custom import PythonFunction, PythonFunctionTool +from langflow.interface.tools.custom import PythonFunctionTool FILE_TOOLS = {"JsonSpec": JsonSpec} CUSTOM_TOOLS = { "Tool": Tool, "PythonFunctionTool": PythonFunctionTool, - "PythonFunction": PythonFunction, } OTHER_TOOLS = {tool: import_class(f"langchain_community.tools.{tool}") for tool in tools.__all__} diff --git a/src/backend/langflow/interface/tools/custom.py b/src/backend/base/langflow/interface/tools/custom.py similarity index 95% rename from src/backend/langflow/interface/tools/custom.py rename to src/backend/base/langflow/interface/tools/custom.py index 73f5842df..6ba8cac13 100644 --- a/src/backend/langflow/interface/tools/custom.py +++ b/src/backend/base/langflow/interface/tools/custom.py @@ -1,10 +1,10 @@ from typing import Callable, Optional -from langflow.interface.importing.utils import get_function +from langchain.agents.tools import Tool from pydantic.v1 import BaseModel, validator +from langflow.interface.custom.utils import get_function from langflow.utils import validate -from langchain.agents.tools import Tool class Function(BaseModel): diff --git a/src/backend/langflow/interface/tools/util.py b/src/backend/base/langflow/interface/tools/util.py similarity index 100% rename from src/backend/langflow/interface/tools/util.py rename to src/backend/base/langflow/interface/tools/util.py diff --git a/src/backend/langflow/interface/types.py b/src/backend/base/langflow/interface/types.py similarity index 75% rename from src/backend/langflow/interface/types.py rename to src/backend/base/langflow/interface/types.py index 39c68889f..32ab7ff95 100644 --- a/src/backend/langflow/interface/types.py +++ b/src/backend/base/langflow/interface/types.py @@ -9,12 +9,10 @@ from langflow.interface.embeddings.base import embedding_creator from langflow.interface.llms.base import llm_creator from langflow.interface.memories.base import memory_creator from langflow.interface.output_parsers.base import output_parser_creator -from langflow.interface.prompts.base import prompt_creator from langflow.interface.retrievers.base import retriever_creator from langflow.interface.text_splitters.base import textsplitter_creator from langflow.interface.toolkits.base import toolkits_creator from langflow.interface.tools.base import tool_creator -from langflow.interface.utilities.base import utility_creator from langflow.interface.wrappers.base import wrapper_creator @@ -39,7 +37,7 @@ def build_langchain_types_dict(): # sourcery skip: dict-assign-update-to-union creators = [ chain_creator, agent_creator, - prompt_creator, + # prompt_creator, llm_creator, memory_creator, tool_creator, @@ -49,7 +47,7 @@ def build_langchain_types_dict(): # sourcery skip: dict-assign-update-to-union # vectorstore_creator, documentloader_creator, textsplitter_creator, - utility_creator, + # utility_creator, output_parser_creator, retriever_creator, ] @@ -63,8 +61,22 @@ def build_langchain_types_dict(): # sourcery skip: dict-assign-update-to-union return all_types -def get_all_types_dict(settings_service): +def get_all_types_dict(components_paths): """Get all types dictionary combining native and custom components.""" native_components = build_langchain_types_dict() - custom_components_from_file = build_custom_components(settings_service) + custom_components_from_file = build_custom_components(components_paths=components_paths) return merge_nested_dicts_with_renaming(native_components, custom_components_from_file) + + +def get_all_components(components_paths, as_dict=False): + """Get all components names combining native and custom components.""" + all_types_dict = get_all_types_dict(components_paths) + components = [] if not as_dict else {} + for category in all_types_dict.values(): + for component in category.values(): + component["name"] = component["display_name"] + if as_dict: + components[component["name"]] = component + else: + components.append(component) + return components diff --git a/src/backend/langflow/template/field/__init__.py b/src/backend/base/langflow/interface/utilities/__init__.py similarity index 100% rename from src/backend/langflow/template/field/__init__.py rename to src/backend/base/langflow/interface/utilities/__init__.py diff --git a/src/backend/langflow/interface/utilities/base.py b/src/backend/base/langflow/interface/utilities/base.py similarity index 97% rename from src/backend/langflow/interface/utilities/base.py rename to src/backend/base/langflow/interface/utilities/base.py index 0a58ef1bc..1b7b69421 100644 --- a/src/backend/langflow/interface/utilities/base.py +++ b/src/backend/base/langflow/interface/utilities/base.py @@ -3,9 +3,9 @@ from typing import Dict, List, Optional, Type from langchain_community import utilities from loguru import logger -from langflow.custom.customs import get_custom_nodes from langflow.interface.base import LangChainTypeCreator from langflow.interface.importing.utils import import_class +from langflow.legacy_custom.customs import get_custom_nodes from langflow.services.deps import get_settings_service from langflow.template.frontend_node.utilities import UtilitiesFrontendNode from langflow.utils.util import build_template_from_class diff --git a/src/backend/langflow/interface/utils.py b/src/backend/base/langflow/interface/utils.py similarity index 71% rename from src/backend/langflow/interface/utils.py rename to src/backend/base/langflow/interface/utils.py index ef29911f5..8e7f476f5 100644 --- a/src/backend/langflow/interface/utils.py +++ b/src/backend/base/langflow/interface/utils.py @@ -1,14 +1,14 @@ import base64 import json import os -from io import BytesIO import re - +from io import BytesIO import yaml from langchain.base_language import BaseLanguageModel -from PIL.Image import Image from loguru import logger +from PIL.Image import Image + from langflow.services.chat.config import ChatConfig from langflow.services.deps import get_settings_service @@ -56,8 +56,35 @@ def try_setting_streaming_options(langchain_object): def extract_input_variables_from_prompt(prompt: str) -> list[str]: - """Extract input variables from prompt.""" - return re.findall(r"{(.*?)}", prompt) + variables = [] + remaining_text = prompt + + # Pattern to match single {var} and double {{var}} braces. + pattern = r"\{\{(.*?)\}\}|\{([^{}]+)\}" + + while True: + match = re.search(pattern, remaining_text) + if not match: + break + + # Extract the variable name from either the single or double brace match + if match.group(1): # Match found in double braces + variable_name = "{{" + match.group(1) + "}}" # Re-add single braces for JSON strings + else: # Match found in single braces + variable_name = match.group(2) + if variable_name is not None: + # This means there is a match + # but there is nothing inside the braces + variables.append(variable_name) + + # Remove the matched text from the remaining_text + start, end = match.span() + remaining_text = remaining_text[:start] + remaining_text[end:] + + # Proceed to the next match until no more matches are found + # No need to compare remaining "{}" instances because we are re-adding braces for JSON compatibility + + return variables def setup_llm_caching(): @@ -73,6 +100,7 @@ def setup_llm_caching(): def set_langchain_cache(settings): from langchain.globals import set_llm_cache + from langflow.interface.importing.utils import import_class if cache_type := os.getenv("LANGFLOW_LANGCHAIN_CACHE"): diff --git a/src/backend/langflow/template/frontend_node/formatter/__init__.py b/src/backend/base/langflow/interface/vector_store/__init__.py similarity index 100% rename from src/backend/langflow/template/frontend_node/formatter/__init__.py rename to src/backend/base/langflow/interface/vector_store/__init__.py diff --git a/src/backend/langflow/interface/vector_store/base.py b/src/backend/base/langflow/interface/vector_store/base.py similarity index 100% rename from src/backend/langflow/interface/vector_store/base.py rename to src/backend/base/langflow/interface/vector_store/base.py diff --git a/src/backend/langflow/template/template/__init__.py b/src/backend/base/langflow/interface/wrappers/__init__.py similarity index 100% rename from src/backend/langflow/template/template/__init__.py rename to src/backend/base/langflow/interface/wrappers/__init__.py diff --git a/src/backend/langflow/interface/wrappers/base.py b/src/backend/base/langflow/interface/wrappers/base.py similarity index 51% rename from src/backend/langflow/interface/wrappers/base.py rename to src/backend/base/langflow/interface/wrappers/base.py index 469559ad9..204a5153e 100644 --- a/src/backend/langflow/interface/wrappers/base.py +++ b/src/backend/base/langflow/interface/wrappers/base.py @@ -1,35 +1,23 @@ -from typing import ClassVar, Dict, List, Optional +from typing import Dict, List, Optional -from langchain_community.utilities import requests, sql_database +from langchain_community.utilities import requests from loguru import logger from langflow.interface.base import LangChainTypeCreator -from langflow.utils.util import build_template_from_class, build_template_from_method +from langflow.utils.util import build_template_from_class class WrapperCreator(LangChainTypeCreator): type_name: str = "wrappers" - from_method_nodes: ClassVar[Dict] = {"SQLDatabase": "from_uri"} - @property def type_to_loader_dict(self) -> Dict: if self.type_dict is None: - self.type_dict = { - wrapper.__name__: wrapper for wrapper in [requests.TextRequestsWrapper, sql_database.SQLDatabase] - } + self.type_dict = {wrapper.__name__: wrapper for wrapper in [requests.TextRequestsWrapper]} return self.type_dict def get_signature(self, name: str) -> Optional[Dict]: try: - if name in self.from_method_nodes: - return build_template_from_method( - name, - type_to_cls_dict=self.type_to_loader_dict, - add_function=True, - method_name=self.from_method_nodes[name], - ) - return build_template_from_class(name, self.type_to_loader_dict) except ValueError as exc: raise ValueError("Wrapper not found") from exc diff --git a/src/backend/langflow/utils/__init__.py b/src/backend/base/langflow/legacy_custom/__init__.py similarity index 100% rename from src/backend/langflow/utils/__init__.py rename to src/backend/base/langflow/legacy_custom/__init__.py diff --git a/src/backend/langflow/custom/customs.py b/src/backend/base/langflow/legacy_custom/customs.py similarity index 94% rename from src/backend/langflow/custom/customs.py rename to src/backend/base/langflow/legacy_custom/customs.py index fb22c56b3..ff69064ff 100644 --- a/src/backend/langflow/custom/customs.py +++ b/src/backend/base/langflow/legacy_custom/customs.py @@ -1,13 +1,12 @@ from langflow.template import frontend_node # These should always be instantiated -CUSTOM_NODES = { +CUSTOM_NODES: dict[str, dict[str, frontend_node.base.FrontendNode]] = { # "prompts": { # "ZeroShotPrompt": frontend_node.prompts.ZeroShotPromptNode(), # }, "tools": { "PythonFunctionTool": frontend_node.tools.PythonFunctionToolNode(), - "PythonFunction": frontend_node.tools.PythonFunctionNode(), "Tool": frontend_node.tools.ToolNode(), }, "agents": { diff --git a/src/backend/base/langflow/load.py b/src/backend/base/langflow/load.py new file mode 100644 index 000000000..1262ac4b9 --- /dev/null +++ b/src/backend/base/langflow/load.py @@ -0,0 +1 @@ +from langflow.processing.load import load_flow_from_json, run_flow_from_json # noqa: F401 diff --git a/src/backend/langflow/main.py b/src/backend/base/langflow/main.py similarity index 74% rename from src/backend/langflow/main.py rename to src/backend/base/langflow/main.py index 0eba10ab1..eff774f57 100644 --- a/src/backend/langflow/main.py +++ b/src/backend/base/langflow/main.py @@ -3,32 +3,42 @@ from pathlib import Path from typing import Optional from urllib.parse import urlencode +import nest_asyncio # type: ignore +import socketio # type: ignore from fastapi import FastAPI, Request from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import FileResponse from fastapi.staticfiles import StaticFiles +from loguru import logger from langflow.api import router +from langflow.initial_setup.setup import create_or_update_starter_projects from langflow.interface.utils import setup_llm_caching from langflow.services.plugins.langfuse_plugin import LangfuseInstance from langflow.services.utils import initialize_services, teardown_services from langflow.utils.logger import configure -@asynccontextmanager -async def lifespan(app: FastAPI): - initialize_services() - setup_llm_caching() - LangfuseInstance.update() - yield - teardown_services() +def get_lifespan(fix_migration=False, socketio_server=None): + @asynccontextmanager + async def lifespan(app: FastAPI): + nest_asyncio.apply() + initialize_services(fix_migration=fix_migration, socketio_server=socketio_server) + setup_llm_caching() + LangfuseInstance.update() + create_or_update_starter_projects() + yield + teardown_services() + + return lifespan def create_app(): """Create the FastAPI app and include the router.""" configure() - + socketio_server = socketio.AsyncServer(async_mode="asgi", cors_allowed_origins="*", logger=True) + lifespan = get_lifespan(socketio_server=socketio_server) app = FastAPI(lifespan=lifespan) origins = ["*"] @@ -56,6 +66,13 @@ def create_app(): app.include_router(router) + app = mount_socketio(app, socketio_server) + + return app + + +def mount_socketio(app: FastAPI, socketio_server: socketio.AsyncServer): + app.mount("/sio", socketio.ASGIApp(socketio_server, socketio_path="")) return app @@ -90,6 +107,7 @@ def get_static_files_dir(): def setup_app(static_files_dir: Optional[Path] = None, backend_only: bool = False) -> FastAPI: """Setup the FastAPI app.""" # get the directory of the current file + logger.info(f"Setting up app with static files directory {static_files_dir}") if not static_files_dir: static_files_dir = get_static_files_dir() @@ -112,6 +130,7 @@ if __name__ == "__main__": host="127.0.0.1", port=7860, workers=get_number_of_workers(), - log_level="debug", + log_level="error", reload=True, + loop="asyncio", ) diff --git a/src/backend/base/langflow/memory.py b/src/backend/base/langflow/memory.py new file mode 100644 index 000000000..aea9b3000 --- /dev/null +++ b/src/backend/base/langflow/memory.py @@ -0,0 +1,100 @@ +from typing import Optional, Union + +from loguru import logger + +from langflow.schema import Record +from langflow.services.deps import get_monitor_service +from langflow.services.monitor.schema import MessageModel + + +def get_messages( + sender: Optional[str] = None, + sender_name: Optional[str] = None, + session_id: Optional[str] = None, + order_by: Optional[str] = "timestamp", + order: Optional[str] = "DESC", + limit: Optional[int] = None, +): + """ + Retrieves messages from the monitor service based on the provided filters. + + Args: + sender (Optional[str]): The sender of the messages (e.g., "Machine" or "User") + sender_name (Optional[str]): The name of the sender. + session_id (Optional[str]): The session ID associated with the messages. + order_by (Optional[str]): The field to order the messages by. Defaults to "timestamp". + limit (Optional[int]): The maximum number of messages to retrieve. + + Returns: + List[Record]: A list of Record objects representing the retrieved messages. + """ + monitor_service = get_monitor_service() + messages_df = monitor_service.get_messages( + sender=sender, + sender_name=sender_name, + session_id=session_id, + order_by=order_by, + limit=limit, + order=order, + ) + + records: list[Record] = [] + # messages_df has a timestamp + # it gets the last 5 messages, for example + # but now they are ordered from most recent to least recent + # so we need to reverse the order + messages_df = messages_df[::-1] if order == "DESC" else messages_df + for row in messages_df.itertuples(): + record = Record( + data={ + "text": row.message, + "sender": row.sender, + "sender_name": row.sender_name, + "session_id": row.session_id, + }, + ) + records.append(record) + + return records + + +def add_messages(records: Union[list[Record], Record]): + """ + Add a message to the monitor service. + """ + try: + monitor_service = get_monitor_service() + + if isinstance(records, Record): + records = [records] + + if not all(isinstance(record, (Record, str)) for record in records): + types = ", ".join([str(type(record)) for record in records]) + raise ValueError(f"The records must be instances of Record. Found: {types}") + + messages: list[MessageModel] = [] + for record in records: + messages.append(MessageModel.from_record(record)) + + for message in messages: + try: + monitor_service.add_message(message) + except Exception as e: + logger.error(f"Error adding message to monitor service: {e}") + logger.exception(e) + raise e + return records + except Exception as e: + logger.exception(e) + raise e + + +def delete_messages(session_id: str): + """ + Delete messages from the monitor service based on the provided session ID. + + Args: + session_id (str): The session ID associated with the messages to delete. + """ + monitor_service = get_monitor_service() + monitor_service.delete_messages(session_id) diff --git a/src/backend/base/langflow/processing/__init__.py b/src/backend/base/langflow/processing/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backend/langflow/processing/base.py b/src/backend/base/langflow/processing/base.py similarity index 90% rename from src/backend/langflow/processing/base.py rename to src/backend/base/langflow/processing/base.py index 41e03e7bc..e11af0a44 100644 --- a/src/backend/langflow/processing/base.py +++ b/src/backend/base/langflow/processing/base.py @@ -4,7 +4,6 @@ from langchain.agents.agent import AgentExecutor from langchain.callbacks.base import BaseCallbackHandler from loguru import logger -from langflow.api.v1.callback import AsyncStreamingLLMCallbackHandler, StreamingLLMCallbackHandler from langflow.processing.process import fix_memory_inputs, format_actions from langflow.services.deps import get_plugins_service @@ -15,11 +14,6 @@ if TYPE_CHECKING: def setup_callbacks(sync, trace_id, **kwargs): """Setup callbacks for langchain object""" callbacks = [] - if sync: - callbacks.append(StreamingLLMCallbackHandler(**kwargs)) - else: - callbacks.append(AsyncStreamingLLMCallbackHandler(**kwargs)) - plugin_service = get_plugins_service() plugin_callbacks = plugin_service.get_callbacks(_id=trace_id) if plugin_callbacks: @@ -70,14 +64,13 @@ async def get_result_and_steps(langchain_object, inputs: Union[dict, str], **kwa except Exception as exc: logger.error(f"Error fixing memory inputs: {exc}") + trace_id = kwargs.pop("session_id", None) try: - trace_id = kwargs.pop("session_id", None) callbacks = setup_callbacks(sync=False, trace_id=trace_id, **kwargs) output = await langchain_object.acall(inputs, callbacks=callbacks) except Exception as exc: # make the error message more informative logger.debug(f"Error: {str(exc)}") - trace_id = kwargs.pop("session_id", None) callbacks = setup_callbacks(sync=True, trace_id=trace_id, **kwargs) output = langchain_object(inputs, callbacks=callbacks) diff --git a/src/backend/base/langflow/processing/load.py b/src/backend/base/langflow/processing/load.py new file mode 100644 index 000000000..43d9ecc78 --- /dev/null +++ b/src/backend/base/langflow/processing/load.py @@ -0,0 +1,67 @@ +import json +from pathlib import Path +from typing import List, Optional, Union + +from langflow.graph import Graph +from langflow.graph.schema import RunOutputs +from langflow.processing.process import process_tweaks, run_graph + + +def load_flow_from_json(flow: Union[Path, str, dict], tweaks: Optional[dict] = None) -> Graph: + """ + Load flow from a JSON file or a JSON object. + + :param flow: JSON file path or JSON object + :param tweaks: Optional tweaks to be processed + :param build: If True, build the graph, otherwise return the graph object + :return: Langchain object or Graph object depending on the build parameter + """ + # If input is a file path, load JSON from the file + if isinstance(flow, (str, Path)): + with open(flow, "r", encoding="utf-8") as f: + flow_graph = json.load(f) + # If input is a dictionary, assume it's a JSON object + elif isinstance(flow, dict): + flow_graph = flow + else: + raise TypeError("Input must be either a file path (str) or a JSON object (dict)") + + graph_data = flow_graph["data"] + if tweaks is not None: + graph_data = process_tweaks(graph_data, tweaks) + + graph = Graph.from_payload(graph_data) + return graph + + +def run_flow_from_json( + flow: Union[Path, str, dict], + input_value: str, + tweaks: Optional[dict] = None, + input_type: str = "chat", + output_type: str = "chat", + output_component: Optional[str] = None, +) -> List[RunOutputs]: + """ + Runs a JSON flow by loading it from a file or dictionary and executing it with the given input value. + + Args: + flow (Union[Path, str, dict]): The path to the JSON file, or the JSON dictionary representing the flow. + input_value (str): The input value to be processed by the flow. + tweaks (Optional[dict], optional): Optional tweaks to be applied to the flow. Defaults to None. + input_type (str, optional): The type of the input value. Defaults to "chat". + output_type (str, optional): The type of the output value. Defaults to "chat". + output_component (Optional[str], optional): The specific output component to retrieve. Defaults to None. + + Returns: + None: The result of running the flow. + """ + graph = load_flow_from_json(flow, tweaks) + result = run_graph( + graph=graph, + input_value=input_value, + input_type=input_type, + output_type=output_type, + output_component=output_component, + ) + return result diff --git a/src/backend/base/langflow/processing/process.py b/src/backend/base/langflow/processing/process.py new file mode 100644 index 000000000..c05163933 --- /dev/null +++ b/src/backend/base/langflow/processing/process.py @@ -0,0 +1,302 @@ +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union + +from langchain.agents import AgentExecutor +from langchain.schema import AgentAction +from loguru import logger +from pydantic import BaseModel + +from langflow.graph.graph.base import Graph +from langflow.graph.schema import RunOutputs +from langflow.graph.vertex.base import Vertex +from langflow.interface.run import get_memory_key, update_memory_keys +from langflow.schema.schema import INPUT_FIELD_NAME +from langflow.services.session.service import SessionService + +if TYPE_CHECKING: + from langflow.api.v1.schemas import InputValueRequest, Tweaks + + +def fix_memory_inputs(langchain_object): + """ + Given a LangChain object, this function checks if it has a memory attribute and if that memory key exists in the + object's input variables. If so, it does nothing. Otherwise, it gets a possible new memory key using the + get_memory_key function and updates the memory keys using the update_memory_keys function. + """ + if not hasattr(langchain_object, "memory") or langchain_object.memory is None: + return + try: + if ( + hasattr(langchain_object.memory, "memory_key") + and langchain_object.memory.memory_key in langchain_object.input_variables + ): + return + except AttributeError: + input_variables = ( + langchain_object.prompt.input_variables + if hasattr(langchain_object, "prompt") + else langchain_object.input_keys + ) + if langchain_object.memory.memory_key in input_variables: + return + + possible_new_mem_key = get_memory_key(langchain_object) + if possible_new_mem_key is not None: + update_memory_keys(langchain_object, possible_new_mem_key) + + +def format_actions(actions: List[Tuple[AgentAction, str]]) -> str: + """Format a list of (AgentAction, answer) tuples into a string.""" + output = [] + for action, answer in actions: + log = action.log + tool = action.tool + tool_input = action.tool_input + output.append(f"Log: {log}") + if "Action" not in log and "Action Input" not in log: + output.append(f"Tool: {tool}") + output.append(f"Tool Input: {tool_input}") + output.append(f"Answer: {answer}") + output.append("") # Add a blank line + return "\n".join(output) + + +def get_result_and_thought(langchain_object: Any, inputs: dict): + """Get result and thought from extracted json""" + try: + if hasattr(langchain_object, "verbose"): + langchain_object.verbose = True + + if hasattr(langchain_object, "return_intermediate_steps"): + langchain_object.return_intermediate_steps = False + + try: + if not isinstance(langchain_object, AgentExecutor): + fix_memory_inputs(langchain_object) + except Exception as exc: + logger.error(f"Error fixing memory inputs: {exc}") + + try: + output = langchain_object(inputs, return_only_outputs=True) + except ValueError as exc: + # make the error message more informative + logger.debug(f"Error: {str(exc)}") + output = langchain_object.run(inputs) + + except Exception as exc: + raise ValueError(f"Error: {str(exc)}") from exc + return output + + +def get_input_str_if_only_one_input(inputs: dict) -> Optional[str]: + """Get input string if only one input is provided""" + return list(inputs.values())[0] if len(inputs) == 1 else None + + +def process_inputs( + inputs: Optional[Union[dict, List[dict]]] = None, + artifacts: Optional[Dict[str, Any]] = None, +) -> Union[dict, List[dict]]: + if inputs is None: + inputs = {} + if artifacts is None: + artifacts = {} + + if isinstance(inputs, dict): + inputs = update_inputs_dict(inputs, artifacts) + elif isinstance(inputs, List): + inputs = [update_inputs_dict(inp, artifacts) for inp in inputs] + + return inputs + + +def update_inputs_dict(inputs: dict, artifacts: Dict[str, Any]) -> dict: + for key, value in artifacts.items(): + if key == "repr": + continue + elif key not in inputs or not inputs[key]: + inputs[key] = value + + return inputs + + +class Result(BaseModel): + result: Any + session_id: str + + +async def run_graph_internal( + graph: "Graph", + flow_id: str, + stream: bool = False, + session_id: Optional[str] = None, + inputs: Optional[List["InputValueRequest"]] = None, + outputs: Optional[List[str]] = None, + artifacts: Optional[Dict[str, Any]] = None, + session_service: Optional[SessionService] = None, +) -> tuple[List[RunOutputs], str]: + """Run the graph and generate the result""" + inputs = inputs or [] + graph_data = graph._graph_data + if session_id is None and session_service is not None: + session_id_str = session_service.generate_key(session_id=flow_id, data_graph=graph_data) + elif session_id is not None: + session_id_str = session_id + else: + raise ValueError("session_id or session_service must be provided") + components = [] + inputs_list = [] + types = [] + for input_value_request in inputs: + if input_value_request.input_value is None: + logger.warning("InputValueRequest input_value cannot be None, defaulting to an empty string.") + input_value_request.input_value = "" + components.append(input_value_request.components or []) + inputs_list.append({INPUT_FIELD_NAME: input_value_request.input_value}) + types.append(input_value_request.type) + + run_outputs = await graph.arun( + inputs_list, + components, + types, + outputs or [], + stream=stream, + session_id=session_id_str or "", + ) + if session_id_str and session_service: + await session_service.update_session(session_id_str, (graph, artifacts)) + return run_outputs, session_id_str + + +def run_graph( + graph: "Graph", + input_value: str, + input_type: str, + output_type: str, + output_component: Optional[str] = None, +) -> List[RunOutputs]: + """ + Runs the given Langflow Graph with the specified input and returns the outputs. + + Args: + graph (Graph): The graph to be executed. + input_value (str): The input value to be passed to the graph. + input_type (str): The type of the input value. + output_type (str): The type of the desired output. + output_component (Optional[str], optional): The specific output component to retrieve. Defaults to None. + + Returns: + List[RunOutputs]: A list of RunOutputs objects representing the outputs of the graph. + + """ + inputs = [InputValueRequest(components=[], input_value=input_value, type=input_type)] + if output_component: + outputs = [output_component] + else: + outputs = [ + vertex.id + for vertex in graph.vertices + if output_type == "debug" + or (vertex.is_output and (output_type == "any" or output_type in vertex.id.lower())) + ] + components = [] + inputs_list = [] + types = [] + for input_value_request in inputs: + if input_value_request.input_value is None: + logger.warning("InputValueRequest input_value cannot be None, defaulting to an empty string.") + input_value_request.input_value = "" + components.append(input_value_request.components or []) + inputs_list.append({INPUT_FIELD_NAME: input_value_request.input_value}) + types.append(input_value_request.type) + run_outputs = graph.run( + inputs_list, + components, + types, + outputs or [], + stream=False, + session_id="", + ) + return run_outputs + + +def validate_input( + graph_data: Dict[str, Any], tweaks: Union["Tweaks", Dict[str, Dict[str, Any]]] +) -> List[Dict[str, Any]]: + if not isinstance(graph_data, dict) or not isinstance(tweaks, dict): + raise ValueError("graph_data and tweaks should be dictionaries") + + nodes = graph_data.get("data", {}).get("nodes") or graph_data.get("nodes") + + if not isinstance(nodes, list): + raise ValueError("graph_data should contain a list of nodes under 'data' key or directly under 'nodes' key") + + return nodes + + +def apply_tweaks(node: Dict[str, Any], node_tweaks: Dict[str, Any]) -> None: + template_data = node.get("data", {}).get("node", {}).get("template") + + if not isinstance(template_data, dict): + logger.warning(f"Template data for node {node.get('id')} should be a dictionary") + return + + for tweak_name, tweak_value in node_tweaks.items(): + if tweak_name not in template_data: + logger.warning(f"Node {node.get('id')} does not have a tweak named {tweak_name}") + continue + if tweak_name in template_data: + key = tweak_name if tweak_name == "file_path" else "value" + template_data[tweak_name][key] = tweak_value + + +def apply_tweaks_on_vertex(vertex: Vertex, node_tweaks: Dict[str, Any]) -> None: + for tweak_name, tweak_value in node_tweaks.items(): + if tweak_name and tweak_value and tweak_name in vertex.params: + vertex.params[tweak_name] = tweak_value + + +def process_tweaks(graph_data: Dict[str, Any], tweaks: Union["Tweaks", Dict[str, Dict[str, Any]]]) -> Dict[str, Any]: + """ + This function is used to tweak the graph data using the node id and the tweaks dict. + + :param graph_data: The dictionary containing the graph data. It must contain a 'data' key with + 'nodes' as its child or directly contain 'nodes' key. Each node should have an 'id' and 'data'. + :param tweaks: The dictionary containing the tweaks. The keys can be the node id or the name of the tweak. + The values can be a dictionary containing the tweaks for the node or the value of the tweak. + :return: The modified graph_data dictionary. + + :raises ValueError: If the input is not in the expected format. + """ + if not isinstance(tweaks, dict): + tweaks = tweaks.model_dump() + + nodes = validate_input(graph_data, tweaks) + nodes_map = {node.get("id"): node for node in nodes} + nodes_display_name_map = {node.get("data", {}).get("node", {}).get("display_name"): node for node in nodes} + + all_nodes_tweaks = {} + for key, value in tweaks.items(): + if isinstance(value, dict): + if node := nodes_map.get(key): + apply_tweaks(node, value) + elif node := nodes_display_name_map.get(key): + apply_tweaks(node, value) + else: + all_nodes_tweaks[key] = value + if all_nodes_tweaks: + for node in nodes: + apply_tweaks(node, all_nodes_tweaks) + + return graph_data + + +def process_tweaks_on_graph(graph: Graph, tweaks: Dict[str, Dict[str, Any]]): + for vertex in graph.vertices: + if isinstance(vertex, Vertex) and isinstance(vertex.id, str): + node_id = vertex.id + if node_tweaks := tweaks.get(node_id): + apply_tweaks_on_vertex(vertex, node_tweaks) + else: + logger.warning("Each node should be a Vertex with an 'id' attribute of type str") + + return graph diff --git a/src/backend/base/langflow/py.typed b/src/backend/base/langflow/py.typed new file mode 100644 index 000000000..e69de29bb diff --git a/src/backend/base/langflow/schema/__init__.py b/src/backend/base/langflow/schema/__init__.py new file mode 100644 index 000000000..14230578c --- /dev/null +++ b/src/backend/base/langflow/schema/__init__.py @@ -0,0 +1,4 @@ +from .dotdict import dotdict +from .schema import Record + +__all__ = ["Record", "dotdict"] diff --git a/src/backend/base/langflow/schema/dotdict.py b/src/backend/base/langflow/schema/dotdict.py new file mode 100644 index 000000000..f85c928bb --- /dev/null +++ b/src/backend/base/langflow/schema/dotdict.py @@ -0,0 +1,71 @@ +class dotdict(dict): + """ + dotdict allows accessing dictionary elements using dot notation (e.g., dict.key instead of dict['key']). + It automatically converts nested dictionaries into dotdict instances, enabling dot notation on them as well. + + Note: + - Only keys that are valid attribute names (e.g., strings that could be variable names) are accessible via dot notation. + - Keys which are not valid Python attribute names or collide with the dict method names (like 'items', 'keys') + should be accessed using the traditional dict['key'] notation. + """ + + def __getattr__(self, attr): + """ + Override dot access to behave like dictionary lookup. Automatically convert nested dicts to dotdicts. + + Args: + attr (str): Attribute to access. + + Returns: + The value associated with 'attr' in the dictionary, converted to dotdict if it is a dict. + + Raises: + AttributeError: If the attribute is not found in the dictionary. + """ + try: + value = self[attr] + if isinstance(value, dict) and not isinstance(value, dotdict): + value = dotdict(value) + self[attr] = value # Update self to nest dotdict for future accesses + return value + except KeyError: + raise AttributeError(f"'dotdict' object has no attribute '{attr}'") + + def __setattr__(self, key, value): + """ + Override attribute setting to work as dictionary item assignment. + + Args: + key (str): The key under which to store the value. + value: The value to store in the dictionary. + """ + if isinstance(value, dict) and not isinstance(value, dotdict): + value = dotdict(value) + self[key] = value + + def __delattr__(self, key): + """ + Override attribute deletion to work as dictionary item deletion. + + Args: + key (str): The key of the item to delete from the dictionary. + + Raises: + AttributeError: If the key is not found in the dictionary. + """ + try: + del self[key] + except KeyError: + raise AttributeError(f"'dotdict' object has no attribute '{key}'") + + def __missing__(self, key): + """ + Handle missing keys by returning an empty dotdict. This allows chaining access without raising KeyError. + + Args: + key: The missing key. + + Returns: + An empty dotdict instance for the given missing key. + """ + return dotdict() diff --git a/src/backend/base/langflow/schema/schema.py b/src/backend/base/langflow/schema/schema.py new file mode 100644 index 000000000..a48e72339 --- /dev/null +++ b/src/backend/base/langflow/schema/schema.py @@ -0,0 +1,150 @@ +import copy +from typing import Literal, Optional + +from langchain_core.documents import Document +from pydantic import BaseModel, model_validator + + +class Record(BaseModel): + """ + Represents a record with text and optional data. + + Attributes: + data (dict, optional): Additional data associated with the record. + """ + + text_key: str = "text" + data: dict = {} + default_value: Optional[str] = "" + + @model_validator(mode="before") + def validate_data(cls, values): + if not values.get("data"): + values["data"] = {} + # Any other keyword should be added to the data dictionary + for key in values: + if key not in values["data"] and key not in {"text_key", "data", "default_value"}: + values["data"][key] = values[key] + return values + + def get_text(self): + """ + Retrieves the text value from the data dictionary. + + If the text key is present in the data dictionary, the corresponding value is returned. + Otherwise, the default value is returned. + + Returns: + The text value from the data dictionary or the default value. + """ + return self.data.get(self.text_key, self.default_value) + + @classmethod + def from_document(cls, document: Document) -> "Record": + """ + Converts a Document to a Record. + + Args: + document (Document): The Document to convert. + + Returns: + Record: The converted Record. + """ + data = document.metadata + data["text"] = document.page_content + return cls(data=data, text_key="text") + + def __add__(self, other: "Record") -> "Record": + """ + Combines the data of two records by attempting to add values for overlapping keys + for all types that support the addition operation. Falls back to the value from 'other' + record when addition is not supported. + """ + combined_data = self.data.copy() + for key, value in other.data.items(): + # If the key exists in both records and both values support the addition operation + if key in combined_data: + try: + combined_data[key] += value + except TypeError: + # Fallback: Use the value from 'other' record if addition is not supported + combined_data[key] = value + else: + # If the key is not in the first record, simply add it + combined_data[key] = value + + return Record(data=combined_data) + + def to_lc_document(self) -> Document: + """ + Converts the Record to a Document. + + Returns: + Document: The converted Document. + """ + text = self.data.pop(self.text_key, self.default_value) + return Document(page_content=text, metadata=self.data) + + def __getattr__(self, key): + """ + Allows attribute-like access to the data dictionary. + """ + try: + if key.startswith("__"): + return self.__getattribute__(key) + if key in {"data", "text_key"} or key.startswith("_"): + return super().__getattr__(key) + + return self.data.get(key, self.default_value) + except KeyError: + # Fallback to default behavior to raise AttributeError for undefined attributes + raise AttributeError(f"'{type(self).__name__}' object has no attribute '{key}'") + + def __setattr__(self, key, value): + """ + Allows attribute-like setting of values in the data dictionary, + while still allowing direct assignment to class attributes. + """ + if key in {"data", "text_key"} or key.startswith("_"): + super().__setattr__(key, value) + else: + self.data[key] = value + + def __delattr__(self, key): + """ + Allows attribute-like deletion from the data dictionary. + """ + if key in {"data", "text_key"} or key.startswith("_"): + super().__delattr__(key) + else: + del self.data[key] + + def __deepcopy__(self, memo): + """ + Custom deepcopy implementation to handle copying of the Record object. + """ + # Create a new Record object with a deep copy of the data dictionary + return Record(data=copy.deepcopy(self.data, memo), text_key=self.text_key, default_value=self.default_value) + + def __str__(self) -> str: + """ + Returns a string representation of the Record, including text and data. + """ + # Assuming a method to dump model data as JSON string exists. + # If it doesn't, you might need to implement it or use json.dumps() directly. + # build the string considering all keys in the data dictionary + prefix = "Record(" + suffix = ")" + text = f"text_key={self.text_key}, " + text += ", ".join([f"{k}={v}" for k, v in self.data.items()]) + return prefix + text + suffix + + # check which attributes the Record has by checking the keys in the data dictionary + def __dir__(self): + return super().__dir__() + list(self.data.keys()) + + +INPUT_FIELD_NAME = "input_value" + +InputType = Literal["chat", "text", "any"] +OutputType = Literal["chat", "text", "any", "debug"] diff --git a/src/backend/langflow/server.py b/src/backend/base/langflow/server.py similarity index 63% rename from src/backend/langflow/server.py rename to src/backend/base/langflow/server.py index 9fe432744..b7e86934d 100644 --- a/src/backend/langflow/server.py +++ b/src/backend/base/langflow/server.py @@ -1,11 +1,19 @@ +import os + from gunicorn.app.base import BaseApplication # type: ignore +from uvicorn.workers import UvicornWorker + + +class LangflowUvicornWorker(UvicornWorker): + CONFIG_KWARGS = {"loop": "asyncio"} class LangflowApplication(BaseApplication): def __init__(self, app, options=None): self.options = options or {} - self.options["worker_class"] = "uvicorn.workers.UvicornWorker" + self.options["worker_class"] = "langflow.server.LangflowUvicornWorker" + self.options["loglevel"] = os.getenv("LANGFLOW_LOG_LEVEL", "error").lower() self.application = app super().__init__() diff --git a/src/backend/langflow/services/__init__.py b/src/backend/base/langflow/services/__init__.py similarity index 100% rename from src/backend/langflow/services/__init__.py rename to src/backend/base/langflow/services/__init__.py diff --git a/src/backend/base/langflow/services/auth/__init__.py b/src/backend/base/langflow/services/auth/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backend/langflow/services/auth/factory.py b/src/backend/base/langflow/services/auth/factory.py similarity index 100% rename from src/backend/langflow/services/auth/factory.py rename to src/backend/base/langflow/services/auth/factory.py index b44019289..63d5d2a6d 100644 --- a/src/backend/langflow/services/auth/factory.py +++ b/src/backend/base/langflow/services/auth/factory.py @@ -1,5 +1,5 @@ -from langflow.services.factory import ServiceFactory from langflow.services.auth.service import AuthService +from langflow.services.factory import ServiceFactory class AuthServiceFactory(ServiceFactory): diff --git a/src/backend/langflow/services/auth/service.py b/src/backend/base/langflow/services/auth/service.py similarity index 99% rename from src/backend/langflow/services/auth/service.py rename to src/backend/base/langflow/services/auth/service.py index 8beef8dcb..5c3a89af6 100644 --- a/src/backend/langflow/services/auth/service.py +++ b/src/backend/base/langflow/services/auth/service.py @@ -1,6 +1,7 @@ -from langflow.services.base import Service from typing import TYPE_CHECKING +from langflow.services.base import Service + if TYPE_CHECKING: from langflow.services.settings.service import SettingsService diff --git a/src/backend/langflow/services/auth/utils.py b/src/backend/base/langflow/services/auth/utils.py similarity index 94% rename from src/backend/langflow/services/auth/utils.py rename to src/backend/base/langflow/services/auth/utils.py index cc0120de9..d89330856 100644 --- a/src/backend/langflow/services/auth/utils.py +++ b/src/backend/base/langflow/services/auth/utils.py @@ -103,13 +103,13 @@ async def get_current_user_by_jwt( if isinstance(token, Coroutine): token = await token - if settings_service.auth_settings.SECRET_KEY is None: + if settings_service.auth_settings.SECRET_KEY.get_secret_value() is None: raise credentials_exception try: payload = jwt.decode( token, - settings_service.auth_settings.SECRET_KEY, + settings_service.auth_settings.SECRET_KEY.get_secret_value(), algorithms=[settings_service.auth_settings.ALGORITHM], ) user_id: UUID = payload.get("sub") # type: ignore @@ -179,7 +179,7 @@ def create_token(data: dict, expires_delta: timedelta): return jwt.encode( to_encode, - settings_service.auth_settings.SECRET_KEY, + settings_service.auth_settings.SECRET_KEY.get_secret_value(), algorithm=settings_service.auth_settings.ALGORITHM, ) @@ -254,13 +254,13 @@ def get_user_id_from_token(token: str) -> UUID: def create_user_tokens(user_id: UUID, db: Session = Depends(get_session), update_last_login: bool = False) -> dict: settings_service = get_settings_service() - access_token_expires = timedelta(minutes=settings_service.auth_settings.ACCESS_TOKEN_EXPIRE_MINUTES) + access_token_expires = timedelta(seconds=settings_service.auth_settings.ACCESS_TOKEN_EXPIRE_SECONDS) access_token = create_token( data={"sub": str(user_id)}, expires_delta=access_token_expires, ) - refresh_token_expires = timedelta(minutes=settings_service.auth_settings.REFRESH_TOKEN_EXPIRE_MINUTES) + refresh_token_expires = timedelta(seconds=settings_service.auth_settings.REFRESH_TOKEN_EXPIRE_SECONDS) refresh_token = create_token( data={"sub": str(user_id), "type": "rf"}, expires_delta=refresh_token_expires, @@ -283,7 +283,7 @@ def create_refresh_token(refresh_token: str, db: Session = Depends(get_session)) try: payload = jwt.decode( refresh_token, - settings_service.auth_settings.SECRET_KEY, + settings_service.auth_settings.SECRET_KEY.get_secret_value(), algorithms=[settings_service.auth_settings.ALGORITHM], ) user_id: UUID = payload.get("sub") # type: ignore @@ -322,8 +322,8 @@ def add_padding(s): def get_fernet(settings_service=Depends(get_settings_service)): - SECRET_KEY = settings_service.auth_settings.SECRET_KEY - # It's important that your secret key is 32 url-safe base64-encoded bytes + SECRET_KEY = settings_service.auth_settings.SECRET_KEY.get_secret_value() + # It's important that your secret key is 32 url-safe base64-encoded byte padded_secret_key = add_padding(SECRET_KEY) fernet = Fernet(padded_secret_key) return fernet diff --git a/src/backend/base/langflow/services/base.py b/src/backend/base/langflow/services/base.py new file mode 100644 index 000000000..594d697bc --- /dev/null +++ b/src/backend/base/langflow/services/base.py @@ -0,0 +1,29 @@ +from abc import ABC + + +class Service(ABC): + name: str + ready: bool = False + + def get_schema(self): + """Build a dictionary listing all methods, their parameters, types, return types and documentation.""" + + schema = {} + ignore = ["teardown", "set_ready"] + for method in dir(self): + if method.startswith("_") or method in ignore: + continue + func = getattr(self, method) + schema[method] = { + "name": method, + "parameters": func.__annotations__, + "return": func.__annotations__.get("return"), + "documentation": func.__doc__, + } + return schema + + def teardown(self): + pass + + def set_ready(self): + self.ready = True diff --git a/src/backend/base/langflow/services/cache/__init__.py b/src/backend/base/langflow/services/cache/__init__.py new file mode 100644 index 000000000..48fb9837a --- /dev/null +++ b/src/backend/base/langflow/services/cache/__init__.py @@ -0,0 +1,12 @@ +from langflow.services.cache.service import AsyncInMemoryCache, CacheService, RedisCache, ThreadingInMemoryCache + +from . import factory, service + +__all__ = [ + "factory", + "service", + "ThreadingInMemoryCache", + "AsyncInMemoryCache", + "CacheService", + "RedisCache", +] diff --git a/src/backend/base/langflow/services/cache/base.py b/src/backend/base/langflow/services/cache/base.py new file mode 100644 index 000000000..3c484934b --- /dev/null +++ b/src/backend/base/langflow/services/cache/base.py @@ -0,0 +1,168 @@ +import abc +import asyncio +import threading +from typing import Optional + +from langflow.services.base import Service + + +class CacheService(Service): + """ + Abstract base class for a cache. + """ + + name = "cache_service" + + @abc.abstractmethod + def get(self, key, lock: Optional[threading.Lock] = None): + """ + Retrieve an item from the cache. + + Args: + key: The key of the item to retrieve. + + Returns: + The value associated with the key, or None if the key is not found. + """ + + @abc.abstractmethod + def set(self, key, value, lock: Optional[threading.Lock] = None): + """ + Add an item to the cache. + + Args: + key: The key of the item. + value: The value to cache. + """ + + @abc.abstractmethod + def upsert(self, key, value, lock: Optional[threading.Lock] = None): + """ + Add an item to the cache if it doesn't exist, or update it if it does. + + Args: + key: The key of the item. + value: The value to cache. + """ + + @abc.abstractmethod + def delete(self, key, lock: Optional[threading.Lock] = None): + """ + Remove an item from the cache. + + Args: + key: The key of the item to remove. + """ + + @abc.abstractmethod + def clear(self, lock: Optional[threading.Lock] = None): + """ + Clear all items from the cache. + """ + + @abc.abstractmethod + def __contains__(self, key): + """ + Check if the key is in the cache. + + Args: + key: The key of the item to check. + + Returns: + True if the key is in the cache, False otherwise. + """ + + @abc.abstractmethod + def __getitem__(self, key): + """ + Retrieve an item from the cache using the square bracket notation. + + Args: + key: The key of the item to retrieve. + """ + + @abc.abstractmethod + def __setitem__(self, key, value): + """ + Add an item to the cache using the square bracket notation. + + Args: + key: The key of the item. + value: The value to cache. + """ + + @abc.abstractmethod + def __delitem__(self, key): + """ + Remove an item from the cache using the square bracket notation. + + Args: + key: The key of the item to remove. + """ + + +class AsyncBaseCacheService(Service): + """ + Abstract base class for a async cache. + """ + + name = "cache_service" + + @abc.abstractmethod + async def get(self, key, lock: Optional[asyncio.Lock] = None): + """ + Retrieve an item from the cache. + + Args: + key: The key of the item to retrieve. + + Returns: + The value associated with the key, or None if the key is not found. + """ + + @abc.abstractmethod + async def set(self, key, value, lock: Optional[asyncio.Lock] = None): + """ + Add an item to the cache. + + Args: + key: The key of the item. + value: The value to cache. + """ + + @abc.abstractmethod + async def upsert(self, key, value, lock: Optional[asyncio.Lock] = None): + """ + Add an item to the cache if it doesn't exist, or update it if it does. + + Args: + key: The key of the item. + value: The value to cache. + """ + + @abc.abstractmethod + async def delete(self, key, lock: Optional[asyncio.Lock] = None): + """ + Remove an item from the cache. + + Args: + key: The key of the item to remove. + """ + + @abc.abstractmethod + async def clear(self, lock: Optional[asyncio.Lock] = None): + """ + Clear all items from the cache. + """ + + @abc.abstractmethod + def __contains__(self, key): + """ + Check if the key is in the cache. + + Args: + key: The key of the item to check. + + Returns: + True if the key is in the cache, False otherwise. + """ diff --git a/src/backend/langflow/services/cache/factory.py b/src/backend/base/langflow/services/cache/factory.py similarity index 78% rename from src/backend/langflow/services/cache/factory.py rename to src/backend/base/langflow/services/cache/factory.py index 145f4e653..a64b47f3a 100644 --- a/src/backend/langflow/services/cache/factory.py +++ b/src/backend/base/langflow/services/cache/factory.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING -from langflow.services.cache.service import BaseCacheService, InMemoryCache, RedisCache +from langflow.services.cache.service import AsyncInMemoryCache, CacheService, RedisCache, ThreadingInMemoryCache from langflow.services.factory import ServiceFactory from langflow.utils.logger import logger @@ -10,7 +10,7 @@ if TYPE_CHECKING: class CacheServiceFactory(ServiceFactory): def __init__(self): - super().__init__(BaseCacheService) + super().__init__(CacheService) def create(self, settings_service: "SettingsService"): # Here you would have logic to create and configure a CacheService @@ -29,7 +29,9 @@ class CacheServiceFactory(ServiceFactory): logger.debug("Redis cache is connected") return redis_cache logger.warning("Redis cache is not connected, falling back to in-memory cache") - return InMemoryCache() + return ThreadingInMemoryCache() elif settings_service.settings.CACHE_TYPE == "memory": - return InMemoryCache() + return ThreadingInMemoryCache() + elif settings_service.settings.CACHE_TYPE == "async": + return AsyncInMemoryCache() diff --git a/src/backend/langflow/services/cache/service.py b/src/backend/base/langflow/services/cache/service.py similarity index 73% rename from src/backend/langflow/services/cache/service.py rename to src/backend/base/langflow/services/cache/service.py index ced345851..4ae4dc540 100644 --- a/src/backend/langflow/services/cache/service.py +++ b/src/backend/base/langflow/services/cache/service.py @@ -1,16 +1,17 @@ +import asyncio import pickle import threading import time from collections import OrderedDict +from typing import Optional from loguru import logger from langflow.services.base import Service -from langflow.services.cache.base import BaseCacheService +from langflow.services.cache.base import AsyncBaseCacheService, CacheService -class InMemoryCache(BaseCacheService, Service): - +class ThreadingInMemoryCache(CacheService, Service): """ A simple in-memory cache using an OrderedDict. @@ -49,7 +50,7 @@ class InMemoryCache(BaseCacheService, Service): self.max_size = max_size self.expiration_time = expiration_time - def get(self, key): + def get(self, key, lock: Optional[threading.Lock] = None): """ Retrieve an item from the cache. @@ -59,7 +60,7 @@ class InMemoryCache(BaseCacheService, Service): Returns: The value associated with the key, or None if the key is not found or the item has expired. """ - with self._lock: + with lock or self._lock: return self._get_without_lock(key) def _get_without_lock(self, key): @@ -80,7 +81,7 @@ class InMemoryCache(BaseCacheService, Service): self.delete(key) return None - def set(self, key, value, pickle=False): + def set(self, key, value, lock: Optional[threading.Lock] = None): """ Add an item to the cache. @@ -90,7 +91,7 @@ class InMemoryCache(BaseCacheService, Service): key: The key of the item. value: The value to cache. """ - with self._lock: + with lock or self._lock: if key in self._cache: # Remove existing key before re-inserting to update order self.delete(key) @@ -98,12 +99,10 @@ class InMemoryCache(BaseCacheService, Service): # Remove least recently used item self._cache.popitem(last=False) # pickle locally to mimic Redis - if pickle: - value = pickle.dumps(value) self._cache[key] = {"value": value, "time": time.time()} - def upsert(self, key, value): + def upsert(self, key, value, lock: Optional[threading.Lock] = None): """ Inserts or updates a value in the cache. If the existing value and the new value are both dictionaries, they are merged. @@ -112,7 +111,7 @@ class InMemoryCache(BaseCacheService, Service): key: The key of the item. value: The value to insert or update. """ - with self._lock: + with lock or self._lock: existing_value = self._get_without_lock(key) if existing_value is not None and isinstance(existing_value, dict) and isinstance(value, dict): existing_value.update(value) @@ -120,7 +119,7 @@ class InMemoryCache(BaseCacheService, Service): self.set(key, value) - def get_or_set(self, key, value): + def get_or_set(self, key, value, lock: Optional[threading.Lock] = None): """ Retrieve an item from the cache. If the item does not exist, set it with the provided value. @@ -132,27 +131,27 @@ class InMemoryCache(BaseCacheService, Service): Returns: The cached value associated with the key. """ - with self._lock: + with lock or self._lock: if key in self._cache: return self.get(key) self.set(key, value) return value - def delete(self, key): + def delete(self, key, lock: Optional[threading.Lock] = None): """ Remove an item from the cache. Args: key: The key of the item to remove. """ - with self._lock: + with lock or self._lock: self._cache.pop(key, None) - def clear(self): + def clear(self, lock: Optional[threading.Lock] = None): """ Clear all items from the cache. """ - with self._lock: + with lock or self._lock: self._cache.clear() def __contains__(self, key): @@ -180,7 +179,7 @@ class InMemoryCache(BaseCacheService, Service): return f"InMemoryCache(max_size={self.max_size}, expiration_time={self.expiration_time})" -class RedisCache(BaseCacheService, Service): +class RedisCache(CacheService): """ A Redis-based cache implementation. @@ -323,3 +322,85 @@ class RedisCache(BaseCacheService, Service): def __repr__(self): """Return a string representation of the RedisCache instance.""" return f"RedisCache(expiration_time={self.expiration_time})" + + +class AsyncInMemoryCache(AsyncBaseCacheService, Service): + def __init__(self, max_size=None, expiration_time=3600): + self.cache = OrderedDict() + + self.lock = asyncio.Lock() + self.max_size = max_size + self.expiration_time = expiration_time + + async def get(self, key, lock: Optional[asyncio.Lock] = None): + if not lock: + async with self.lock: + return await self._get(key) + else: + return await self._get(key) + + async def _get(self, key): + item = self.cache.get(key, None) + if item and (time.time() - item["time"] < self.expiration_time): + self.cache.move_to_end(key) + return pickle.loads(item["value"]) if isinstance(item["value"], bytes) else item["value"] + if item: + await self.delete(key) + return None + + async def set(self, key, value, lock: Optional[asyncio.Lock] = None): + if not lock: + async with self.lock: + await self._set( + key, + value, + ) + else: + await self._set( + key, + value, + ) + + async def _set(self, key, value): + if self.max_size and len(self.cache) >= self.max_size: + self.cache.popitem(last=False) + self.cache[key] = {"value": value, "time": time.time()} + self.cache.move_to_end(key) + + async def delete(self, key, lock: Optional[asyncio.Lock] = None): + if not lock: + async with self.lock: + await self._delete(key) + else: + await self._delete(key) + + async def _delete(self, key): + if key in self.cache: + del self.cache[key] + + async def clear(self, lock: Optional[asyncio.Lock] = None): + if not lock: + async with self.lock: + await self._clear() + else: + await self._clear() + + async def _clear(self): + self.cache.clear() + + async def upsert(self, key, value, lock: Optional[asyncio.Lock] = None): + if not lock: + async with self.lock: + await self._upsert(key, value) + else: + await self._upsert(key, value) + + async def _upsert(self, key, value): + existing_value = await self.get(key) + if existing_value is not None and isinstance(existing_value, dict) and isinstance(value, dict): + existing_value.update(value) + value = existing_value + await self.set(key, value) + + def __contains__(self, key): + return key in self.cache diff --git a/src/backend/langflow/services/cache/utils.py b/src/backend/base/langflow/services/cache/utils.py similarity index 100% rename from src/backend/langflow/services/cache/utils.py rename to src/backend/base/langflow/services/cache/utils.py diff --git a/src/backend/base/langflow/services/chat/__init__.py b/src/backend/base/langflow/services/chat/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backend/langflow/services/chat/cache.py b/src/backend/base/langflow/services/chat/cache.py similarity index 99% rename from src/backend/langflow/services/chat/cache.py rename to src/backend/base/langflow/services/chat/cache.py index f6247b540..959ea877c 100644 --- a/src/backend/langflow/services/chat/cache.py +++ b/src/backend/base/langflow/services/chat/cache.py @@ -1,10 +1,11 @@ from contextlib import contextmanager from typing import Any, Awaitable, Callable, List, Optional -from langflow.services.base import Service import pandas as pd from PIL import Image +from langflow.services.base import Service + class Subject: """Base class for implementing the observer pattern.""" diff --git a/src/backend/langflow/services/chat/config.py b/src/backend/base/langflow/services/chat/config.py similarity index 100% rename from src/backend/langflow/services/chat/config.py rename to src/backend/base/langflow/services/chat/config.py diff --git a/src/backend/langflow/services/chat/factory.py b/src/backend/base/langflow/services/chat/factory.py similarity index 100% rename from src/backend/langflow/services/chat/factory.py rename to src/backend/base/langflow/services/chat/factory.py diff --git a/src/backend/base/langflow/services/chat/service.py b/src/backend/base/langflow/services/chat/service.py new file mode 100644 index 000000000..072920418 --- /dev/null +++ b/src/backend/base/langflow/services/chat/service.py @@ -0,0 +1,39 @@ +import asyncio +from collections import defaultdict +from typing import Any, Optional + +from langflow.services.base import Service +from langflow.services.deps import get_cache_service + + +class ChatService(Service): + name = "chat_service" + + def __init__(self): + self._cache_locks = defaultdict(asyncio.Lock) + self.cache_service = get_cache_service() + + async def set_cache(self, flow_id: str, data: Any, lock: Optional[asyncio.Lock] = None) -> bool: + """ + Set the cache for a client. + """ + # client_id is the flow id but that already exists in the cache + # so we need to change it to something else + result_dict = { + "result": data, + "type": type(data), + } + await self.cache_service.upsert(flow_id, result_dict, lock=lock or self._cache_locks[flow_id]) + return flow_id in self.cache_service + + async def get_cache(self, flow_id: str, lock: Optional[asyncio.Lock] = None) -> Any: + """ + Get the cache for a client. + """ + return await self.cache_service.get(flow_id, lock=lock or self._cache_locks[flow_id]) + + async def clear_cache(self, flow_id: str, lock: Optional[asyncio.Lock] = None): + """ + Clear the cache for a client. + """ + await self.cache_service.delete(flow_id, lock=lock or self._cache_locks[flow_id]) diff --git a/src/backend/langflow/services/chat/utils.py b/src/backend/base/langflow/services/chat/utils.py similarity index 99% rename from src/backend/langflow/services/chat/utils.py rename to src/backend/base/langflow/services/chat/utils.py index 0562b9df2..271c0e85b 100644 --- a/src/backend/langflow/services/chat/utils.py +++ b/src/backend/base/langflow/services/chat/utils.py @@ -3,10 +3,11 @@ from typing import Any from langchain.agents import AgentExecutor from langchain.chains.base import Chain from langchain_core.runnables import Runnable +from loguru import logger + from langflow.api.v1.schemas import ChatMessage from langflow.interface.utils import try_setting_streaming_options from langflow.processing.base import get_result_and_steps -from loguru import logger LANGCHAIN_RUNNABLES = (Chain, Runnable, AgentExecutor) diff --git a/src/backend/base/langflow/services/database/__init__.py b/src/backend/base/langflow/services/database/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backend/langflow/services/database/factory.py b/src/backend/base/langflow/services/database/factory.py similarity index 99% rename from src/backend/langflow/services/database/factory.py rename to src/backend/base/langflow/services/database/factory.py index 57bf1668d..3b03da131 100644 --- a/src/backend/langflow/services/database/factory.py +++ b/src/backend/base/langflow/services/database/factory.py @@ -1,4 +1,6 @@ from typing import TYPE_CHECKING + + from langflow.services.database.service import DatabaseService from langflow.services.factory import ServiceFactory diff --git a/src/backend/base/langflow/services/database/models/__init__.py b/src/backend/base/langflow/services/database/models/__init__.py new file mode 100644 index 000000000..1f19435bd --- /dev/null +++ b/src/backend/base/langflow/services/database/models/__init__.py @@ -0,0 +1,6 @@ +from .api_key import ApiKey +from .flow import Flow +from .user import User +from .variable import Variable + +__all__ = ["Flow", "User", "ApiKey", "Variable"] diff --git a/src/backend/langflow/services/database/models/api_key/__init__.py b/src/backend/base/langflow/services/database/models/api_key/__init__.py similarity index 100% rename from src/backend/langflow/services/database/models/api_key/__init__.py rename to src/backend/base/langflow/services/database/models/api_key/__init__.py diff --git a/src/backend/langflow/services/database/models/api_key/crud.py b/src/backend/base/langflow/services/database/models/api_key/crud.py similarity index 100% rename from src/backend/langflow/services/database/models/api_key/crud.py rename to src/backend/base/langflow/services/database/models/api_key/crud.py diff --git a/src/backend/langflow/services/database/models/api_key/model.py b/src/backend/base/langflow/services/database/models/api_key/model.py similarity index 100% rename from src/backend/langflow/services/database/models/api_key/model.py rename to src/backend/base/langflow/services/database/models/api_key/model.py diff --git a/src/backend/langflow/services/database/models/base.py b/src/backend/base/langflow/services/database/models/base.py similarity index 100% rename from src/backend/langflow/services/database/models/base.py rename to src/backend/base/langflow/services/database/models/base.py diff --git a/src/backend/langflow/services/database/models/flow/__init__.py b/src/backend/base/langflow/services/database/models/flow/__init__.py similarity index 100% rename from src/backend/langflow/services/database/models/flow/__init__.py rename to src/backend/base/langflow/services/database/models/flow/__init__.py diff --git a/src/backend/base/langflow/services/database/models/flow/model.py b/src/backend/base/langflow/services/database/models/flow/model.py new file mode 100644 index 000000000..cbfdec563 --- /dev/null +++ b/src/backend/base/langflow/services/database/models/flow/model.py @@ -0,0 +1,127 @@ +# Path: src/backend/langflow/services/database/models/flow/model.py + +from datetime import datetime +from typing import TYPE_CHECKING, Dict, Optional +from uuid import UUID, uuid4 + +from emoji import purely_emoji # type: ignore +from pydantic import field_serializer, field_validator +from sqlmodel import JSON, Column, Field, Relationship, SQLModel + +from langflow.interface.custom.attributes import validate_icon +from langflow.schema.schema import Record + +if TYPE_CHECKING: + from langflow.services.database.models.user import User + + +class FlowBase(SQLModel): + name: str = Field(index=True) + description: Optional[str] = Field(index=True, nullable=True, default=None) + icon: Optional[str] = Field(default=None, nullable=True) + icon_bg_color: Optional[str] = Field(default=None, nullable=True) + data: Optional[Dict] = Field(default=None, nullable=True) + is_component: Optional[bool] = Field(default=False, nullable=True) + updated_at: Optional[datetime] = Field(default_factory=datetime.utcnow, nullable=True) + folder: Optional[str] = Field(default=None, nullable=True) + + @field_validator("icon_bg_color") + def validate_icon_bg_color(cls, v): + if v is not None and not isinstance(v, str): + raise ValueError("Icon background color must be a string") + # validate that is is a hex color + if v and not v.startswith("#"): + raise ValueError("Icon background color must start with #") + + # validate that it is a valid hex color + if v and len(v) != 7: + raise ValueError("Icon background color must be 7 characters long") + return v + + @field_validator("icon") + def validate_icon_atr(cls, v): + # const emojiRegex = /\p{Emoji}/u; + # const isEmoji = emojiRegex.test(data?.node?.icon!); + # emoji pattern in Python + if v is None: + return v + + emoji = validate_icon(v) + + if purely_emoji(emoji): + # this is indeed an emoji + return emoji + # otherwise it should be a valid lucide icon + if v is not None and not isinstance(v, str): + raise ValueError("Icon must be a string") + # is should be lowercase and contain only letters and hyphens + if v and not v.islower(): + raise ValueError("Icon must be lowercase") + if v and not v.replace("-", "").isalpha(): + raise ValueError("Icon must contain only letters and hyphens") + return v + + @field_validator("data") + def validate_json(v): + if not v: + return v + if not isinstance(v, dict): + raise ValueError("Flow must be a valid JSON") + + # data must contain nodes and edges + if "nodes" not in v.keys(): + raise ValueError("Flow must have nodes") + if "edges" not in v.keys(): + raise ValueError("Flow must have edges") + + return v + + # updated_at can be serialized to JSON + @field_serializer("updated_at") + def serialize_dt(self, dt: datetime, _info): + if dt is None: + return None + return dt.isoformat() + + @field_validator("updated_at", mode="before") + def validate_dt(cls, v): + if v is None: + return v + elif isinstance(v, datetime): + return v + + return datetime.fromisoformat(v) + + +class Flow(FlowBase, table=True): + id: UUID = Field(default_factory=uuid4, primary_key=True, unique=True) + data: Optional[Dict] = Field(default=None, sa_column=Column(JSON)) + user_id: Optional[UUID] = Field(index=True, foreign_key="user.id", nullable=True) + user: "User" = Relationship(back_populates="flows") + + def to_record(self): + serialized = self.model_dump() + data = { + "id": serialized.pop("id"), + "data": serialized.pop("data"), + "name": serialized.pop("name"), + "description": serialized.pop("description"), + "updated_at": serialized.pop("updated_at"), + } + record = Record(data=data) + return record + + +class FlowCreate(FlowBase): + user_id: Optional[UUID] = None + + +class FlowRead(FlowBase): + id: UUID + user_id: Optional[UUID] = Field() + + +class FlowUpdate(SQLModel): + name: Optional[str] = None + description: Optional[str] = None + data: Optional[Dict] = None diff --git a/src/backend/langflow/services/database/models/user/__init__.py b/src/backend/base/langflow/services/database/models/user/__init__.py similarity index 100% rename from src/backend/langflow/services/database/models/user/__init__.py rename to src/backend/base/langflow/services/database/models/user/__init__.py diff --git a/src/backend/langflow/services/database/models/user/crud.py b/src/backend/base/langflow/services/database/models/user/crud.py similarity index 99% rename from src/backend/langflow/services/database/models/user/crud.py rename to src/backend/base/langflow/services/database/models/user/crud.py index e8f58735c..5a948815e 100644 --- a/src/backend/langflow/services/database/models/user/crud.py +++ b/src/backend/base/langflow/services/database/models/user/crud.py @@ -3,12 +3,13 @@ from typing import Optional, Union from uuid import UUID from fastapi import Depends, HTTPException, status -from langflow.services.database.models.user.model import User, UserUpdate -from langflow.services.deps import get_session from sqlalchemy.exc import IntegrityError from sqlalchemy.orm.attributes import flag_modified from sqlmodel import Session, select +from langflow.services.database.models.user.model import User, UserUpdate +from langflow.services.deps import get_session + def get_user_by_username(db: Session, username: str) -> Union[User, None]: return db.exec(select(User).where(User.username == username)).first() diff --git a/src/backend/langflow/services/database/models/user/model.py b/src/backend/base/langflow/services/database/models/user/model.py similarity index 93% rename from src/backend/langflow/services/database/models/user/model.py rename to src/backend/base/langflow/services/database/models/user/model.py index dccd3c305..fa229b4b3 100644 --- a/src/backend/langflow/services/database/models/user/model.py +++ b/src/backend/base/langflow/services/database/models/user/model.py @@ -6,7 +6,7 @@ from sqlmodel import Field, Relationship, SQLModel if TYPE_CHECKING: from langflow.services.database.models.api_key import ApiKey - from langflow.services.database.models.credential import Credential + from langflow.services.database.models.variable import Variable from langflow.services.database.models.flow import Flow @@ -26,7 +26,7 @@ class User(SQLModel, table=True): ) store_api_key: Optional[str] = Field(default=None, nullable=True) flows: list["Flow"] = Relationship(back_populates="user") - credentials: list["Credential"] = Relationship( + variables: list["Variable"] = Relationship( back_populates="user", sa_relationship_kwargs={"cascade": "delete"}, ) diff --git a/src/backend/base/langflow/services/database/models/variable/__init__.py b/src/backend/base/langflow/services/database/models/variable/__init__.py new file mode 100644 index 000000000..62ecc4f87 --- /dev/null +++ b/src/backend/base/langflow/services/database/models/variable/__init__.py @@ -0,0 +1,3 @@ +from .model import Variable, VariableCreate, VariableRead, VariableUpdate + +__all__ = ["Variable", "VariableCreate", "VariableRead", "VariableUpdate"] diff --git a/src/backend/base/langflow/services/database/models/variable/model.py b/src/backend/base/langflow/services/database/models/variable/model.py new file mode 100644 index 000000000..1c314d756 --- /dev/null +++ b/src/backend/base/langflow/services/database/models/variable/model.py @@ -0,0 +1,49 @@ +from datetime import datetime, timezone +from typing import TYPE_CHECKING, Optional +from uuid import UUID, uuid4 + +from sqlmodel import Field, Relationship, SQLModel + + +if TYPE_CHECKING: + from langflow.services.database.models.user.model import User + + +def utc_now(): + return datetime.now(timezone.utc) + + +class VariableBase(SQLModel): + name: Optional[str] = Field(None, description="Name of the variable") + value: Optional[str] = Field(None, description="Encrypted value of the variable") + type: Optional[str] = Field(None, description="Type of the variable") + + +class Variable(VariableBase, table=True): + id: Optional[UUID] = Field( + default_factory=uuid4, + primary_key=True, + description="Unique ID for the variable", + ) + # name is unique per user + created_at: datetime = Field(default_factory=utc_now, description="Creation time of the variable") + updated_at: Optional[datetime] = Field(None, description="Last update time of the variable") + # foreign key to user table + user_id: UUID = Field(description="User ID associated with this variable", foreign_key="user.id") + user: "User" = Relationship(back_populates="variables") + + +class VariableCreate(VariableBase): + type: Optional[str] = Field(None, description="Type of the variable") + + +class VariableRead(SQLModel): + id: UUID + name: Optional[str] = Field(None, description="Name of the variable") + type: Optional[str] = Field(None, description="Type of the variable") + + +class VariableUpdate(SQLModel): + id: UUID # Include the ID for updating + name: Optional[str] = Field(None, description="Name of the variable") + value: Optional[str] = Field(None, description="Encrypted value of the variable") diff --git a/src/backend/langflow/services/database/service.py b/src/backend/base/langflow/services/database/service.py similarity index 94% rename from src/backend/langflow/services/database/service.py rename to src/backend/base/langflow/services/database/service.py index 1103d7755..f3d77f6d7 100644 --- a/src/backend/langflow/services/database/service.py +++ b/src/backend/base/langflow/services/database/service.py @@ -1,3 +1,4 @@ +from datetime import datetime import time from pathlib import Path from typing import TYPE_CHECKING @@ -40,7 +41,7 @@ class DatabaseService(Service): connect_args = {"check_same_thread": False} else: connect_args = {} - return create_engine(self.database_url, connect_args=connect_args, max_overflow=-1) + return create_engine(self.database_url, connect_args=connect_args) def __enter__(self): self._session = Session(self.engine) @@ -124,10 +125,16 @@ class DatabaseService(Service): # if not self.script_location.exists(): # this is not the correct way to check if alembic has been initialized # We need to check if the alembic_version table exists # if not, we need to initialize alembic - alembic_cfg = Config() + # stdout should be something like sys.stdout + # which is a buffer + # I don't want to output anything + # subprocess.DEVNULL is an int + buffer = open(self.script_location / "alembic.log", "w") + alembic_cfg = Config(stdout=buffer) # alembic_cfg.attributes["connection"] = session alembic_cfg.set_main_option("script_location", str(self.script_location)) alembic_cfg.set_main_option("sqlalchemy.url", self.database_url) + should_initialize_alembic = False with Session(self.engine) as session: # If the table does not exist it throws an error @@ -150,6 +157,7 @@ class DatabaseService(Service): logger.info(f"Running DB migrations in {self.script_location}") try: + buffer.write(f"{datetime.now().isoformat()}: Checking migrations\n") command.check(alembic_cfg) except Exception as exc: if isinstance(exc, (util.exc.CommandError, util.exc.AutogenerateDiffsDetected)): @@ -157,13 +165,14 @@ class DatabaseService(Service): time.sleep(3) try: + buffer.write(f"{datetime.now().isoformat()}: Checking migrations\n") command.check(alembic_cfg) - except util.exc.AutogenerateDiffsDetected as e: - logger.error("AutogenerateDiffsDetected: {exc}") + except util.exc.AutogenerateDiffsDetected as exc: + logger.error(f"AutogenerateDiffsDetected: {exc}") if not fix: raise RuntimeError( "Something went wrong running migrations. Please, run `langflow migration --fix`" - ) from e + ) from exc if fix: self.try_downgrade_upgrade_until_success(alembic_cfg) diff --git a/src/backend/langflow/services/database/utils.py b/src/backend/base/langflow/services/database/utils.py similarity index 100% rename from src/backend/langflow/services/database/utils.py rename to src/backend/base/langflow/services/database/utils.py diff --git a/src/backend/base/langflow/services/deps.py b/src/backend/base/langflow/services/deps.py new file mode 100644 index 000000000..23a78e320 --- /dev/null +++ b/src/backend/base/langflow/services/deps.py @@ -0,0 +1,219 @@ +from contextlib import contextmanager +from typing import TYPE_CHECKING, Generator + +from langflow.services import ServiceType, service_manager + +if TYPE_CHECKING: + from sqlmodel import Session + + from langflow.services.cache.service import CacheService + from langflow.services.chat.service import ChatService + from langflow.services.database.service import DatabaseService + from langflow.services.monitor.service import MonitorService + from langflow.services.plugins.service import PluginService + from langflow.services.session.service import SessionService + from langflow.services.settings.service import SettingsService + from langflow.services.socket.service import SocketIOService + from langflow.services.state.service import StateService + from langflow.services.storage.service import StorageService + from langflow.services.store.service import StoreService + from langflow.services.task.service import TaskService + from langflow.services.variable.service import VariableService + + +def get_service(service_type: ServiceType): + """ + Retrieves the service instance for the given service type. + + Args: + service_type (ServiceType): The type of service to retrieve. + + Returns: + Any: The service instance. + + """ + return service_manager.get(service_type) # type: ignore + + +def get_state_service() -> "StateService": + """ + Retrieves the StateService instance from the service manager. + + Returns: + The StateService instance. + """ + return service_manager.get(ServiceType.STATE_SERVICE) # type: ignore + + +def get_socket_service() -> "SocketIOService": + """ + Get the SocketIOService instance from the service manager. + + Returns: + SocketIOService: The SocketIOService instance. + """ + return service_manager.get(ServiceType.SOCKETIO_SERVICE) # type: ignore + + +def get_storage_service() -> "StorageService": + """ + Retrieves the storage service instance. + + Returns: + The storage service instance. + """ + return service_manager.get(ServiceType.STORAGE_SERVICE) # type: ignore + + +def get_variable_service() -> "VariableService": + """ + Retrieves the VariableService instance from the service manager. + + Returns: + The VariableService instance. + + """ + return service_manager.get(ServiceType.VARIABLE_SERVICE) # type: ignore + + +def get_plugins_service() -> "PluginService": + """ + Get the PluginService instance from the service manager. + + Returns: + PluginService: The PluginService instance. + """ + return service_manager.get(ServiceType.PLUGIN_SERVICE) # type: ignore + + +def get_settings_service() -> "SettingsService": + """ + Retrieves the SettingsService instance. + + If the service is not yet initialized, it will be initialized before returning. + + Returns: + The SettingsService instance. + + Raises: + ValueError: If the service cannot be retrieved or initialized. + """ + try: + return service_manager.get(ServiceType.SETTINGS_SERVICE) # type: ignore + except ValueError: + # initialize settings service + from langflow.services.manager import initialize_settings_service + + initialize_settings_service() + return service_manager.get(ServiceType.SETTINGS_SERVICE) # type: ignore + + +def get_db_service() -> "DatabaseService": + """ + Retrieves the DatabaseService instance from the service manager. + + Returns: + The DatabaseService instance. + + """ + return service_manager.get(ServiceType.DATABASE_SERVICE) # type: ignore + + +def get_session() -> Generator["Session", None, None]: + """ + Retrieves a session from the database service. + + Yields: + Session: A session object. + + """ + db_service = get_db_service() + yield from db_service.get_session() + + +@contextmanager +def session_scope(): + """ + Context manager for managing a session scope. + + This context manager is used to manage a session scope for database operations. + It ensures that the session is properly committed if no exceptions occur, + and rolled back if an exception is raised. + + Yields: + session: The session object. + + Raises: + Exception: If an error occurs during the session scope. + + """ + session = next(get_session()) + try: + yield session + session.commit() + except: + session.rollback() + raise + finally: + session.close() + + +def get_cache_service() -> "CacheService": + """ + Retrieves the cache service from the service manager. + + Returns: + The cache service instance. + """ + return service_manager.get(ServiceType.CACHE_SERVICE) # type: ignore + + +def get_session_service() -> "SessionService": + """ + Retrieves the session service from the service manager. + + Returns: + The session service instance. + """ + return service_manager.get(ServiceType.SESSION_SERVICE) # type: ignore + + +def get_monitor_service() -> "MonitorService": + """ + Retrieves the MonitorService instance from the service manager. + + Returns: + MonitorService: The MonitorService instance. + """ + return service_manager.get(ServiceType.MONITOR_SERVICE) # type: ignore + + +def get_task_service() -> "TaskService": + """ + Retrieves the TaskService instance from the service manager. + + Returns: + The TaskService instance. + + """ + return service_manager.get(ServiceType.TASK_SERVICE) # type: ignore + + +def get_chat_service() -> "ChatService": + """ + Get the chat service instance. + + Returns: + ChatService: The chat service instance. + """ + return service_manager.get(ServiceType.CHAT_SERVICE) # type: ignore + + +def get_store_service() -> "StoreService": + """ + Retrieves the StoreService instance from the service manager. + + Returns: + StoreService: The StoreService instance. + """ + return service_manager.get(ServiceType.STORE_SERVICE) # type: ignore diff --git a/src/backend/base/langflow/services/factory.py b/src/backend/base/langflow/services/factory.py new file mode 100644 index 000000000..49bea7db2 --- /dev/null +++ b/src/backend/base/langflow/services/factory.py @@ -0,0 +1,83 @@ +import importlib +import inspect +from typing import TYPE_CHECKING, Type, get_type_hints + +from cachetools import LRUCache, cached +from loguru import logger + +from langflow.services.schema import ServiceType + +if TYPE_CHECKING: + from langflow.services.base import Service + + +class ServiceFactory: + def __init__( + self, + service_class, + ): + self.service_class = service_class + self.dependencies = infer_service_types(self, import_all_services_into_a_dict()) + + def create(self, *args, **kwargs) -> "Service": + raise self.service_class(*args, **kwargs) + + +def hash_factory(factory: Type[ServiceFactory]) -> str: + return factory.service_class.__name__ + + +def hash_dict(d: dict) -> str: + return str(d) + + +def hash_infer_service_types_args(factory_class: Type[ServiceFactory], available_services=None) -> str: + factory_hash = hash_factory(factory_class) + services_hash = hash_dict(available_services) + return f"{factory_hash}_{services_hash}" + + +@cached(cache=LRUCache(maxsize=10), key=hash_infer_service_types_args) +def infer_service_types(factory_class: Type[ServiceFactory], available_services=None) -> list["ServiceType"]: + create_method = factory_class.create + type_hints = get_type_hints(create_method, globalns=available_services) + service_types = [] + for param_name, param_type in type_hints.items(): + # Skip the return type if it's included in type hints + if param_name == "return": + continue + + # Convert the type to the expected enum format directly without appending "_SERVICE" + type_name = param_type.__name__.upper().replace("SERVICE", "_SERVICE") + + try: + # Attempt to find a matching enum value + service_type = ServiceType[type_name] + service_types.append(service_type) + except KeyError: + raise ValueError(f"No matching ServiceType for parameter type: {param_type.__name__}") + return service_types + + +@cached(cache=LRUCache(maxsize=1)) +def import_all_services_into_a_dict(): + # Services are all in langflow.services.{service_name}.service + # and are subclass of Service + # We want to import all of them and put them in a dict + # to use as globals + from langflow.services.base import Service + + services = {} + for service_type in ServiceType: + try: + service_name = ServiceType(service_type).value.replace("_service", "") + module_name = f"langflow.services.{service_name}.service" + module = importlib.import_module(module_name) + for name, obj in inspect.getmembers(module, inspect.isclass): + if issubclass(obj, Service) and obj is not Service: + services[name] = obj + break + except Exception as exc: + logger.exception(exc) + raise RuntimeError("Could not initialize services. Please check your settings.") from exc + return services diff --git a/src/backend/langflow/services/manager.py b/src/backend/base/langflow/services/manager.py similarity index 61% rename from src/backend/langflow/services/manager.py rename to src/backend/base/langflow/services/manager.py index 0adeefd29..20186f7da 100644 --- a/src/backend/langflow/services/manager.py +++ b/src/backend/base/langflow/services/manager.py @@ -1,11 +1,11 @@ -from typing import TYPE_CHECKING, Dict, List, Optional +from typing import TYPE_CHECKING, Dict -from langflow.services.schema import ServiceType from loguru import logger if TYPE_CHECKING: from langflow.services.base import Service from langflow.services.factory import ServiceFactory + from langflow.services.schema import ServiceType class ServiceManager: @@ -16,23 +16,19 @@ class ServiceManager: def __init__(self): self.services: Dict[str, "Service"] = {} self.factories = {} - self.dependencies = {} def register_factory( self, service_factory: "ServiceFactory", - dependencies: Optional[List[ServiceType]] = None, ): """ Registers a new factory with dependencies. """ - if dependencies is None: - dependencies = [] + service_name = service_factory.service_class.name self.factories[service_name] = service_factory - self.dependencies[service_name] = dependencies - def get(self, service_name: ServiceType) -> "Service": + def get(self, service_name: "ServiceType") -> "Service": """ Get (or create) a service by its name. """ @@ -41,7 +37,7 @@ class ServiceManager: return self.services[service_name] - def _create_service(self, service_name: ServiceType): + def _create_service(self, service_name: "ServiceType"): """ Create a new service given its name, handling dependencies. """ @@ -49,25 +45,26 @@ class ServiceManager: self._validate_service_creation(service_name) # Create dependencies first - for dependency in self.dependencies.get(service_name, []): + factory = self.factories.get(service_name) + for dependency in factory.dependencies: if dependency not in self.services: self._create_service(dependency) # Collect the dependent services - dependent_services = {dep.value: self.services[dep] for dep in self.dependencies.get(service_name, [])} + dependent_services = {dep.value: self.services[dep] for dep in factory.dependencies} # Create the actual service self.services[service_name] = self.factories[service_name].create(**dependent_services) self.services[service_name].set_ready() - def _validate_service_creation(self, service_name: ServiceType): + def _validate_service_creation(self, service_name: "ServiceType"): """ Validate whether the service can be created. """ if service_name not in self.factories: raise ValueError(f"No factory registered for the service class '{service_name.name}'") - def update(self, service_name: ServiceType): + def update(self, service_name: "ServiceType"): """ Update a service by its name. """ @@ -90,36 +87,11 @@ class ServiceManager: logger.exception(exc) self.services = {} self.factories = {} - self.dependencies = {} service_manager = ServiceManager() -def reinitialize_services(): - """ - Reinitialize all the services needed. - """ - - service_manager.update(ServiceType.SETTINGS_SERVICE) - service_manager.update(ServiceType.DATABASE_SERVICE) - service_manager.update(ServiceType.CACHE_SERVICE) - service_manager.update(ServiceType.CHAT_SERVICE) - service_manager.update(ServiceType.SESSION_SERVICE) - service_manager.update(ServiceType.AUTH_SERVICE) - service_manager.update(ServiceType.TASK_SERVICE) - - # Test cache connection - service_manager.get(ServiceType.CACHE_SERVICE) - # Test database connection - service_manager.get(ServiceType.DATABASE_SERVICE) - - # Test cache connection - service_manager.get(ServiceType.CACHE_SERVICE) - # Test database connection - service_manager.get(ServiceType.DATABASE_SERVICE) - - def initialize_settings_service(): """ Initialize the settings manager. @@ -134,13 +106,12 @@ def initialize_session_service(): Initialize the session manager. """ from langflow.services.cache import factory as cache_factory - from langflow.services.session import factory as session_service_factory # type: ignore + from langflow.services.session import ( + factory as session_service_factory, + ) # type: ignore initialize_settings_service() - service_manager.register_factory(cache_factory.CacheServiceFactory(), dependencies=[ServiceType.SETTINGS_SERVICE]) + service_manager.register_factory(cache_factory.CacheServiceFactory()) - service_manager.register_factory( - session_service_factory.SessionServiceFactory(), - dependencies=[ServiceType.CACHE_SERVICE], - ) + service_manager.register_factory(session_service_factory.SessionServiceFactory()) diff --git a/src/backend/base/langflow/services/monitor/__init__.py b/src/backend/base/langflow/services/monitor/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backend/base/langflow/services/monitor/factory.py b/src/backend/base/langflow/services/monitor/factory.py new file mode 100644 index 000000000..054e6bb3f --- /dev/null +++ b/src/backend/base/langflow/services/monitor/factory.py @@ -0,0 +1,13 @@ +from langflow.services.factory import ServiceFactory +from langflow.services.monitor.service import MonitorService +from langflow.services.settings.service import SettingsService + + +class MonitorServiceFactory(ServiceFactory): + name = "monitor_service" + + def __init__(self): + super().__init__(MonitorService) + + def create(self, settings_service: SettingsService): + return self.service_class(settings_service) diff --git a/src/backend/base/langflow/services/monitor/schema.py b/src/backend/base/langflow/services/monitor/schema.py new file mode 100644 index 000000000..80636a554 --- /dev/null +++ b/src/backend/base/langflow/services/monitor/schema.py @@ -0,0 +1,142 @@ +import json +from datetime import datetime +from typing import TYPE_CHECKING, Any, Optional + +from pydantic import BaseModel, Field, field_serializer, validator + +if TYPE_CHECKING: + from langflow.schema import Record + + +class TransactionModel(BaseModel): + id: Optional[int] = Field(default=None, alias="id") + timestamp: Optional[datetime] = Field(default_factory=datetime.now, alias="timestamp") + source: str + target: str + target_args: dict + status: str + error: Optional[str] = None + + class Config: + from_attributes = True + populate_by_name = True + + # validate target_args in case it is a JSON + @validator("target_args", pre=True) + def validate_target_args(cls, v): + if isinstance(v, str): + return json.loads(v) + return v + + +class MessageModel(BaseModel): + id: Optional[int] = Field(default=None, alias="id") + timestamp: datetime = Field(default_factory=datetime.now) + sender: str + sender_name: str + session_id: str + message: str + artifacts: dict + + class Config: + from_attributes = True + populate_by_name = True + + @validator("artifacts", pre=True) + def validate_target_args(cls, v): + if isinstance(v, str): + return json.loads(v) + return v + + @classmethod + def from_record(cls, record: "Record"): + # first check if the record has all the required fields + if not record.data or ("sender" not in record.data and "sender_name" not in record.data): + raise ValueError("The record does not have the required fields 'sender' and 'sender_name' in the data.") + return cls( + sender=record.sender, + sender_name=record.sender_name, + message=record.text, + session_id=record.session_id, + artifacts=record.artifacts or {}, + ) + + +class VertexBuildModel(BaseModel): + index: Optional[int] = Field(default=None, alias="index", exclude=True) + id: Optional[str] = Field(default=None, alias="id") + flow_id: str + valid: bool + params: Any + data: dict + artifacts: dict + timestamp: datetime = Field(default_factory=datetime.now) + + class Config: + from_attributes = True + populate_by_name = True + + @field_serializer("data", "artifacts") + def serialize_dict(v): + if isinstance(v, dict): + # check if the value of each key is a BaseModel or a list of BaseModels + for key, value in v.items(): + if isinstance(value, BaseModel): + v[key] = value.model_dump() + elif isinstance(value, list) and all(isinstance(i, BaseModel) for i in value): + v[key] = [i.model_dump() for i in value] + return json.dumps(v) + return v + + @validator("params", pre=True) + def validate_params(cls, v): + if isinstance(v, str): + try: + return json.loads(v) + except json.JSONDecodeError: + return v + return v + + @field_serializer("params") + def serialize_params(v): + if isinstance(v, list) and all(isinstance(i, BaseModel) for i in v): + return json.dumps([i.model_dump() for i in v]) + return v + + @validator("data", pre=True) + def validate_data(cls, v): + if isinstance(v, str): + return json.loads(v) + return v + + @validator("artifacts", pre=True) + def validate_artifacts(cls, v): + if isinstance(v, str): + return json.loads(v) + return v + + +class VertexBuildResponseModel(VertexBuildModel): + @field_serializer("data", "artifacts") + def serialize_dict(v): + return v + + +def to_map(value: dict): + keys = list(value.keys()) + values = list(value.values()) + return {"key": keys, "value": values} + + +class VertexBuildMapModel(BaseModel): + vertex_builds: dict[str, list[VertexBuildResponseModel]] + + @classmethod + def from_list_of_dicts(cls, vertex_build_dicts): + vertex_build_map = {} + for vertex_build_dict in vertex_build_dicts: + vertex_build = VertexBuildResponseModel(**vertex_build_dict) + if vertex_build.id not in vertex_build_map: + vertex_build_map[vertex_build.id] = [] + vertex_build_map[vertex_build.id].append(vertex_build) + return cls(vertex_builds=vertex_build_map) diff --git a/src/backend/base/langflow/services/monitor/service.py b/src/backend/base/langflow/services/monitor/service.py new file mode 100644 index 000000000..e3d56db52 --- /dev/null +++ b/src/backend/base/langflow/services/monitor/service.py @@ -0,0 +1,167 @@ +from datetime import datetime +from pathlib import Path +from typing import TYPE_CHECKING, Optional, Union + +import duckdb +from loguru import logger +from platformdirs import user_cache_dir + +from langflow.services.base import Service +from langflow.services.monitor.schema import MessageModel, TransactionModel, VertexBuildModel +from langflow.services.monitor.utils import add_row_to_table, drop_and_create_table_if_schema_mismatch + +if TYPE_CHECKING: + from langflow.services.settings.manager import SettingsService + + +class MonitorService(Service): + name = "monitor_service" + + def __init__(self, settings_service: "SettingsService"): + self.settings_service = settings_service + self.base_cache_dir = Path(user_cache_dir("langflow")) + self.db_path = self.base_cache_dir / "monitor.duckdb" + self.table_map = { + "transactions": TransactionModel, + "messages": MessageModel, + "vertex_builds": VertexBuildModel, + } + + try: + self.ensure_tables_exist() + except Exception as e: + logger.exception(f"Error initializing monitor service: {e}") + + def to_df(self, table_name): + return self.load_table_as_dataframe(table_name) + + def ensure_tables_exist(self): + for table_name, model in self.table_map.items(): + drop_and_create_table_if_schema_mismatch(str(self.db_path), table_name, model) + + def add_row( + self, + table_name: str, + data: Union[dict, TransactionModel, MessageModel, VertexBuildModel], + ): + # Make sure the model passed matches the table + + model = self.table_map.get(table_name) + if model is None: + raise ValueError(f"Unknown table name: {table_name}") + + # Connect to DuckDB and add the row + with duckdb.connect(str(self.db_path)) as conn: + add_row_to_table(conn, table_name, model, data) + + def load_table_as_dataframe(self, table_name): + with duckdb.connect(str(self.db_path)) as conn: + return conn.table(table_name).df() + + @staticmethod + def get_timestamp(): + return datetime.now().strftime("%Y-%m-%d %H:%M:%S") + + def get_vertex_builds( + self, + flow_id: Optional[str] = None, + vertex_id: Optional[str] = None, + valid: Optional[bool] = None, + order_by: Optional[str] = "timestamp", + ): + query = "SELECT id, flow_id, valid, params, data, artifacts, timestamp FROM vertex_builds" + conditions = [] + if flow_id: + conditions.append(f"flow_id = '{flow_id}'") + if vertex_id: + conditions.append(f"id = '{vertex_id}'") + if valid is not None: # Check for None because valid is a boolean + valid_str = "true" if valid else "false" + conditions.append(f"valid = {valid_str}") + + if conditions: + query += " WHERE " + " AND ".join(conditions) + + if order_by: + query += f" ORDER BY {order_by}" + + with duckdb.connect(str(self.db_path)) as conn: + df = conn.execute(query).df() + + return df.to_dict(orient="records") + + def delete_vertex_builds(self, flow_id: Optional[str] = None): + query = "DELETE FROM vertex_builds" + if flow_id: + query += f" WHERE flow_id = '{flow_id}'" + + with duckdb.connect(str(self.db_path)) as conn: + conn.execute(query) + + def delete_messages(self, session_id: str): + query = f"DELETE FROM messages WHERE session_id = '{session_id}'" + + with duckdb.connect(str(self.db_path)) as conn: + conn.execute(query) + + def add_message(self, message: MessageModel): + self.add_row("messages", message) + + def get_messages( + self, + sender: Optional[str] = None, + sender_name: Optional[str] = None, + session_id: Optional[str] = None, + order_by: Optional[str] = "timestamp", + order: Optional[str] = "DESC", + limit: Optional[int] = None, + ): + query = "SELECT sender_name, sender, session_id, message, artifacts, timestamp FROM messages" + conditions = [] + if sender: + conditions.append(f"sender = '{sender}'") + if sender_name: + conditions.append(f"sender_name = '{sender_name}'") + if session_id: + conditions.append(f"session_id = '{session_id}'") + + if conditions: + query += " WHERE " + " AND ".join(conditions) + + if order_by and order: + # Make sure the order is from newest to oldest + query += f" ORDER BY {order_by} {order.upper()}" + + if limit is not None: + query += f" LIMIT {limit}" + + with duckdb.connect(str(self.db_path)) as conn: + df = conn.execute(query).df() + + return df + + def get_transactions( + self, + source: Optional[str] = None, + target: Optional[str] = None, + status: Optional[str] = None, + order_by: Optional[str] = "timestamp", + ): + query = "SELECT source, target, target_args, status, error, timestamp FROM transactions" + conditions = [] + if source: + conditions.append(f"source = '{source}'") + if target: + conditions.append(f"target = '{target}'") + if status: + conditions.append(f"status = '{status}'") + + if conditions: + query += " WHERE " + " AND ".join(conditions) + + if order_by: + query += f" ORDER BY {order_by}" + with duckdb.connect(str(self.db_path)) as conn: + df = conn.execute(query).df() + + return df.to_dict(orient="records") diff --git a/src/backend/base/langflow/services/monitor/utils.py b/src/backend/base/langflow/services/monitor/utils.py new file mode 100644 index 000000000..a71653e82 --- /dev/null +++ b/src/backend/base/langflow/services/monitor/utils.py @@ -0,0 +1,159 @@ +from typing import TYPE_CHECKING, Any, Dict, Optional, Type, Union + +import duckdb +from loguru import logger +from pydantic import BaseModel + +from langflow.services.deps import get_monitor_service + +if TYPE_CHECKING: + from langflow.api.v1.schemas import ResultDataResponse + + +INDEX_KEY = "index" + + +def get_table_schema_as_dict(conn: duckdb.DuckDBPyConnection, table_name: str) -> dict: + result = conn.execute(f"PRAGMA table_info('{table_name}')").fetchall() + schema = {row[1]: row[2].upper() for row in result} + schema.pop(INDEX_KEY, None) + return schema + + +def model_to_sql_column_definitions(model: Type[BaseModel]) -> dict: + columns = {} + for field_name, field_type in model.model_fields.items(): + if hasattr(field_type.annotation, "__args__") and field_type.annotation is not None: + field_args = field_type.annotation.__args__ + else: + field_args = [] + field_info = field_args[0] if field_args else field_type.annotation + if field_info.__name__ == "int": + sql_type = "INTEGER" + elif field_info.__name__ == "str": + sql_type = "VARCHAR" + elif field_info.__name__ == "datetime": + sql_type = "TIMESTAMP" + elif field_info.__name__ == "bool": + sql_type = "BOOLEAN" + elif field_info.__name__ == "dict": + sql_type = "VARCHAR" + elif field_info.__name__ == "Any": + sql_type = "VARCHAR" + else: + continue # Skip types we don't handle + columns[field_name] = sql_type + return columns + + +def drop_and_create_table_if_schema_mismatch(db_path: str, table_name: str, model: Type[BaseModel]): + with duckdb.connect(db_path) as conn: + # Get the current schema from the database + try: + current_schema = get_table_schema_as_dict(conn, table_name) + except duckdb.CatalogException: + current_schema = {} + # Get the desired schema from the model + desired_schema = model_to_sql_column_definitions(model) + + # Compare the current and desired schemas + + if current_schema != desired_schema: + # If they don't match, drop the existing table and create a new one + conn.execute(f"DROP TABLE IF EXISTS {table_name}") + if "id" in desired_schema.keys(): + # Create a sequence for the id column + try: + conn.execute(f"CREATE SEQUENCE seq_{table_name} START 1;") + except duckdb.CatalogException: + pass + desired_schema[INDEX_KEY] = f"INTEGER PRIMARY KEY DEFAULT NEXTVAL('seq_{table_name}')" + columns_sql = ", ".join(f"{name} {data_type}" for name, data_type in desired_schema.items()) + create_table_sql = f"CREATE TABLE {table_name} ({columns_sql})" + conn.execute(create_table_sql) + + +def add_row_to_table( + conn: duckdb.DuckDBPyConnection, + table_name: str, + model: Type, + monitor_data: Union[Dict[str, Any], BaseModel], +): + # Validate the data with the Pydantic model + if isinstance(monitor_data, model): + validated_data = monitor_data + else: + validated_data = model(**monitor_data) + + # Extract data for the insert statement + validated_dict = validated_data.model_dump() + keys = [key for key in validated_dict.keys() if key != INDEX_KEY] + columns = ", ".join(keys) + + values_placeholders = ", ".join(["?" for _ in keys]) + values = list(validated_dict.values()) + + # Create the insert statement + insert_sql = f"INSERT INTO {table_name} ({columns}) VALUES ({values_placeholders})" + + # Execute the insert statement + try: + conn.execute(insert_sql, values) + except Exception as e: + # Log values types + for key, value in validated_dict.items(): + logger.error(f"{key}: {type(value)}") + + logger.error(f"Error adding row to table: {e}") + + +async def log_message( + sender: str, + sender_name: str, + message: str, + session_id: str, + artifacts: Optional[dict] = None, +): + try: + from langflow.graph.vertex.base import Vertex + + if isinstance(session_id, Vertex): + session_id = await session_id.build() # type: ignore + + monitor_service = get_monitor_service() + row = { + "sender": sender, + "sender_name": sender_name, + "message": message, + "artifacts": artifacts or {}, + "session_id": session_id, + "timestamp": monitor_service.get_timestamp(), + } + monitor_service.add_row(table_name="messages", data=row) + except Exception as e: + logger.error(f"Error logging message: {e}") + + +async def log_vertex_build( + flow_id: str, + vertex_id: str, + valid: bool, + params: Any, + data: "ResultDataResponse", + artifacts: Optional[dict] = None, +): + try: + monitor_service = get_monitor_service() + + row = { + "flow_id": flow_id, + "id": vertex_id, + "valid": valid, + "params": params, + "data": data.model_dump(), + "artifacts": artifacts or {}, + "timestamp": monitor_service.get_timestamp(), + } + monitor_service.add_row(table_name="vertex_builds", data=row) + except Exception as e: + logger.exception(f"Error logging vertex build: {e}") diff --git a/src/backend/base/langflow/services/plugins/__init__.py b/src/backend/base/langflow/services/plugins/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backend/langflow/services/plugins/base.py b/src/backend/base/langflow/services/plugins/base.py similarity index 100% rename from src/backend/langflow/services/plugins/base.py rename to src/backend/base/langflow/services/plugins/base.py diff --git a/src/backend/langflow/services/plugins/factory.py b/src/backend/base/langflow/services/plugins/factory.py similarity index 100% rename from src/backend/langflow/services/plugins/factory.py rename to src/backend/base/langflow/services/plugins/factory.py diff --git a/src/backend/langflow/services/plugins/langfuse_plugin.py b/src/backend/base/langflow/services/plugins/langfuse_plugin.py similarity index 99% rename from src/backend/langflow/services/plugins/langfuse_plugin.py rename to src/backend/base/langflow/services/plugins/langfuse_plugin.py index e5d3afdd6..e6d37d3c5 100644 --- a/src/backend/langflow/services/plugins/langfuse_plugin.py +++ b/src/backend/base/langflow/services/plugins/langfuse_plugin.py @@ -1,8 +1,9 @@ from typing import Optional +from loguru import logger + from langflow.services.deps import get_settings_service from langflow.services.plugins.base import CallbackPlugin -from loguru import logger class LangfuseInstance: diff --git a/src/backend/langflow/services/plugins/service.py b/src/backend/base/langflow/services/plugins/service.py similarity index 99% rename from src/backend/langflow/services/plugins/service.py rename to src/backend/base/langflow/services/plugins/service.py index f7b2895ec..98f210fea 100644 --- a/src/backend/langflow/services/plugins/service.py +++ b/src/backend/base/langflow/services/plugins/service.py @@ -3,9 +3,10 @@ import inspect import os from typing import TYPE_CHECKING, Union +from loguru import logger + from langflow.services.base import Service from langflow.services.plugins.base import BasePlugin, CallbackPlugin -from loguru import logger if TYPE_CHECKING: from langflow.services.settings.service import SettingsService diff --git a/src/backend/langflow/services/schema.py b/src/backend/base/langflow/services/schema.py similarity index 66% rename from src/backend/langflow/services/schema.py rename to src/backend/base/langflow/services/schema.py index 8265c1108..fe0d7022e 100644 --- a/src/backend/langflow/services/schema.py +++ b/src/backend/base/langflow/services/schema.py @@ -14,6 +14,10 @@ class ServiceType(str, Enum): CHAT_SERVICE = "chat_service" SESSION_SERVICE = "session_service" TASK_SERVICE = "task_service" - PLUGIN_SERVICE = "plugin_service" + PLUGINS_SERVICE = "plugins_service" STORE_SERVICE = "store_service" - CREDENTIAL_SERVICE = "credential_service" + VARIABLE_SERVICE = "variable_service" + STORAGE_SERVICE = "storage_service" + MONITOR_SERVICE = "monitor_service" + SOCKETIO_SERVICE = "socket_service" + STATE_SERVICE = "state_service" diff --git a/src/backend/base/langflow/services/session/__init__.py b/src/backend/base/langflow/services/session/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backend/langflow/services/session/factory.py b/src/backend/base/langflow/services/session/factory.py similarity index 72% rename from src/backend/langflow/services/session/factory.py rename to src/backend/base/langflow/services/session/factory.py index beb0bd6bd..d55bd5b46 100644 --- a/src/backend/langflow/services/session/factory.py +++ b/src/backend/base/langflow/services/session/factory.py @@ -1,14 +1,15 @@ from typing import TYPE_CHECKING -from langflow.services.session.service import SessionService + from langflow.services.factory import ServiceFactory +from langflow.services.session.service import SessionService if TYPE_CHECKING: - from langflow.services.cache.service import BaseCacheService + from langflow.services.cache.service import CacheService class SessionServiceFactory(ServiceFactory): def __init__(self): super().__init__(SessionService) - def create(self, cache_service: "BaseCacheService"): + def create(self, cache_service: "CacheService"): return SessionService(cache_service) diff --git a/src/backend/langflow/services/session/service.py b/src/backend/base/langflow/services/session/service.py similarity index 57% rename from src/backend/langflow/services/session/service.py rename to src/backend/base/langflow/services/session/service.py index 059d82bec..0c925db19 100644 --- a/src/backend/langflow/services/session/service.py +++ b/src/backend/base/langflow/services/session/service.py @@ -1,32 +1,33 @@ -from typing import TYPE_CHECKING, Optional +from typing import Coroutine, Optional from langflow.interface.run import build_sorted_vertices from langflow.services.base import Service +from langflow.services.cache.base import CacheService from langflow.services.session.utils import compute_dict_hash, session_id_generator -if TYPE_CHECKING: - from langflow.services.cache.base import BaseCacheService - class SessionService(Service): name = "session_service" def __init__(self, cache_service): - self.cache_service: "BaseCacheService" = cache_service + self.cache_service: "CacheService" = cache_service - async def load_session(self, key, data_graph: Optional[dict] = None): + async def load_session(self, key, flow_id: str, data_graph: Optional[dict] = None): # Check if the data is cached if key in self.cache_service: - return self.cache_service.get(key) + result = self.cache_service.get(key) + if isinstance(result, Coroutine): + result = await result + return result if key is None: key = self.generate_key(session_id=None, data_graph=data_graph) if data_graph is None: return (None, None) # If not cached, build the graph and cache it - graph, artifacts = await build_sorted_vertices(data_graph) + graph, artifacts = await build_sorted_vertices(data_graph, flow_id) - self.cache_service.set(key, (graph, artifacts)) + await self.cache_service.set(key, (graph, artifacts)) return graph, artifacts @@ -41,8 +42,14 @@ class SessionService(Service): session_id = session_id_generator() return self.build_key(session_id, data_graph=data_graph) - def update_session(self, session_id, value): - self.cache_service.set(session_id, value) + async def update_session(self, session_id, value): + result = self.cache_service.set(session_id, value) + # if it is a coroutine, await it + if isinstance(result, Coroutine): + await result - def clear_session(self, session_id): - self.cache_service.delete(session_id) + async def clear_session(self, session_id): + result = self.cache_service.delete(session_id) + # if it is a coroutine, await it + if isinstance(result, Coroutine): + await result diff --git a/src/backend/langflow/services/session/utils.py b/src/backend/base/langflow/services/session/utils.py similarity index 100% rename from src/backend/langflow/services/session/utils.py rename to src/backend/base/langflow/services/session/utils.py diff --git a/src/backend/langflow/services/settings/__init__.py b/src/backend/base/langflow/services/settings/__init__.py similarity index 100% rename from src/backend/langflow/services/settings/__init__.py rename to src/backend/base/langflow/services/settings/__init__.py diff --git a/src/backend/langflow/services/settings/auth.py b/src/backend/base/langflow/services/settings/auth.py similarity index 81% rename from src/backend/langflow/services/settings/auth.py rename to src/backend/base/langflow/services/settings/auth.py index 8463d0781..103c96a40 100644 --- a/src/backend/langflow/services/settings/auth.py +++ b/src/backend/base/langflow/services/settings/auth.py @@ -1,32 +1,29 @@ import secrets from pathlib import Path -from typing import Optional +from typing import Literal -from langflow.services.settings.constants import ( - DEFAULT_SUPERUSER, - DEFAULT_SUPERUSER_PASSWORD, -) -from langflow.services.settings.utils import read_secret_from_file, write_secret_to_file from loguru import logger from passlib.context import CryptContext -from pydantic import Field, validator +from pydantic import Field, SecretStr, validator from pydantic_settings import BaseSettings +from langflow.services.settings.constants import DEFAULT_SUPERUSER, DEFAULT_SUPERUSER_PASSWORD +from langflow.services.settings.utils import read_secret_from_file, write_secret_to_file + class AuthSettings(BaseSettings): # Login settings CONFIG_DIR: str - SECRET_KEY: str = Field( - default="", + SECRET_KEY: SecretStr = Field( + default=SecretStr(""), description="Secret key for JWT. If not provided, a random one will be generated.", frozen=False, ) ALGORITHM: str = "HS256" - ACCESS_TOKEN_EXPIRE_MINUTES: int = 60 - REFRESH_TOKEN_EXPIRE_MINUTES: int = 60 * 12 * 7 + ACCESS_TOKEN_EXPIRE_SECONDS: int = 60 * 60 # 1 hour + REFRESH_TOKEN_EXPIRE_SECONDS: int = 60 * 60 * 24 * 7 # 7 days # API Key to execute /process endpoint - API_KEY_SECRET_KEY: Optional[str] = "b82818e0ad4ff76615c5721ee21004b07d84cd9b87ba4d9cb42374da134b841a" API_KEY_ALGORITHM: str = "HS256" API_V1_STR: str = "/api/v1" @@ -37,15 +34,15 @@ class AuthSettings(BaseSettings): SUPERUSER: str = DEFAULT_SUPERUSER SUPERUSER_PASSWORD: str = DEFAULT_SUPERUSER_PASSWORD - REFRESH_SAME_SITE: str = "none" + REFRESH_SAME_SITE: Literal["lax", "strict", "none"] = "none" """The SameSite attribute of the refresh token cookie.""" REFRESH_SECURE: bool = True """The Secure attribute of the refresh token cookie.""" REFRESH_HTTPONLY: bool = True """The HttpOnly attribute of the refresh token cookie.""" - ACCESS_SAME_SITE: str = "none" + ACCESS_SAME_SITE: Literal["lax", "strict", "none"] = "lax" """The SameSite attribute of the access token cookie.""" - ACCESS_SECURE: bool = True + ACCESS_SECURE: bool = False """The Secure attribute of the access token cookie.""" ACCESS_HTTPONLY: bool = False """The HttpOnly attribute of the access token cookie.""" @@ -89,9 +86,10 @@ class AuthSettings(BaseSettings): secret_key_path = Path(config_dir) / "secret_key" - if value: + if value and isinstance(value, SecretStr): logger.debug("Secret key provided") - write_secret_to_file(secret_key_path, value) + secret_value = value.get_secret_value() + write_secret_to_file(secret_key_path, secret_value) else: logger.debug("No secret key provided, generating a random one") @@ -107,4 +105,4 @@ class AuthSettings(BaseSettings): write_secret_to_file(secret_key_path, value) logger.debug("Saved secret key") - return value + return value if isinstance(value, SecretStr) else SecretStr(value) diff --git a/src/backend/langflow/services/settings/base.py b/src/backend/base/langflow/services/settings/base.py similarity index 98% rename from src/backend/langflow/services/settings/base.py rename to src/backend/base/langflow/services/settings/base.py index f68afb0f4..9c7ab21c4 100644 --- a/src/backend/langflow/services/settings/base.py +++ b/src/backend/base/langflow/services/settings/base.py @@ -38,7 +38,7 @@ class Settings(BaseSettings): DEV: bool = False DATABASE_URL: Optional[str] = None - CACHE_TYPE: str = "memory" + CACHE_TYPE: str = "async" REMOVE_API_KEYS: bool = False COMPONENTS_PATH: List[str] = [] LANGCHAIN_CACHE: str = "InMemoryCache" @@ -63,6 +63,10 @@ class Settings(BaseSettings): ] = "https://api.langflow.store/flows/trigger/ec611a61-8460-4438-b187-a4f65e5559d4" LIKE_WEBHOOK_URL: Optional[str] = "https://api.langflow.store/flows/trigger/64275852-ec00-45c1-984e-3bff814732da" + STORAGE_TYPE: str = "local" + + CELERY_ENABLED: bool = False + @validator("CONFIG_DIR", pre=True, allow_reuse=True) def set_langflow_dir(cls, value): if not value: diff --git a/src/backend/langflow/services/settings/constants.py b/src/backend/base/langflow/services/settings/constants.py similarity index 100% rename from src/backend/langflow/services/settings/constants.py rename to src/backend/base/langflow/services/settings/constants.py diff --git a/src/backend/langflow/services/settings/factory.py b/src/backend/base/langflow/services/settings/factory.py similarity index 99% rename from src/backend/langflow/services/settings/factory.py rename to src/backend/base/langflow/services/settings/factory.py index 713f13f82..a94e0abbe 100644 --- a/src/backend/langflow/services/settings/factory.py +++ b/src/backend/base/langflow/services/settings/factory.py @@ -1,6 +1,7 @@ from pathlib import Path -from langflow.services.settings.service import SettingsService + from langflow.services.factory import ServiceFactory +from langflow.services.settings.service import SettingsService class SettingsServiceFactory(ServiceFactory): diff --git a/src/backend/langflow/services/settings/service.py b/src/backend/base/langflow/services/settings/manager.py similarity index 99% rename from src/backend/langflow/services/settings/service.py rename to src/backend/base/langflow/services/settings/manager.py index a57a59eb8..f81c3f0c5 100644 --- a/src/backend/langflow/services/settings/service.py +++ b/src/backend/base/langflow/services/settings/manager.py @@ -1,9 +1,11 @@ +import os + +import yaml +from loguru import logger + from langflow.services.base import Service from langflow.services.settings.auth import AuthSettings from langflow.services.settings.base import Settings -from loguru import logger -import os -import yaml class SettingsService(Service): diff --git a/src/backend/base/langflow/services/settings/service.py b/src/backend/base/langflow/services/settings/service.py new file mode 100644 index 000000000..a66888924 --- /dev/null +++ b/src/backend/base/langflow/services/settings/service.py @@ -0,0 +1,44 @@ +import os + +import yaml +from loguru import logger + +from langflow.services.base import Service +from langflow.services.settings.auth import AuthSettings +from langflow.services.settings.base import Settings + + +class SettingsService(Service): + name = "settings_service" + + def __init__(self, settings: Settings, auth_settings: AuthSettings): + super().__init__() + self.settings: Settings = settings + self.auth_settings: AuthSettings = auth_settings + + @classmethod + def load_settings_from_yaml(cls, file_path: str) -> "SettingsService": + # Check if a string is a valid path or a file name + if "/" not in file_path: + # Get current path + current_path = os.path.dirname(os.path.abspath(__file__)) + + file_path = os.path.join(current_path, file_path) + + with open(file_path, "r") as f: + settings_dict = yaml.safe_load(f) + settings_dict = {k.upper(): v for k, v in settings_dict.items()} + + for key in settings_dict: + if key not in Settings.model_fields.keys(): + raise KeyError(f"Key {key} not found in settings") + logger.debug(f"Loading {len(settings_dict[key])} {key} from {file_path}") + + settings = Settings(**settings_dict) + if not settings.CONFIG_DIR: + raise ValueError("CONFIG_DIR must be set in settings") + + auth_settings = AuthSettings( + CONFIG_DIR=settings.CONFIG_DIR, + ) + return cls(settings, auth_settings) diff --git a/src/backend/langflow/services/settings/utils.py b/src/backend/base/langflow/services/settings/utils.py similarity index 100% rename from src/backend/langflow/services/settings/utils.py rename to src/backend/base/langflow/services/settings/utils.py diff --git a/src/backend/base/langflow/services/socket/__init__.py b/src/backend/base/langflow/services/socket/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backend/base/langflow/services/socket/factory.py b/src/backend/base/langflow/services/socket/factory.py new file mode 100644 index 000000000..3ea6bb0ba --- /dev/null +++ b/src/backend/base/langflow/services/socket/factory.py @@ -0,0 +1,17 @@ +from typing import TYPE_CHECKING + +from langflow.services.factory import ServiceFactory +from langflow.services.socket.service import SocketIOService + +if TYPE_CHECKING: + from langflow.services.cache.service import CacheService + + +class SocketIOFactory(ServiceFactory): + def __init__(self): + super().__init__( + service_class=SocketIOService, + ) + + def create(self, cache_service: "CacheService"): + return SocketIOService(cache_service) diff --git a/src/backend/base/langflow/services/socket/service.py b/src/backend/base/langflow/services/socket/service.py new file mode 100644 index 000000000..45cfc5fbc --- /dev/null +++ b/src/backend/base/langflow/services/socket/service.py @@ -0,0 +1,86 @@ +from typing import TYPE_CHECKING, Any + +import socketio # type: ignore +from loguru import logger + +from langflow.services.base import Service +from langflow.services.deps import get_chat_service +from langflow.services.socket.utils import build_vertex, get_vertices + +if TYPE_CHECKING: + from langflow.services.cache.service import CacheService + + +class SocketIOService(Service): + name = "socket_service" + + def __init__(self, cache_service: "CacheService"): + self.cache_service = cache_service + + def init(self, sio: socketio.AsyncServer): + # Registering event handlers + self.sio = sio + if self.sio: + self.sio.event(self.connect) + self.sio.event(self.disconnect) + self.sio.on("message")(self.message) + self.sio.on("get_vertices")(self.on_get_vertices) + self.sio.on("build_vertex")(self.on_build_vertex) + self.sessions = {} # type: dict[str, dict] + + async def emit_error(self, sid, error): + await self.sio.emit("error", to=sid, data=error) + + async def connect(self, sid, environ): + logger.info(f"Socket connected: {sid}") + self.sessions[sid] = environ + + async def disconnect(self, sid): + logger.info(f"Socket disconnected: {sid}") + self.sessions.pop(sid, None) + + async def message(self, sid, data=None): + # Logic for handling messages + await self.emit_message(to=sid, data=data or {"foo": "bar", "baz": [1, 2, 3]}) + + async def emit_message(self, to, data): + # Abstracting sio.emit + await self.sio.emit("message", to=to, data=data) + + async def emit_token(self, to, data): + await self.sio.emit("token", to=to, data=data) + + async def on_get_vertices(self, sid, flow_id): + await get_vertices(self.sio, sid, flow_id, get_chat_service()) + + async def on_build_vertex(self, sid, flow_id, vertex_id, tweaks, inputs): + await build_vertex( + sio=self.sio, + sid=sid, + flow_id=flow_id, + vertex_id=vertex_id, + tweaks=tweaks, + inputs=inputs, + get_cache=self.get_cache, + set_cache=self.set_cache, + ) + + def get_cache(self, sid: str) -> Any: + """ + Get the cache for a client. + """ + return self.cache_service.get(sid) + + def set_cache(self, sid: str, build_result: Any) -> bool: + """ + Set the cache for a client. + """ + # client_id is the flow id but that already exists in the cache + # so we need to change it to something else + + result_dict = { + "result": build_result, + "type": type(build_result), + } + self.cache_service.upsert(sid, result_dict) + return sid in self.cache_service diff --git a/src/backend/base/langflow/services/socket/utils.py b/src/backend/base/langflow/services/socket/utils.py new file mode 100644 index 000000000..c1f012e18 --- /dev/null +++ b/src/backend/base/langflow/services/socket/utils.py @@ -0,0 +1,103 @@ +import time +from typing import Callable + +import socketio # type: ignore +from sqlmodel import select + +from langflow.api.utils import format_elapsed_time +from langflow.api.v1.schemas import ResultDataResponse, VertexBuildResponse +from langflow.graph.graph.base import Graph +from langflow.graph.vertex.base import Vertex +from langflow.services.database.models.flow.model import Flow +from langflow.services.deps import get_session +from langflow.services.monitor.utils import log_vertex_build + + +def set_socketio_server(socketio_server): + from langflow.services.deps import get_socket_service + + socket_service = get_socket_service() + socket_service.init(socketio_server) + + +async def get_vertices(sio, sid, flow_id, chat_service): + try: + session = get_session() + flow: Flow = session.exec(select(Flow).where(Flow.id == flow_id)).first() + if not flow or not flow.data: + await sio.emit("error", data="Invalid flow ID", to=sid) + return + + graph = Graph.from_payload(flow.data) + chat_service.set_cache(flow_id, graph) + vertices = graph.layered_topological_sort() + + # Emit the vertices to the client + await sio.emit("vertices_order", data=vertices, to=sid) + + except Exception as exc: + await sio.emit("error", data=str(exc), to=sid) + + +async def build_vertex( + sio: socketio.AsyncServer, + sid: str, + flow_id: str, + vertex_id: str, + get_cache: Callable, + set_cache: Callable, + tweaks=None, + inputs=None, +): + try: + cache = get_cache(flow_id) + graph = cache.get("result") + + if not isinstance(graph, Graph): + await sio.emit("error", data="Invalid graph", to=sid) + return + + vertex = graph.get_vertex(vertex_id) + if not vertex: + await sio.emit("error", data="Invalid vertex", to=sid) + return + start_time = time.perf_counter() + try: + if isinstance(vertex, Vertex) or not vertex._built: + await vertex.build(user_id=None, session_id=sid) + params = vertex._built_object_repr() + valid = True + result_dict = vertex.get_built_result() + # We need to set the artifacts to pass information + # to the frontend + vertex.set_artifacts() + artifacts = vertex.artifacts + timedelta = time.perf_counter() - start_time + duration = format_elapsed_time(timedelta) + result_dict = ResultDataResponse( + results=result_dict, + artifacts=artifacts, + duration=duration, + timedelta=timedelta, + ) + except Exception as exc: + params = str(exc) + valid = False + result_dict = ResultDataResponse(results={}) + artifacts = {} + set_cache(flow_id, graph) + await log_vertex_build( + flow_id=flow_id, + vertex_id=vertex_id, + valid=valid, + params=params, + data=result_dict, + artifacts=artifacts, + ) + + # Emit the vertex build response + response = VertexBuildResponse(valid=valid, params=params, id=vertex.id, data=result_dict) + await sio.emit("vertex_build", data=response.model_dump(), to=sid) + + except Exception as exc: + await sio.emit("error", data=str(exc), to=sid) diff --git a/src/backend/base/langflow/services/state/__init__.py b/src/backend/base/langflow/services/state/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backend/base/langflow/services/state/factory.py b/src/backend/base/langflow/services/state/factory.py new file mode 100644 index 000000000..e6c5ee740 --- /dev/null +++ b/src/backend/base/langflow/services/state/factory.py @@ -0,0 +1,13 @@ +from langflow.services.factory import ServiceFactory +from langflow.services.settings.service import SettingsService +from langflow.services.state.service import InMemoryStateService + + +class StateServiceFactory(ServiceFactory): + def __init__(self): + super().__init__(InMemoryStateService) + + def create(self, settings_service: SettingsService): + return InMemoryStateService( + settings_service, + ) diff --git a/src/backend/base/langflow/services/state/service.py b/src/backend/base/langflow/services/state/service.py new file mode 100644 index 000000000..b56f95148 --- /dev/null +++ b/src/backend/base/langflow/services/state/service.py @@ -0,0 +1,74 @@ +from collections import defaultdict +from threading import Lock +from typing import Callable + +from loguru import logger + +from langflow.services.base import Service +from langflow.services.settings.service import SettingsService + + +class StateService(Service): + name = "state_service" + + def append_state(self, key, new_state, run_id: str): + raise NotImplementedError + + def update_state(self, key, new_state, run_id: str): + raise NotImplementedError + + def get_state(self, key, run_id: str): + raise NotImplementedError + + def subscribe(self, key, observer: Callable): + raise NotImplementedError + + def notify_observers(self, key, new_state): + raise NotImplementedError + + +class InMemoryStateService(StateService): + def __init__(self, settings_service: SettingsService): + self.settings_service = settings_service + self.states: dict = {} + self.observers: dict = defaultdict(list) + self.lock = Lock() + + def append_state(self, key, new_state, run_id: str): + with self.lock: + if run_id not in self.states: + self.states[run_id] = {} + if key not in self.states[run_id]: + self.states[run_id][key] = [] + elif not isinstance(self.states[run_id][key], list): + self.states[run_id][key] = [self.states[run_id][key]] + self.states[run_id][key].append(new_state) + self.notify_append_observers(key, new_state) + + def update_state(self, key, new_state, run_id: str): + with self.lock: + if run_id not in self.states: + self.states[run_id] = {} + self.states[run_id][key] = new_state + self.notify_observers(key, new_state) + + def get_state(self, key, run_id: str): + with self.lock: + return self.states.get(run_id, {}).get(key, "") + + def subscribe(self, key, observer: Callable): + with self.lock: + if observer not in self.observers[key]: + self.observers[key].append(observer) + + def notify_observers(self, key, new_state): + for callback in self.observers[key]: + callback(key, new_state, append=False) + + def notify_append_observers(self, key, new_state): + for callback in self.observers[key]: + try: + callback(key, new_state, append=True) + except Exception as e: + logger.error(f"Error in observer {callback} for key {key}: {e}") + logger.warning("Callbacks not implemented yet") diff --git a/src/backend/base/langflow/services/storage/__init__.py b/src/backend/base/langflow/services/storage/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backend/base/langflow/services/storage/constants.py b/src/backend/base/langflow/services/storage/constants.py new file mode 100644 index 000000000..ddec29f3f --- /dev/null +++ b/src/backend/base/langflow/services/storage/constants.py @@ -0,0 +1,28 @@ +EXTENSION_TO_CONTENT_TYPE = { + "json": "application/json", + "txt": "text/plain", + "csv": "text/csv", + "html": "text/html", + "pdf": "application/pdf", + "png": "image/png", + "jpg": "image/jpeg", + "jpeg": "image/jpeg", + "gif": "image/gif", + "svg": "image/svg+xml", + "mp3": "audio/mpeg", + "wav": "audio/wav", + "mp4": "video/mp4", + "webm": "video/webm", + "zip": "application/zip", + "tar": "application/x-tar", + "gz": "application/gzip", + "doc": "application/msword", + "docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "xls": "application/vnd.ms-excel", + "xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "ppt": "application/vnd.ms-powerpoint", + "pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation", + "xml": "application/xml", + "yaml": "application/x-yaml", + "yml": "application/x-yaml", +} diff --git a/src/backend/base/langflow/services/storage/factory.py b/src/backend/base/langflow/services/storage/factory.py new file mode 100644 index 000000000..1b2baf050 --- /dev/null +++ b/src/backend/base/langflow/services/storage/factory.py @@ -0,0 +1,29 @@ +from loguru import logger + +from langflow.services.factory import ServiceFactory +from langflow.services.session.service import SessionService +from langflow.services.settings.service import SettingsService +from langflow.services.storage.service import StorageService + + +class StorageServiceFactory(ServiceFactory): + def __init__(self): + super().__init__( + StorageService, + ) + + def create(self, session_service: SessionService, settings_service: SettingsService): + storage_type = settings_service.settings.STORAGE_TYPE + if storage_type.lower() == "local": + from .local import LocalStorageService + + return LocalStorageService(session_service, settings_service) + elif storage_type.lower() == "s3": + from .s3 import S3StorageService + + return S3StorageService(session_service, settings_service) + else: + logger.warning(f"Storage type {storage_type} not supported. Using local storage.") + from .local import LocalStorageService + + return LocalStorageService(session_service, settings_service) diff --git a/src/backend/base/langflow/services/storage/local.py b/src/backend/base/langflow/services/storage/local.py new file mode 100644 index 000000000..815059857 --- /dev/null +++ b/src/backend/base/langflow/services/storage/local.py @@ -0,0 +1,95 @@ +from pathlib import Path + +from loguru import logger + +from .service import StorageService + + +class LocalStorageService(StorageService): + """A service class for handling local storage operations without aiofiles.""" + + def __init__(self, session_service, settings_service): + """Initialize the local storage service with session and settings services.""" + super().__init__(session_service, settings_service) + self.data_dir = Path(settings_service.settings.CONFIG_DIR) + self.set_ready() + + def build_full_path(self, flow_id: str, file_name: str) -> str: + """Build the full path of a file in the local storage.""" + return str(self.data_dir / flow_id / file_name) + + async def save_file(self, flow_id: str, file_name: str, data: bytes): + """ + Save a file in the local storage. + + :param flow_id: The identifier for the flow. + :param file_name: The name of the file to be saved. + :param data: The byte content of the file. + :raises FileNotFoundError: If the specified flow does not exist. + :raises IsADirectoryError: If the file name is a directory. + :raises PermissionError: If there is no permission to write the file. + """ + folder_path = self.data_dir / flow_id + folder_path.mkdir(parents=True, exist_ok=True) + file_path = folder_path / file_name + + try: + with open(file_path, "wb") as f: + f.write(data) + logger.info(f"File {file_name} saved successfully in flow {flow_id}.") + except Exception as e: + logger.error(f"Error saving file {file_name} in flow {flow_id}: {e}") + raise e + + async def get_file(self, flow_id: str, file_name: str) -> bytes: + """ + Retrieve a file from the local storage. + + :param flow_id: The identifier for the flow. + :param file_name: The name of the file to be retrieved. + :return: The byte content of the file. + :raises FileNotFoundError: If the file does not exist. + """ + file_path = self.data_dir / flow_id / file_name + if not file_path.exists(): + logger.warning(f"File {file_name} not found in flow {flow_id}.") + raise FileNotFoundError(f"File {file_name} not found in flow {flow_id}") + + with open(file_path, "rb") as f: + logger.info(f"File {file_name} retrieved successfully from flow {flow_id}.") + return f.read() + + async def list_files(self, flow_id: str): + """ + List all files in a specified flow. + + :param flow_id: The identifier for the flow. + :return: A list of file names. + :raises FileNotFoundError: If the flow directory does not exist. + """ + folder_path = self.data_dir / flow_id + if not folder_path.exists() or not folder_path.is_dir(): + logger.warning(f"Flow {flow_id} directory does not exist.") + raise FileNotFoundError(f"Flow {flow_id} directory does not exist.") + + files = [file.name for file in folder_path.iterdir() if file.is_file()] + logger.info(f"Listed {len(files)} files in flow {flow_id}.") + return files + + async def delete_file(self, flow_id: str, file_name: str): + """ + Delete a file from the local storage. + + :param flow_id: The identifier for the flow. + :param file_name: The name of the file to be deleted. + """ + file_path = self.data_dir / flow_id / file_name + if file_path.exists(): + file_path.unlink() + logger.info(f"File {file_name} deleted successfully from flow {flow_id}.") + else: + logger.warning(f"Attempted to delete non-existent file {file_name} in flow {flow_id}.") + + def teardown(self): + """Perform any cleanup operations when the service is being torn down.""" + pass # No specific teardown actions required for local diff --git a/src/backend/base/langflow/services/storage/s3.py b/src/backend/base/langflow/services/storage/s3.py new file mode 100644 index 000000000..4426f377c --- /dev/null +++ b/src/backend/base/langflow/services/storage/s3.py @@ -0,0 +1,89 @@ +import boto3 # type: ignore +from botocore.exceptions import ClientError, NoCredentialsError # type: ignore +from loguru import logger + +from .service import StorageService + + +class S3StorageService(StorageService): + """A service class for handling operations with AWS S3 storage.""" + + async def __init__(self, session_service, settings_service): + """Initialize the S3 storage service with session and settings services.""" + super().__init__(session_service, settings_service) + self.bucket = "langflow" + self.s3_client = boto3.client("s3") + self.set_ready() + + async def save_file(self, folder: str, file_name: str, data): + """ + Save a file to the S3 bucket. + + :param folder: The folder in the bucket to save the file. + :param file_name: The name of the file to be saved. + :param data: The byte content of the file. + :raises Exception: If an error occurs during file saving. + """ + try: + self.s3_client.put_object(Bucket=self.bucket, Key=f"{folder}/{file_name}", Body=data) + logger.info(f"File {file_name} saved successfully in folder {folder}.") + except NoCredentialsError: + logger.error("Credentials not available for AWS S3.") + raise + except ClientError as e: + logger.error(f"Error saving file {file_name} in folder {folder}: {e}") + raise + + async def get_file(self, folder: str, file_name: str): + """ + Retrieve a file from the S3 bucket. + + :param folder: The folder in the bucket where the file is stored. + :param file_name: The name of the file to be retrieved. + :return: The byte content of the file. + :raises Exception: If an error occurs during file retrieval. + """ + try: + response = self.s3_client.get_object(Bucket=self.bucket, Key=f"{folder}/{file_name}") + logger.info(f"File {file_name} retrieved successfully from folder {folder}.") + return response["Body"].read() + except ClientError as e: + logger.error(f"Error retrieving file {file_name} from folder {folder}: {e}") + raise + + async def list_files(self, folder: str): + """ + List all files in a specified folder of the S3 bucket. + + :param folder: The folder in the bucket to list files from. + :return: A list of file names. + :raises Exception: If an error occurs during file listing. + """ + try: + response = self.s3_client.list_objects_v2(Bucket=self.bucket, Prefix=folder) + files = [item["Key"] for item in response.get("Contents", []) if "/" not in item["Key"][len(folder) :]] + logger.info(f"{len(files)} files listed in folder {folder}.") + return files + except ClientError as e: + logger.error(f"Error listing files in folder {folder}: {e}") + raise + + async def delete_file(self, folder: str, file_name: str): + """ + Delete a file from the S3 bucket. + + :param folder: The folder in the bucket where the file is stored. + :param file_name: The name of the file to be deleted. + :raises Exception: If an error occurs during file deletion. + """ + try: + self.s3_client.delete_object(Bucket=self.bucket, Key=f"{folder}/{file_name}") + logger.info(f"File {file_name} deleted successfully from folder {folder}.") + except ClientError as e: + logger.error(f"Error deleting file {file_name} from folder {folder}: {e}") + raise + + async def teardown(self): + """Perform any cleanup operations when the service is being torn down.""" + # No specific teardown actions required for S3 storage at the moment. + pass diff --git a/src/backend/base/langflow/services/storage/service.py b/src/backend/base/langflow/services/storage/service.py new file mode 100644 index 000000000..ac226bc31 --- /dev/null +++ b/src/backend/base/langflow/services/storage/service.py @@ -0,0 +1,42 @@ +from abc import abstractmethod +from typing import TYPE_CHECKING + +from langflow.services.base import Service + +if TYPE_CHECKING: + from langflow.services.session.service import SessionService + from langflow.services.settings.service import SettingsService + + +class StorageService(Service): + name = "storage_service" + + def __init__(self, session_service: "SessionService", settings_service: "SettingsService"): + self.settings_service = settings_service + self.session_service = session_service + self.set_ready() + + def build_full_path(self, flow_id: str, file_name: str) -> str: + raise NotImplementedError + + def set_ready(self): + self.ready = True + + @abstractmethod + async def save_file(self, flow_id: str, file_name: str, data) -> None: + raise NotImplementedError + + @abstractmethod + async def get_file(self, flow_id: str, file_name: str) -> bytes: + raise NotImplementedError + + @abstractmethod + async def list_files(self, flow_id: str) -> list[str]: + raise NotImplementedError + + @abstractmethod + async def delete_file(self, flow_id: str, file_name: str) -> bool: + raise NotImplementedError + + def teardown(self): + raise NotImplementedError diff --git a/src/backend/base/langflow/services/storage/utils.py b/src/backend/base/langflow/services/storage/utils.py new file mode 100644 index 000000000..a5515171b --- /dev/null +++ b/src/backend/base/langflow/services/storage/utils.py @@ -0,0 +1,5 @@ +from langflow.services.storage.constants import EXTENSION_TO_CONTENT_TYPE + + +def build_content_type_from_extension(extension: str): + return EXTENSION_TO_CONTENT_TYPE.get(extension.lower(), "application/octet-stream") diff --git a/src/backend/base/langflow/services/store/__init__.py b/src/backend/base/langflow/services/store/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backend/langflow/services/store/exceptions.py b/src/backend/base/langflow/services/store/exceptions.py similarity index 100% rename from src/backend/langflow/services/store/exceptions.py rename to src/backend/base/langflow/services/store/exceptions.py diff --git a/src/backend/langflow/services/store/factory.py b/src/backend/base/langflow/services/store/factory.py similarity index 99% rename from src/backend/langflow/services/store/factory.py rename to src/backend/base/langflow/services/store/factory.py index a25ad78c7..2bdc918bd 100644 --- a/src/backend/langflow/services/store/factory.py +++ b/src/backend/base/langflow/services/store/factory.py @@ -1,6 +1,7 @@ from typing import TYPE_CHECKING -from langflow.services.store.service import StoreService + from langflow.services.factory import ServiceFactory +from langflow.services.store.service import StoreService if TYPE_CHECKING: from langflow.services.settings.service import SettingsService diff --git a/src/backend/langflow/services/store/schema.py b/src/backend/base/langflow/services/store/schema.py similarity index 100% rename from src/backend/langflow/services/store/schema.py rename to src/backend/base/langflow/services/store/schema.py diff --git a/src/backend/langflow/services/store/service.py b/src/backend/base/langflow/services/store/service.py similarity index 100% rename from src/backend/langflow/services/store/service.py rename to src/backend/base/langflow/services/store/service.py diff --git a/src/backend/langflow/services/store/utils.py b/src/backend/base/langflow/services/store/utils.py similarity index 100% rename from src/backend/langflow/services/store/utils.py rename to src/backend/base/langflow/services/store/utils.py diff --git a/src/backend/base/langflow/services/task/__init__.py b/src/backend/base/langflow/services/task/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backend/base/langflow/services/task/backends/__init__.py b/src/backend/base/langflow/services/task/backends/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backend/langflow/services/task/backends/anyio.py b/src/backend/base/langflow/services/task/backends/anyio.py similarity index 100% rename from src/backend/langflow/services/task/backends/anyio.py rename to src/backend/base/langflow/services/task/backends/anyio.py diff --git a/src/backend/langflow/services/task/backends/base.py b/src/backend/base/langflow/services/task/backends/base.py similarity index 95% rename from src/backend/langflow/services/task/backends/base.py rename to src/backend/base/langflow/services/task/backends/base.py index ccbd9273b..93fbfd858 100644 --- a/src/backend/langflow/services/task/backends/base.py +++ b/src/backend/base/langflow/services/task/backends/base.py @@ -3,6 +3,8 @@ from typing import Any, Callable class TaskBackend(ABC): + name: str + @abstractmethod def launch_task(self, task_func: Callable[..., Any], *args: Any, **kwargs: Any): pass diff --git a/src/backend/langflow/services/task/backends/celery.py b/src/backend/base/langflow/services/task/backends/celery.py similarity index 99% rename from src/backend/langflow/services/task/backends/celery.py rename to src/backend/base/langflow/services/task/backends/celery.py index f23374549..cfb17ae3b 100644 --- a/src/backend/langflow/services/task/backends/celery.py +++ b/src/backend/base/langflow/services/task/backends/celery.py @@ -1,5 +1,8 @@ from typing import Any, Callable + from celery.result import AsyncResult # type: ignore + + from langflow.services.task.backends.base import TaskBackend from langflow.worker import celery_app diff --git a/src/backend/langflow/services/task/factory.py b/src/backend/base/langflow/services/task/factory.py similarity index 100% rename from src/backend/langflow/services/task/factory.py rename to src/backend/base/langflow/services/task/factory.py index e87eecc94..937f390ae 100644 --- a/src/backend/langflow/services/task/factory.py +++ b/src/backend/base/langflow/services/task/factory.py @@ -1,5 +1,5 @@ -from langflow.services.task.service import TaskService from langflow.services.factory import ServiceFactory +from langflow.services.task.service import TaskService class TaskServiceFactory(ServiceFactory): diff --git a/src/backend/langflow/services/task/service.py b/src/backend/base/langflow/services/task/service.py similarity index 76% rename from src/backend/langflow/services/task/service.py rename to src/backend/base/langflow/services/task/service.py index 3f7a81f2c..487b507cd 100644 --- a/src/backend/langflow/services/task/service.py +++ b/src/backend/base/langflow/services/task/service.py @@ -1,11 +1,14 @@ -from typing import Any, Callable, Coroutine, Union +from typing import TYPE_CHECKING, Any, Callable, Coroutine + +from loguru import logger from langflow.services.base import Service from langflow.services.task.backends.anyio import AnyIOBackend from langflow.services.task.backends.base import TaskBackend from langflow.services.task.utils import get_celery_worker_status -from langflow.utils.logger import configure -from loguru import logger + +if TYPE_CHECKING: + from langflow.services.settings.service import SettingsService def check_celery_availability(): @@ -20,28 +23,31 @@ def check_celery_availability(): return status -try: - configure() - status = check_celery_availability() - - USE_CELERY = status.get("availability") is not None -except ImportError: - USE_CELERY = False - - class TaskService(Service): name = "task_service" - def __init__(self): - self.backend = self.get_backend() + def __init__(self, settings_service: "SettingsService"): + self.settings_service = settings_service + try: + if self.settings_service.settings.CELERY_ENABLED: + USE_CELERY = True + status = check_celery_availability() + + USE_CELERY = status.get("availability") is not None + else: + USE_CELERY = False + except ImportError: + USE_CELERY = False + self.use_celery = USE_CELERY + self.backend = self.get_backend() @property def backend_name(self) -> str: return self.backend.name def get_backend(self) -> TaskBackend: - if USE_CELERY: + if self.use_celery: from langflow.services.task.backends.celery import CeleryBackend logger.debug("Using Celery backend") @@ -74,5 +80,5 @@ class TaskService(Service): task = self.backend.launch_task(task_func, *args, **kwargs) return await task if isinstance(task, Coroutine) else task - def get_task(self, task_id: Union[int, str]) -> Any: + def get_task(self, task_id: str) -> Any: return self.backend.get_task(task_id) diff --git a/src/backend/langflow/services/task/utils.py b/src/backend/base/langflow/services/task/utils.py similarity index 100% rename from src/backend/langflow/services/task/utils.py rename to src/backend/base/langflow/services/task/utils.py diff --git a/src/backend/langflow/services/utils.py b/src/backend/base/langflow/services/utils.py similarity index 71% rename from src/backend/langflow/services/utils.py rename to src/backend/base/langflow/services/utils.py index fcb077538..10c1a359e 100644 --- a/src/backend/langflow/services/utils.py +++ b/src/backend/base/langflow/services/utils.py @@ -1,59 +1,41 @@ +import importlib +import inspect + from loguru import logger from sqlmodel import Session, select from langflow.services.auth.utils import create_super_user, verify_password from langflow.services.database.utils import initialize_database +from langflow.services.factory import ServiceFactory from langflow.services.manager import service_manager from langflow.services.schema import ServiceType -from langflow.services.settings.constants import ( - DEFAULT_SUPERUSER, - DEFAULT_SUPERUSER_PASSWORD, -) +from langflow.services.settings.constants import DEFAULT_SUPERUSER, DEFAULT_SUPERUSER_PASSWORD +from langflow.services.socket.utils import set_socketio_server from .deps import get_db_service, get_session, get_settings_service -def get_factories_and_deps(): - from langflow.services.auth import factory as auth_factory - from langflow.services.cache import factory as cache_factory - from langflow.services.chat import factory as chat_factory - from langflow.services.credentials import factory as credentials_factory - from langflow.services.database import factory as database_factory - from langflow.services.plugins import factory as plugins_factory - from langflow.services.session import ( - factory as session_service_factory, - ) # type: ignore - from langflow.services.settings import factory as settings_factory - from langflow.services.store import factory as store_factory - from langflow.services.task import factory as task_factory +def get_factories(): + service_names = [ServiceType(service_type).value.replace("_service", "") for service_type in ServiceType] + base_module = "langflow.services" + factories = [] - return [ - (settings_factory.SettingsServiceFactory(), []), - ( - auth_factory.AuthServiceFactory(), - [ServiceType.SETTINGS_SERVICE], - ), - ( - database_factory.DatabaseServiceFactory(), - [ServiceType.SETTINGS_SERVICE], - ), - ( - cache_factory.CacheServiceFactory(), - [ServiceType.SETTINGS_SERVICE], - ), - (chat_factory.ChatServiceFactory(), []), - (task_factory.TaskServiceFactory(), []), - ( - session_service_factory.SessionServiceFactory(), - [ServiceType.CACHE_SERVICE], - ), - (plugins_factory.PluginServiceFactory(), [ServiceType.SETTINGS_SERVICE]), - (store_factory.StoreServiceFactory(), [ServiceType.SETTINGS_SERVICE]), - ( - credentials_factory.CredentialServiceFactory(), - [ServiceType.SETTINGS_SERVICE], - ), - ] + for name in service_names: + try: + module_name = f"{base_module}.{name}.factory" + module = importlib.import_module(module_name) + + # Find all classes in the module that are subclasses of ServiceFactory + for name, obj in inspect.getmembers(module, inspect.isclass): + if issubclass(obj, ServiceFactory) and obj is not ServiceFactory: + factories.append(obj()) + break + + except Exception as exc: + logger.exception(exc) + raise RuntimeError(f"Could not initialize services. Please check your settings. Error in {name}.") from exc + + return factories def get_or_create_super_user(session: Session, username, password, is_default): @@ -182,30 +164,29 @@ def initialize_session_service(): Initialize the session manager. """ from langflow.services.cache import factory as cache_factory - from langflow.services.session import ( - factory as session_service_factory, - ) # type: ignore + from langflow.services.session import factory as session_service_factory # type: ignore initialize_settings_service() - service_manager.register_factory(cache_factory.CacheServiceFactory(), dependencies=[ServiceType.SETTINGS_SERVICE]) + service_manager.register_factory( + cache_factory.CacheServiceFactory(), + ) service_manager.register_factory( session_service_factory.SessionServiceFactory(), - dependencies=[ServiceType.CACHE_SERVICE], ) -def initialize_services(fix_migration: bool = False): +def initialize_services(fix_migration: bool = False, socketio_server=None): """ Initialize all the services needed. """ - for factory, dependencies in get_factories_and_deps(): + for factory in get_factories(): try: - service_manager.register_factory(factory, dependencies=dependencies) + service_manager.register_factory(factory) except Exception as exc: logger.exception(exc) - raise RuntimeError("Could not initialize services. Please check your settings.") from exc + logger.error(f"Error initializing {factory}: {exc}") # Test cache connection service_manager.get(ServiceType.CACHE_SERVICE) @@ -221,3 +202,6 @@ def initialize_services(fix_migration: bool = False): except Exception as exc: logger.error(f"Error migrating flows: {exc}") raise RuntimeError("Error migrating flows") from exc + + # Initialize the SocketIO service + set_socketio_server(socketio_server) diff --git a/src/backend/base/langflow/services/variable/__init__.py b/src/backend/base/langflow/services/variable/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backend/langflow/services/credentials/factory.py b/src/backend/base/langflow/services/variable/factory.py similarity index 55% rename from src/backend/langflow/services/credentials/factory.py rename to src/backend/base/langflow/services/variable/factory.py index c44a43da4..aac384807 100644 --- a/src/backend/langflow/services/credentials/factory.py +++ b/src/backend/base/langflow/services/variable/factory.py @@ -1,15 +1,15 @@ from typing import TYPE_CHECKING -from langflow.services.credentials.service import CredentialService from langflow.services.factory import ServiceFactory +from langflow.services.variable.service import VariableService if TYPE_CHECKING: from langflow.services.settings.service import SettingsService -class CredentialServiceFactory(ServiceFactory): +class VariableServiceFactory(ServiceFactory): def __init__(self): - super().__init__(CredentialService) + super().__init__(VariableService) def create(self, settings_service: "SettingsService"): - return CredentialService(settings_service) + return VariableService(settings_service) diff --git a/src/backend/base/langflow/services/variable/service.py b/src/backend/base/langflow/services/variable/service.py new file mode 100644 index 000000000..23d1cd806 --- /dev/null +++ b/src/backend/base/langflow/services/variable/service.py @@ -0,0 +1,66 @@ +from typing import TYPE_CHECKING, Optional, Union +from uuid import UUID + +from fastapi import Depends +from sqlmodel import Session, select + +from langflow.services.auth import utils as auth_utils +from langflow.services.base import Service +from langflow.services.database.models.variable.model import Variable +from langflow.services.deps import get_session + +if TYPE_CHECKING: + from langflow.services.settings.service import SettingsService + + +class VariableService(Service): + name = "variable_service" + + def __init__(self, settings_service: "SettingsService"): + self.settings_service = settings_service + + def get_variable(self, user_id: Union[UUID, str], name: str, session: Session = Depends(get_session)) -> str: + # we get the credential from the database + # credential = session.query(Variable).filter(Variable.user_id == user_id, Variable.name == name).first() + variable = session.exec(select(Variable).where(Variable.user_id == user_id, Variable.name == name)).first() + # we decrypt the value + if not variable or not variable.value: + raise ValueError(f"{name} variable not found.") + decrypted = auth_utils.decrypt_api_key(variable.value, settings_service=self.settings_service) + return decrypted + + def list_variables(self, user_id: Union[UUID, str], session: Session = Depends(get_session)) -> list[Optional[str]]: + variables = session.exec(select(Variable).where(Variable.user_id == user_id)).all() + return [variable.name for variable in variables] + + def update_variable( + self, user_id: Union[UUID, str], name: str, value: str, session: Session = Depends(get_session) + ): + variable = session.exec(select(Variable).where(Variable.user_id == user_id, Variable.name == name)).first() + if not variable: + raise ValueError(f"{name} variable not found.") + encrypted = auth_utils.encrypt_api_key(value, settings_service=self.settings_service) + variable.value = encrypted + session.add(variable) + session.commit() + session.refresh(variable) + return variable + + def delete_variable(self, user_id: Union[UUID, str], name: str, session: Session = Depends(get_session)): + variable = session.exec(select(Variable).where(Variable.user_id == user_id, Variable.name == name)).first() + if not variable: + raise ValueError(f"{name} variable not found.") + session.delete(variable) + session.commit() + return variable + + def create_variable( + self, user_id: Union[UUID, str], name: str, value: str, session: Session = Depends(get_session) + ): + variable = Variable( + user_id=user_id, name=name, value=auth_utils.encrypt_api_key(value, settings_service=self.settings_service) + ) + session.add(variable) + session.commit() + session.refresh(variable) + return variable diff --git a/src/backend/langflow/settings.py b/src/backend/base/langflow/settings.py similarity index 100% rename from src/backend/langflow/settings.py rename to src/backend/base/langflow/settings.py diff --git a/src/backend/base/langflow/template/__init__.py b/src/backend/base/langflow/template/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backend/base/langflow/template/field/__init__.py b/src/backend/base/langflow/template/field/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backend/langflow/template/field/base.py b/src/backend/base/langflow/template/field/base.py similarity index 64% rename from src/backend/langflow/template/field/base.py rename to src/backend/base/langflow/template/field/base.py index 798d07b55..c68a5c476 100644 --- a/src/backend/langflow/template/field/base.py +++ b/src/backend/base/langflow/template/field/base.py @@ -1,11 +1,13 @@ from typing import Any, Callable, Optional, Union +from pydantic import BaseModel, ConfigDict, Field, field_serializer, field_validator, model_serializer, model_validator + from langflow.field_typing.range_spec import RangeSpec -from pydantic import BaseModel, ConfigDict, Field, field_serializer class TemplateField(BaseModel): model_config = ConfigDict() + field_type: str = Field(default="str", serialization_alias="type") """The type of field this is. Default is a string.""" @@ -28,7 +30,7 @@ class TemplateField(BaseModel): """The value of the field. Default is None.""" file_types: list[str] = Field(default=[], serialization_alias="fileTypes") - """List of file types associated with the field. Default is an empty list. (duplicate)""" + """List of file types associated with the field . Default is an empty list.""" file_path: Optional[str] = "" """The file path of the field if it is a file. Defaults to None.""" @@ -57,18 +59,45 @@ class TemplateField(BaseModel): info: Optional[str] = "" """Additional information about the field to be shown in the tooltip. Defaults to an empty string.""" - refresh: Optional[bool] = None - """Specifies if the field should be refreshed. Defaults to False.""" + real_time_refresh: Optional[bool] = None + """Specifies if the field should have real time refresh. `refresh_button` must be False. Defaults to None.""" + + refresh_button: Optional[bool] = None + """Specifies if the field should have a refresh button. Defaults to False.""" + refresh_button_text: Optional[str] = None + """Specifies the text for the refresh button. Defaults to None.""" range_spec: Optional[RangeSpec] = Field(default=None, serialization_alias="rangeSpec") """Range specification for the field. Defaults to None.""" - title_case: bool = True + load_from_db: bool = False + """Specifies if the field should be loaded from the database. Defaults to False.""" + title_case: bool = False """Specifies if the field should be displayed in title case. Defaults to True.""" def to_dict(self): return self.model_dump(by_alias=True, exclude_none=True) + @model_serializer(mode="wrap") + def serialize_model(self, handler): + result = handler(self) + # If the field is str, we add the Text input type + if self.field_type in ["str", "Text"]: + if "input_types" not in result: + result["input_types"] = ["Text"] + if self.field_type == "Text": + result["type"] = "str" + else: + result["type"] = self.field_type + return result + + @model_validator(mode="after") + def validate_model(self): + # if field_type is int, we need to set the range_spec + if self.field_type == "int" and self.range_spec is not None: + self.range_spec = RangeSpec.set_step_type("int", self.range_spec) + return self + @field_serializer("file_path") def serialize_file_path(self, value): return value if self.field_type == "file" else "" @@ -90,3 +119,12 @@ class TemplateField(BaseModel): if self.title_case: value = value.title() return value + + @field_validator("file_types") + def validate_file_types(cls, value): + if not isinstance(value, list): + raise ValueError("file_types must be a list") + return [ + (f".{file_type}" if isinstance(file_type, str) and not file_type.startswith(".") else file_type) + for file_type in value + ] diff --git a/src/backend/base/langflow/template/field/prompt.py b/src/backend/base/langflow/template/field/prompt.py new file mode 100644 index 000000000..72c57c5db --- /dev/null +++ b/src/backend/base/langflow/template/field/prompt.py @@ -0,0 +1,14 @@ +from typing import Optional + +from langflow.template.field.base import TemplateField + + +class DefaultPromptField(TemplateField): + name: str + display_name: Optional[str] = None + field_type: str = "str" + + advanced: bool = False + multiline: bool = True + input_types: list[str] = ["Document", "BaseOutputParser", "Record", "Text"] + value: str = "" # Set the value to empty string diff --git a/src/backend/langflow/template/frontend_node/__init__.py b/src/backend/base/langflow/template/frontend_node/__init__.py similarity index 95% rename from src/backend/langflow/template/frontend_node/__init__.py rename to src/backend/base/langflow/template/frontend_node/__init__.py index e13aa1ded..ceb2e0cb9 100644 --- a/src/backend/langflow/template/frontend_node/__init__.py +++ b/src/backend/base/langflow/template/frontend_node/__init__.py @@ -1,19 +1,21 @@ from langflow.template.frontend_node import ( agents, chains, + custom_components, + documentloaders, embeddings, llms, memories, prompts, + textsplitters, tools, vectorstores, - documentloaders, - textsplitters, - custom_components, + base, ) __all__ = [ "agents", + "base", "chains", "embeddings", "memories", diff --git a/src/backend/langflow/template/frontend_node/agents.py b/src/backend/base/langflow/template/frontend_node/agents.py similarity index 99% rename from src/backend/langflow/template/frontend_node/agents.py rename to src/backend/base/langflow/template/frontend_node/agents.py index 361abf531..0993c1736 100644 --- a/src/backend/langflow/template/frontend_node/agents.py +++ b/src/backend/base/langflow/template/frontend_node/agents.py @@ -1,6 +1,8 @@ from typing import Optional from langchain.agents import types + + from langflow.template.field.base import TemplateField from langflow.template.frontend_node.base import FrontendNode from langflow.template.template.base import Template diff --git a/src/backend/langflow/template/frontend_node/base.py b/src/backend/base/langflow/template/frontend_node/base.py similarity index 88% rename from src/backend/langflow/template/frontend_node/base.py rename to src/backend/base/langflow/template/frontend_node/base.py index daef4f9a8..8a051058e 100644 --- a/src/backend/langflow/template/frontend_node/base.py +++ b/src/backend/base/langflow/template/frontend_node/base.py @@ -2,12 +2,13 @@ import re from collections import defaultdict from typing import ClassVar, Dict, List, Optional, Union +from pydantic import BaseModel, Field, field_serializer, model_serializer + from langflow.template.field.base import TemplateField -from langflow.template.frontend_node.constants import CLASSES_TO_REMOVE, FORCE_SHOW_FIELDS +from langflow.template.frontend_node.constants import FORCE_SHOW_FIELDS from langflow.template.frontend_node.formatter import field_formatters from langflow.template.template.base import Template from langflow.utils import constants -from pydantic import BaseModel, Field, field_serializer, model_serializer class FieldFormatters(BaseModel): @@ -41,16 +42,40 @@ class FieldFormatters(BaseModel): class FrontendNode(BaseModel): _format_template: bool = True template: Template + """Template for the frontend node.""" description: Optional[str] = None + """Description of the frontend node.""" icon: Optional[str] = None + """Icon of the frontend node.""" + is_input: Optional[bool] = None + """Whether the frontend node is used as an input when processing the Graph. + If True, there should be a field named 'input_value'.""" + is_output: Optional[bool] = None + """Whether the frontend node is used as an output when processing the Graph. + If True, there should be a field named 'input_value'.""" + is_composition: Optional[bool] = None + """Whether the frontend node is used for composition.""" base_classes: List[str] + """List of base classes for the frontend node.""" name: str = "" + """Name of the frontend node.""" display_name: Optional[str] = "" + """Display name of the frontend node.""" documentation: str = "" + """Documentation of the frontend node.""" custom_fields: Optional[Dict] = defaultdict(list) + """Custom fields of the frontend node.""" output_types: List[str] = [] + """List of output types for the frontend node.""" full_path: Optional[str] = None + """Full path of the frontend node.""" field_formatters: FieldFormatters = Field(default_factory=FieldFormatters) + """Field formatters for the frontend node.""" + frozen: bool = False + """Whether the frontend node is frozen.""" + + field_order: list[str] = [] + """Order of the fields in the frontend node.""" beta: bool = False error: Optional[str] = None @@ -69,7 +94,8 @@ class FrontendNode(BaseModel): def process_base_classes(self, base_classes: List[str]) -> List[str]: """Removes unwanted base classes from the list of base classes.""" - return [base_class for base_class in base_classes if base_class not in CLASSES_TO_REMOVE] + sorted_base_classes = sorted(list(set(base_classes)), key=lambda x: x.lower()) + return sorted_base_classes @field_serializer("display_name") def process_display_name(self, display_name: str) -> str: diff --git a/src/backend/langflow/template/frontend_node/chains.py b/src/backend/base/langflow/template/frontend_node/chains.py similarity index 90% rename from src/backend/langflow/template/frontend_node/chains.py rename to src/backend/base/langflow/template/frontend_node/chains.py index 5ff211f68..4ce23a316 100644 --- a/src/backend/langflow/template/frontend_node/chains.py +++ b/src/backend/base/langflow/template/frontend_node/chains.py @@ -7,6 +7,11 @@ from langflow.template.template.base import Template class ChainFrontendNode(FrontendNode): + output_type: str = "Chain" + + def add_extra_base_classes(self) -> None: + self.base_classes.append("Text") + def add_extra_fields(self) -> None: if self.template.type_name == "ConversationalRetrievalChain": # add memory @@ -48,16 +53,16 @@ class ChainFrontendNode(FrontendNode): @staticmethod def format_field(field: TemplateField, name: Optional[str] = None) -> None: FrontendNode.format_field(field, name) - key = field.name or "" - if "name" == "RetrievalQA" and key == "memory": + + if "name" == "RetrievalQA" and field.name == "memory": field.show = False field.required = False field.advanced = False - if "key" in key: + if "key" in str(field.name): field.password = False field.show = False - if key in ["input_key", "output_key"]: + if field.name in ["input_key", "output_key"]: field.required = True field.show = True field.advanced = True @@ -71,26 +76,26 @@ class ChainFrontendNode(FrontendNode): # field.value = field.value.template # Separated for possible future changes - if key == "prompt" and field.value is None: + if field.name == "prompt" and field.value is None: field.required = True field.show = True field.advanced = False - if key == "memory": + if field.name == "memory": # field.required = False field.show = True field.advanced = False - if key == "verbose": + if field.name == "verbose": field.required = False field.show = False field.advanced = True - if key == "llm": + if field.name == "llm": field.required = True field.show = True field.advanced = False - field.field_type = "BaseLanguageModel" # temporary fix + field.field_type = "BaseLanguageModel" field.is_list = False - if key == "return_source_documents": + if field.name == "return_source_documents": field.required = False field.show = True field.advanced = True @@ -98,6 +103,7 @@ class ChainFrontendNode(FrontendNode): class SeriesCharacterChainNode(FrontendNode): + output_type: str = "Chain" name: str = "SeriesCharacterChain" template: Template = Template( type_name="SeriesCharacterChain", @@ -144,11 +150,12 @@ class SeriesCharacterChainNode(FrontendNode): "Chain", "ConversationChain", "SeriesCharacterChain", - "Callable", + "function", ] class TimeTravelGuideChainNode(FrontendNode): + output_type: str = "Chain" name: str = "TimeTravelGuideChain" template: Template = Template( type_name="TimeTravelGuideChain", @@ -184,6 +191,7 @@ class TimeTravelGuideChainNode(FrontendNode): class MidJourneyPromptChainNode(FrontendNode): + output_type: str = "Chain" name: str = "MidJourneyPromptChain" template: Template = Template( type_name="MidJourneyPromptChain", @@ -219,6 +227,7 @@ class MidJourneyPromptChainNode(FrontendNode): class CombineDocsChainNode(FrontendNode): + output_type: str = "Chain" name: str = "CombineDocsChain" template: Template = Template( type_name="load_qa_chain", @@ -245,7 +254,10 @@ class CombineDocsChainNode(FrontendNode): ], ) description: str = """Load question answering chain.""" - base_classes: list[str] = ["BaseCombineDocumentsChain", "Callable"] + base_classes: list[str] = ["BaseCombineDocumentsChain", "function"] + + def to_dict(self): + return super().to_dict() @staticmethod def format_field(field: TemplateField, name: Optional[str] = None) -> None: diff --git a/src/backend/langflow/template/frontend_node/constants.py b/src/backend/base/langflow/template/frontend_node/constants.py similarity index 92% rename from src/backend/langflow/template/frontend_node/constants.py rename to src/backend/base/langflow/template/frontend_node/constants.py index a213a2744..513ccd1ef 100644 --- a/src/backend/langflow/template/frontend_node/constants.py +++ b/src/backend/base/langflow/template/frontend_node/constants.py @@ -63,13 +63,3 @@ You can change this to use other APIs like JinaChat, LocalAI and Prem. INPUT_KEY_INFO = """The variable to be used as Chat Input when more than one variable is available.""" OUTPUT_KEY_INFO = """The variable to be used as Chat Output (e.g. answer in a ConversationalRetrievalChain)""" - - -CLASSES_TO_REMOVE = [ - "RunnableSerializable", - "Serializable", - "BaseModel", - "object", - "Runnable", - "Generic", -] diff --git a/src/backend/langflow/template/frontend_node/custom_components.py b/src/backend/base/langflow/template/frontend_node/custom_components.py similarity index 92% rename from src/backend/langflow/template/frontend_node/custom_components.py rename to src/backend/base/langflow/template/frontend_node/custom_components.py index d604ae055..456aa7466 100644 --- a/src/backend/langflow/template/frontend_node/custom_components.py +++ b/src/backend/base/langflow/template/frontend_node/custom_components.py @@ -4,7 +4,8 @@ from langflow.template.field.base import TemplateField from langflow.template.frontend_node.base import FrontendNode from langflow.template.template.base import Template -DEFAULT_CUSTOM_COMPONENT_CODE = """from langflow import CustomComponent +DEFAULT_CUSTOM_COMPONENT_CODE = """from langflow.interface.custom.custom_component import CustomComponent + from typing import Optional, List, Dict, Union from langflow.field_typing import ( AgentExecutor, @@ -48,7 +49,7 @@ class CustomComponentFrontendNode(FrontendNode): _format_template: bool = False name: str = "CustomComponent" display_name: Optional[str] = "CustomComponent" - beta: bool = True + beta: bool = False template: Template = Template( type_name="CustomComponent", fields=[ diff --git a/src/backend/langflow/template/frontend_node/documentloaders.py b/src/backend/base/langflow/template/frontend_node/documentloaders.py similarity index 100% rename from src/backend/langflow/template/frontend_node/documentloaders.py rename to src/backend/base/langflow/template/frontend_node/documentloaders.py diff --git a/src/backend/langflow/template/frontend_node/embeddings.py b/src/backend/base/langflow/template/frontend_node/embeddings.py similarity index 100% rename from src/backend/langflow/template/frontend_node/embeddings.py rename to src/backend/base/langflow/template/frontend_node/embeddings.py diff --git a/src/backend/base/langflow/template/frontend_node/formatter/__init__.py b/src/backend/base/langflow/template/frontend_node/formatter/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backend/langflow/template/frontend_node/formatter/base.py b/src/backend/base/langflow/template/frontend_node/formatter/base.py similarity index 99% rename from src/backend/langflow/template/frontend_node/formatter/base.py rename to src/backend/base/langflow/template/frontend_node/formatter/base.py index f582bc298..20ba64eae 100644 --- a/src/backend/langflow/template/frontend_node/formatter/base.py +++ b/src/backend/base/langflow/template/frontend_node/formatter/base.py @@ -1,9 +1,10 @@ from abc import ABC, abstractmethod from typing import Optional -from langflow.template.field.base import TemplateField from pydantic import BaseModel +from langflow.template.field.base import TemplateField + class FieldFormatter(BaseModel, ABC): @abstractmethod diff --git a/src/backend/langflow/template/frontend_node/formatter/field_formatters.py b/src/backend/base/langflow/template/frontend_node/formatter/field_formatters.py similarity index 100% rename from src/backend/langflow/template/frontend_node/formatter/field_formatters.py rename to src/backend/base/langflow/template/frontend_node/formatter/field_formatters.py diff --git a/src/backend/langflow/template/frontend_node/llms.py b/src/backend/base/langflow/template/frontend_node/llms.py similarity index 100% rename from src/backend/langflow/template/frontend_node/llms.py rename to src/backend/base/langflow/template/frontend_node/llms.py diff --git a/src/backend/langflow/template/frontend_node/memories.py b/src/backend/base/langflow/template/frontend_node/memories.py similarity index 97% rename from src/backend/langflow/template/frontend_node/memories.py rename to src/backend/base/langflow/template/frontend_node/memories.py index fc9df6291..1cdc8febb 100644 --- a/src/backend/langflow/template/frontend_node/memories.py +++ b/src/backend/base/langflow/template/frontend_node/memories.py @@ -1,9 +1,6 @@ from typing import Optional -from langchain_community.chat_message_histories.mongodb import ( - DEFAULT_COLLECTION_NAME, - DEFAULT_DBNAME, -) +from langchain_community.chat_message_histories.mongodb import DEFAULT_COLLECTION_NAME, DEFAULT_DBNAME from langchain_community.chat_message_histories.postgres import DEFAULT_CONNECTION_STRING from langflow.template.field.base import TemplateField @@ -13,7 +10,8 @@ from langflow.template.template.base import Template class MemoryFrontendNode(FrontendNode): - #! Needs testing + frozen: bool = True + def add_extra_fields(self) -> None: # chat history should have another way to add common field? # prevent adding incorect field in ChatMessageHistory diff --git a/src/backend/langflow/template/frontend_node/output_parsers.py b/src/backend/base/langflow/template/frontend_node/output_parsers.py similarity index 99% rename from src/backend/langflow/template/frontend_node/output_parsers.py rename to src/backend/base/langflow/template/frontend_node/output_parsers.py index e9b4d3706..6b33ee680 100644 --- a/src/backend/langflow/template/frontend_node/output_parsers.py +++ b/src/backend/base/langflow/template/frontend_node/output_parsers.py @@ -1,4 +1,6 @@ from typing import Optional + + from langflow.template.field.base import TemplateField from langflow.template.frontend_node.base import FrontendNode diff --git a/src/backend/langflow/template/frontend_node/prompts.py b/src/backend/base/langflow/template/frontend_node/prompts.py similarity index 100% rename from src/backend/langflow/template/frontend_node/prompts.py rename to src/backend/base/langflow/template/frontend_node/prompts.py diff --git a/src/backend/langflow/template/frontend_node/retrievers.py b/src/backend/base/langflow/template/frontend_node/retrievers.py similarity index 100% rename from src/backend/langflow/template/frontend_node/retrievers.py rename to src/backend/base/langflow/template/frontend_node/retrievers.py diff --git a/src/backend/langflow/template/frontend_node/textsplitters.py b/src/backend/base/langflow/template/frontend_node/textsplitters.py similarity index 99% rename from src/backend/langflow/template/frontend_node/textsplitters.py rename to src/backend/base/langflow/template/frontend_node/textsplitters.py index e6d5bdc60..eb302e996 100644 --- a/src/backend/langflow/template/frontend_node/textsplitters.py +++ b/src/backend/base/langflow/template/frontend_node/textsplitters.py @@ -1,6 +1,7 @@ +from langchain.text_splitter import Language + from langflow.template.field.base import TemplateField from langflow.template.frontend_node.base import FrontendNode -from langchain.text_splitter import Language class TextSplittersFrontendNode(FrontendNode): diff --git a/src/backend/langflow/template/frontend_node/tools.py b/src/backend/base/langflow/template/frontend_node/tools.py similarity index 100% rename from src/backend/langflow/template/frontend_node/tools.py rename to src/backend/base/langflow/template/frontend_node/tools.py diff --git a/src/backend/langflow/template/frontend_node/utilities.py b/src/backend/base/langflow/template/frontend_node/utilities.py similarity index 100% rename from src/backend/langflow/template/frontend_node/utilities.py rename to src/backend/base/langflow/template/frontend_node/utilities.py index a5adb219d..51849189c 100644 --- a/src/backend/langflow/template/frontend_node/utilities.py +++ b/src/backend/base/langflow/template/frontend_node/utilities.py @@ -1,7 +1,7 @@ import ast from typing import Optional -from langflow.services.database.models.base import orjson_dumps +from langflow.services.database.models.base import orjson_dumps from langflow.template.field.base import TemplateField from langflow.template.frontend_node.base import FrontendNode diff --git a/src/backend/langflow/template/frontend_node/vectorstores.py b/src/backend/base/langflow/template/frontend_node/vectorstores.py similarity index 100% rename from src/backend/langflow/template/frontend_node/vectorstores.py rename to src/backend/base/langflow/template/frontend_node/vectorstores.py diff --git a/src/backend/base/langflow/template/template/__init__.py b/src/backend/base/langflow/template/template/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backend/langflow/template/template/base.py b/src/backend/base/langflow/template/template/base.py similarity index 97% rename from src/backend/langflow/template/template/base.py rename to src/backend/base/langflow/template/template/base.py index 9bc375b0f..d7632e239 100644 --- a/src/backend/langflow/template/template/base.py +++ b/src/backend/base/langflow/template/template/base.py @@ -1,14 +1,14 @@ from typing import Callable, Union +from pydantic import BaseModel, model_serializer + from langflow.template.field.base import TemplateField from langflow.utils.constants import DIRECT_TYPES -from pydantic import BaseModel, model_serializer class Template(BaseModel): type_name: str fields: list[TemplateField] - field_order: list[str] = [] def process_fields( self, @@ -30,7 +30,6 @@ class Template(BaseModel): for field in self.fields: result[field.name] = field.model_dump(by_alias=True, exclude_none=True) result["_type"] = result.pop("type_name") - result.pop("field_order", None) return result # For backwards compatibility diff --git a/src/backend/base/langflow/utils/__init__.py b/src/backend/base/langflow/utils/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backend/langflow/utils/constants.py b/src/backend/base/langflow/utils/constants.py similarity index 98% rename from src/backend/langflow/utils/constants.py rename to src/backend/base/langflow/utils/constants.py index 9b01f8c2d..ac0a03fdf 100644 --- a/src/backend/langflow/utils/constants.py +++ b/src/backend/base/langflow/utils/constants.py @@ -158,8 +158,8 @@ LOADERS_INFO: List[Dict[str, Any]] = [ "loader": "UnstructuredMarkdownLoader", "name": "Unstructured Markdown (.md)", "import": "langchain_community.document_loaders.UnstructuredMarkdownLoader", - "defaultFor": ["md"], - "allowdTypes": ["md"], + "defaultFor": ["md", "mdx"], + "allowdTypes": ["md", "mdx"], }, { "loader": "UnstructuredPowerPointLoader", diff --git a/src/backend/langflow/utils/lazy_load.py b/src/backend/base/langflow/utils/lazy_load.py similarity index 100% rename from src/backend/langflow/utils/lazy_load.py rename to src/backend/base/langflow/utils/lazy_load.py diff --git a/src/backend/langflow/utils/logger.py b/src/backend/base/langflow/utils/logger.py similarity index 93% rename from src/backend/langflow/utils/logger.py rename to src/backend/base/langflow/utils/logger.py index 060ad9731..d92bdb0e1 100644 --- a/src/backend/langflow/utils/logger.py +++ b/src/backend/base/langflow/utils/logger.py @@ -25,10 +25,10 @@ def patching(record): def configure(log_level: Optional[str] = None, log_file: Optional[Path] = None): - if os.getenv("LANGFLOW_LOG_LEVEL") in VALID_LOG_LEVELS and log_level is None: + if os.getenv("LANGFLOW_LOG_LEVEL", "").upper() in VALID_LOG_LEVELS and log_level is None: log_level = os.getenv("LANGFLOW_LOG_LEVEL") if log_level is None: - log_level = "INFO" + log_level = "ERROR" # Human-readable log_format = ( "{time:YYYY-MM-DD HH:mm:ss} - " diff --git a/src/backend/langflow/utils/payload.py b/src/backend/base/langflow/utils/payload.py similarity index 100% rename from src/backend/langflow/utils/payload.py rename to src/backend/base/langflow/utils/payload.py diff --git a/src/backend/base/langflow/utils/schemas.py b/src/backend/base/langflow/utils/schemas.py new file mode 100644 index 000000000..3e6f17a5a --- /dev/null +++ b/src/backend/base/langflow/utils/schemas.py @@ -0,0 +1,55 @@ +import enum +from typing import Dict, List, Optional, Union + +from langchain_core.messages import BaseMessage +from pydantic import BaseModel, model_validator + + +class ChatOutputResponse(BaseModel): + """Chat output response schema.""" + + message: Union[str, List[Union[str, Dict]]] + sender: Optional[str] = "Machine" + sender_name: Optional[str] = "AI" + session_id: Optional[str] = None + stream_url: Optional[str] = None + component_id: Optional[str] = None + + @classmethod + def from_message( + cls, + message: BaseMessage, + sender: Optional[str] = "Machine", + sender_name: Optional[str] = "AI", + ): + """Build chat output response from message.""" + content = message.content + return cls(message=content, sender=sender, sender_name=sender_name) + + @model_validator(mode="after") + def validate_message(self): + """Validate message.""" + # The idea here is ensure the \n in message + # is compliant with markdown if sender is machine + # so, for example: + # \n\n -> \n\n + # \n -> \n\n + + if self.sender != "Machine": + return self + + # We need to make sure we don't duplicate \n + # in the message + message = self.message.replace("\n\n", "\n") + self.message = message.replace("\n", "\n\n") + return self + + +class ContainsEnumMeta(enum.EnumMeta): + def __contains__(cls, item): + try: + cls(item) + except ValueError: + return False + else: + return True diff --git a/src/backend/langflow/utils/util.py b/src/backend/base/langflow/utils/util.py similarity index 92% rename from src/backend/langflow/utils/util.py rename to src/backend/base/langflow/utils/util.py index 7e1206222..4ec2c526c 100644 --- a/src/backend/langflow/utils/util.py +++ b/src/backend/base/langflow/utils/util.py @@ -5,12 +5,17 @@ from functools import wraps from typing import Any, Dict, List, Optional, Union from docstring_parser import parse -from langchain_core.documents import Document +from langflow.schema.schema import Record from langflow.template.frontend_node.constants import FORCE_SHOW_FIELDS from langflow.utils import constants +def unescape_string(s: str): + # Replace escaped new line characters with actual new line characters + return s.replace("\\n", "\n") + + def remove_ansi_escape_codes(text): return re.sub(r"\x1b\[[0-9;]*[a-zA-Z]", "", text) @@ -86,7 +91,8 @@ def build_template_from_class(name: str, type_to_cls_dict: Dict, add_function: b if name_ == "default_factory": try: variables[class_field_items]["default"] = get_default_factory( - module=_class.__base__.__module__, function=value_ + module=_class.__base__.__module__, + function=value_, ) except Exception: variables[class_field_items]["default"] = None @@ -145,8 +151,8 @@ def build_template_from_method( "_type": _type, **{ name: { - "default": param.default if param.default != param.empty else None, - "type": param.annotation if param.annotation != param.empty else None, + "default": (param.default if param.default != param.empty else None), + "type": (param.annotation if param.annotation != param.empty else None), "required": param.default == param.empty, } for name, param in params.items() @@ -243,7 +249,7 @@ def format_dict(dictionary: Dict[str, Any], class_name: Optional[str] = None) -> """ for key, value in dictionary.items(): - if key == "_type": + if key in ["_type"]: continue _type: Union[str, type] = get_type(value) @@ -439,10 +445,20 @@ def add_options_to_field(value: Dict[str, Any], class_name: Optional[str], key: value["value"] = options_map[class_name][0] -def build_loader_repr_from_documents(documents: List[Document]) -> str: - if documents: - avg_length = sum(len(doc.page_content) for doc in documents) / len(documents) - return f"""{len(documents)} documents - \nAvg. Document Length (characters): {int(avg_length)} - Documents: {documents[:3]}...""" - return "0 documents" +def build_loader_repr_from_records(records: List[Record]) -> str: + """ + Builds a string representation of the loader based on the given records. + + Args: + records (List[Record]): A list of records. + + Returns: + str: A string representation of the loader. + + """ + if records: + avg_length = sum(len(doc.text) for doc in records) / len(records) + return f"""{len(records)} records + \nAvg. Record Length (characters): {int(avg_length)} + Records: {records[:3]}...""" + return "0 records" diff --git a/src/backend/langflow/utils/validate.py b/src/backend/base/langflow/utils/validate.py similarity index 97% rename from src/backend/langflow/utils/validate.py rename to src/backend/base/langflow/utils/validate.py index 6e6226568..0871dbd82 100644 --- a/src/backend/langflow/utils/validate.py +++ b/src/backend/base/langflow/utils/validate.py @@ -157,6 +157,9 @@ def create_class(code, class_name): if not hasattr(ast, "TypeIgnore"): ast.TypeIgnore = create_type_ignore_class() + # Replace from langflow import CustomComponent with from langflow.custom import CustomComponent + code = code.replace("from langflow import CustomComponent", "from langflow.custom import CustomComponent") + module = ast.parse(code) exec_globals = prepare_global_scope(code, module) @@ -200,8 +203,8 @@ def prepare_global_scope(code, module): imported_module = importlib.import_module(node.module) for alias in node.names: exec_globals[alias.name] = getattr(imported_module, alias.name) - except ModuleNotFoundError as e: - raise ModuleNotFoundError(f"Module {node.module} not found. Please install it and try again.") from e + except ModuleNotFoundError: + raise ModuleNotFoundError(f"Module {node.module} not found. Please install it and try again") return exec_globals diff --git a/src/backend/base/langflow/worker.py b/src/backend/base/langflow/worker.py new file mode 100644 index 000000000..a5d1cf956 --- /dev/null +++ b/src/backend/base/langflow/worker.py @@ -0,0 +1,37 @@ +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union + +from asgiref.sync import async_to_sync +from celery.exceptions import SoftTimeLimitExceeded # type: ignore + +from langflow.core.celery_app import celery_app + +if TYPE_CHECKING: + from langflow.graph.vertex.base import Vertex + + +@celery_app.task(acks_late=True) +def test_celery(word: str) -> str: + return f"test task return {word}" + + +@celery_app.task(bind=True, soft_time_limit=30, max_retries=3) +def build_vertex(self, vertex: "Vertex") -> "Vertex": + """ + Build a vertex + """ + try: + vertex.task_id = self.request.id + async_to_sync(vertex.build)() + return vertex + except SoftTimeLimitExceeded as e: + raise self.retry(exc=SoftTimeLimitExceeded("Task took too long"), countdown=2) from e + + +@celery_app.task(acks_late=True) +def process_graph_cached_task( + data_graph: Dict[str, Any], + inputs: Optional[Union[dict, List[dict]]] = None, + clear_cache=False, + session_id=None, +) -> Dict[str, Any]: + raise NotImplementedError("This task is not implemented yet") diff --git a/src/backend/base/poetry.lock b/src/backend/base/poetry.lock new file mode 100644 index 000000000..a0d213615 --- /dev/null +++ b/src/backend/base/poetry.lock @@ -0,0 +1,6271 @@ +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. + +[[package]] +name = "aiohttp" +version = "3.9.3" +description = "Async http client/server framework (asyncio)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:939677b61f9d72a4fa2a042a5eee2a99a24001a67c13da113b2e30396567db54"}, + {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1f5cd333fcf7590a18334c90f8c9147c837a6ec8a178e88d90a9b96ea03194cc"}, + {file = "aiohttp-3.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:82e6aa28dd46374f72093eda8bcd142f7771ee1eb9d1e223ff0fa7177a96b4a5"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f56455b0c2c7cc3b0c584815264461d07b177f903a04481dfc33e08a89f0c26b"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bca77a198bb6e69795ef2f09a5f4c12758487f83f33d63acde5f0d4919815768"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e083c285857b78ee21a96ba1eb1b5339733c3563f72980728ca2b08b53826ca5"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab40e6251c3873d86ea9b30a1ac6d7478c09277b32e14745d0d3c6e76e3c7e29"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df822ee7feaaeffb99c1a9e5e608800bd8eda6e5f18f5cfb0dc7eeb2eaa6bbec"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:acef0899fea7492145d2bbaaaec7b345c87753168589cc7faf0afec9afe9b747"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cd73265a9e5ea618014802ab01babf1940cecb90c9762d8b9e7d2cc1e1969ec6"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a78ed8a53a1221393d9637c01870248a6f4ea5b214a59a92a36f18151739452c"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6b0e029353361f1746bac2e4cc19b32f972ec03f0f943b390c4ab3371840aabf"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7cf5c9458e1e90e3c390c2639f1017a0379a99a94fdfad3a1fd966a2874bba52"}, + {file = "aiohttp-3.9.3-cp310-cp310-win32.whl", hash = "sha256:3e59c23c52765951b69ec45ddbbc9403a8761ee6f57253250c6e1536cacc758b"}, + {file = "aiohttp-3.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:055ce4f74b82551678291473f66dc9fb9048a50d8324278751926ff0ae7715e5"}, + {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6b88f9386ff1ad91ace19d2a1c0225896e28815ee09fc6a8932fded8cda97c3d"}, + {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c46956ed82961e31557b6857a5ca153c67e5476972e5f7190015018760938da2"}, + {file = "aiohttp-3.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:07b837ef0d2f252f96009e9b8435ec1fef68ef8b1461933253d318748ec1acdc"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad46e6f620574b3b4801c68255492e0159d1712271cc99d8bdf35f2043ec266"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ed3e046ea7b14938112ccd53d91c1539af3e6679b222f9469981e3dac7ba1ce"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:039df344b45ae0b34ac885ab5b53940b174530d4dd8a14ed8b0e2155b9dddccb"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7943c414d3a8d9235f5f15c22ace69787c140c80b718dcd57caaade95f7cd93b"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84871a243359bb42c12728f04d181a389718710129b36b6aad0fc4655a7647d4"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5eafe2c065df5401ba06821b9a054d9cb2848867f3c59801b5d07a0be3a380ae"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9d3c9b50f19704552f23b4eaea1fc082fdd82c63429a6506446cbd8737823da3"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:f033d80bc6283092613882dfe40419c6a6a1527e04fc69350e87a9df02bbc283"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:2c895a656dd7e061b2fd6bb77d971cc38f2afc277229ce7dd3552de8313a483e"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1f5a71d25cd8106eab05f8704cd9167b6e5187bcdf8f090a66c6d88b634802b4"}, + {file = "aiohttp-3.9.3-cp311-cp311-win32.whl", hash = "sha256:50fca156d718f8ced687a373f9e140c1bb765ca16e3d6f4fe116e3df7c05b2c5"}, + {file = "aiohttp-3.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:5fe9ce6c09668063b8447f85d43b8d1c4e5d3d7e92c63173e6180b2ac5d46dd8"}, + {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:38a19bc3b686ad55804ae931012f78f7a534cce165d089a2059f658f6c91fa60"}, + {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:770d015888c2a598b377bd2f663adfd947d78c0124cfe7b959e1ef39f5b13869"}, + {file = "aiohttp-3.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee43080e75fc92bf36219926c8e6de497f9b247301bbf88c5c7593d931426679"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52df73f14ed99cee84865b95a3d9e044f226320a87af208f068ecc33e0c35b96"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc9b311743a78043b26ffaeeb9715dc360335e5517832f5a8e339f8a43581e4d"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b955ed993491f1a5da7f92e98d5dad3c1e14dc175f74517c4e610b1f2456fb11"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:504b6981675ace64c28bf4a05a508af5cde526e36492c98916127f5a02354d53"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6fe5571784af92b6bc2fda8d1925cccdf24642d49546d3144948a6a1ed58ca5"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ba39e9c8627edc56544c8628cc180d88605df3892beeb2b94c9bc857774848ca"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e5e46b578c0e9db71d04c4b506a2121c0cb371dd89af17a0586ff6769d4c58c1"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:938a9653e1e0c592053f815f7028e41a3062e902095e5a7dc84617c87267ebd5"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:c3452ea726c76e92f3b9fae4b34a151981a9ec0a4847a627c43d71a15ac32aa6"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ff30218887e62209942f91ac1be902cc80cddb86bf00fbc6783b7a43b2bea26f"}, + {file = "aiohttp-3.9.3-cp312-cp312-win32.whl", hash = "sha256:38f307b41e0bea3294a9a2a87833191e4bcf89bb0365e83a8be3a58b31fb7f38"}, + {file = "aiohttp-3.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:b791a3143681a520c0a17e26ae7465f1b6f99461a28019d1a2f425236e6eedb5"}, + {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0ed621426d961df79aa3b963ac7af0d40392956ffa9be022024cd16297b30c8c"}, + {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7f46acd6a194287b7e41e87957bfe2ad1ad88318d447caf5b090012f2c5bb528"}, + {file = "aiohttp-3.9.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:feeb18a801aacb098220e2c3eea59a512362eb408d4afd0c242044c33ad6d542"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f734e38fd8666f53da904c52a23ce517f1b07722118d750405af7e4123933511"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b40670ec7e2156d8e57f70aec34a7216407848dfe6c693ef131ddf6e76feb672"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdd215b7b7fd4a53994f238d0f46b7ba4ac4c0adb12452beee724ddd0743ae5d"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:017a21b0df49039c8f46ca0971b3a7fdc1f56741ab1240cb90ca408049766168"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e99abf0bba688259a496f966211c49a514e65afa9b3073a1fcee08856e04425b"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:648056db9a9fa565d3fa851880f99f45e3f9a771dd3ff3bb0c048ea83fb28194"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8aacb477dc26797ee089721536a292a664846489c49d3ef9725f992449eda5a8"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:522a11c934ea660ff8953eda090dcd2154d367dec1ae3c540aff9f8a5c109ab4"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:5bce0dc147ca85caa5d33debc4f4d65e8e8b5c97c7f9f660f215fa74fc49a321"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b4af9f25b49a7be47c0972139e59ec0e8285c371049df1a63b6ca81fdd216a2"}, + {file = "aiohttp-3.9.3-cp38-cp38-win32.whl", hash = "sha256:298abd678033b8571995650ccee753d9458dfa0377be4dba91e4491da3f2be63"}, + {file = "aiohttp-3.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:69361bfdca5468c0488d7017b9b1e5ce769d40b46a9f4a2eed26b78619e9396c"}, + {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0fa43c32d1643f518491d9d3a730f85f5bbaedcbd7fbcae27435bb8b7a061b29"}, + {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:835a55b7ca49468aaaac0b217092dfdff370e6c215c9224c52f30daaa735c1c1"}, + {file = "aiohttp-3.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06a9b2c8837d9a94fae16c6223acc14b4dfdff216ab9b7202e07a9a09541168f"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abf151955990d23f84205286938796c55ff11bbfb4ccfada8c9c83ae6b3c89a3"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59c26c95975f26e662ca78fdf543d4eeaef70e533a672b4113dd888bd2423caa"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f95511dd5d0e05fd9728bac4096319f80615aaef4acbecb35a990afebe953b0e"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:595f105710293e76b9dc09f52e0dd896bd064a79346234b521f6b968ffdd8e58"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7c8b816c2b5af5c8a436df44ca08258fc1a13b449393a91484225fcb7545533"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f1088fa100bf46e7b398ffd9904f4808a0612e1d966b4aa43baa535d1b6341eb"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f59dfe57bb1ec82ac0698ebfcdb7bcd0e99c255bd637ff613760d5f33e7c81b3"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:361a1026c9dd4aba0109e4040e2aecf9884f5cfe1b1b1bd3d09419c205e2e53d"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:363afe77cfcbe3a36353d8ea133e904b108feea505aa4792dad6585a8192c55a"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e2c45c208c62e955e8256949eb225bd8b66a4c9b6865729a786f2aa79b72e9d"}, + {file = "aiohttp-3.9.3-cp39-cp39-win32.whl", hash = "sha256:f7217af2e14da0856e082e96ff637f14ae45c10a5714b63c77f26d8884cf1051"}, + {file = "aiohttp-3.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:27468897f628c627230dba07ec65dc8d0db566923c48f29e084ce382119802bc"}, + {file = "aiohttp-3.9.3.tar.gz", hash = "sha256:90842933e5d1ff760fae6caca4b2b3edba53ba8f4b71e95dacf2818a2aca06f7"}, +] + +[package.dependencies] +aiosignal = ">=1.1.2" +async-timeout = {version = ">=4.0,<5.0", markers = "python_version < \"3.11\""} +attrs = ">=17.3.0" +frozenlist = ">=1.1.1" +multidict = ">=4.5,<7.0" +yarl = ">=1.0,<2.0" + +[package.extras] +speedups = ["Brotli", "aiodns", "brotlicffi"] + +[[package]] +name = "aiosignal" +version = "1.3.1" +description = "aiosignal: a list of registered asynchronous callbacks" +optional = false +python-versions = ">=3.7" +files = [ + {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, + {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, +] + +[package.dependencies] +frozenlist = ">=1.1.0" + +[[package]] +name = "alembic" +version = "1.13.1" +description = "A database migration tool for SQLAlchemy." +optional = false +python-versions = ">=3.8" +files = [ + {file = "alembic-1.13.1-py3-none-any.whl", hash = "sha256:2edcc97bed0bd3272611ce3a98d98279e9c209e7186e43e75bbb1b2bdfdbcc43"}, + {file = "alembic-1.13.1.tar.gz", hash = "sha256:4932c8558bf68f2ee92b9bbcb8218671c627064d5b08939437af6d77dc05e595"}, +] + +[package.dependencies] +Mako = "*" +SQLAlchemy = ">=1.3.0" +typing-extensions = ">=4" + +[package.extras] +tz = ["backports.zoneinfo"] + +[[package]] +name = "annotated-types" +version = "0.6.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.8" +files = [ + {file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"}, + {file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"}, +] + +[[package]] +name = "anthropic" +version = "0.21.3" +description = "The official Python library for the anthropic API" +optional = false +python-versions = ">=3.7" +files = [ + {file = "anthropic-0.21.3-py3-none-any.whl", hash = "sha256:5869115453b543a46ded6515c9f29b8d610b6e94bbba3230ad80ac947d2b0862"}, + {file = "anthropic-0.21.3.tar.gz", hash = "sha256:02f1ab5694c497e2b2d42d30d51a4f2edcaca92d2ec86bb64fe78a9c7434a869"}, +] + +[package.dependencies] +anyio = ">=3.5.0,<5" +distro = ">=1.7.0,<2" +httpx = ">=0.23.0,<1" +pydantic = ">=1.9.0,<3" +sniffio = "*" +tokenizers = ">=0.13.0" +typing-extensions = ">=4.7,<5" + +[package.extras] +bedrock = ["boto3 (>=1.28.57)", "botocore (>=1.31.57)"] +vertex = ["google-auth (>=2,<3)"] + +[[package]] +name = "anyio" +version = "4.3.0" +description = "High level compatibility layer for multiple asynchronous event loop implementations" +optional = false +python-versions = ">=3.8" +files = [ + {file = "anyio-4.3.0-py3-none-any.whl", hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8"}, + {file = "anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6"}, +] + +[package.dependencies] +exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} +idna = ">=2.8" +sniffio = ">=1.1" +typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} + +[package.extras] +doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (>=0.23)"] + +[[package]] +name = "appnope" +version = "0.1.4" +description = "Disable App Nap on macOS >= 10.9" +optional = false +python-versions = ">=3.6" +files = [ + {file = "appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c"}, + {file = "appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee"}, +] + +[[package]] +name = "asgiref" +version = "3.8.1" +description = "ASGI specs, helper code, and adapters" +optional = false +python-versions = ">=3.8" +files = [ + {file = "asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47"}, + {file = "asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4", markers = "python_version < \"3.11\""} + +[package.extras] +tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] + +[[package]] +name = "astrapy" +version = "0.7.7" +description = "AstraPy is a Pythonic SDK for DataStax Astra" +optional = false +python-versions = ">=3.8.0,<4.0.0" +files = [ + {file = "astrapy-0.7.7-py3-none-any.whl", hash = "sha256:e5def4e3c5ceb06dfc996471250dc0c972b729c06336ea4aac006dadfc071a9a"}, + {file = "astrapy-0.7.7.tar.gz", hash = "sha256:4bf81096a0c26cce18a14a34bb5f699649fd7d90b4ec6050f3d7c0274722d769"}, +] + +[package.dependencies] +cassio = ">=0.1.4,<0.2.0" +deprecation = ">=2.1.0,<2.2.0" +httpx = {version = ">=0.25.2,<1", extras = ["http2"]} +toml = ">=0.10.2,<0.11.0" + +[[package]] +name = "asttokens" +version = "2.4.1" +description = "Annotate AST trees with source code positions" +optional = false +python-versions = "*" +files = [ + {file = "asttokens-2.4.1-py2.py3-none-any.whl", hash = "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24"}, + {file = "asttokens-2.4.1.tar.gz", hash = "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0"}, +] + +[package.dependencies] +six = ">=1.12.0" + +[package.extras] +astroid = ["astroid (>=1,<2)", "astroid (>=2,<4)"] +test = ["astroid (>=1,<2)", "astroid (>=2,<4)", "pytest"] + +[[package]] +name = "async-timeout" +version = "4.0.3" +description = "Timeout context manager for asyncio programs" +optional = false +python-versions = ">=3.7" +files = [ + {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"}, + {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, +] + +[[package]] +name = "attrs" +version = "23.2.0" +description = "Classes Without Boilerplate" +optional = false +python-versions = ">=3.7" +files = [ + {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, + {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, +] + +[package.extras] +cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] +dev = ["attrs[tests]", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs[tests-no-zope]", "zope-interface"] +tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] +tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] + +[[package]] +name = "backoff" +version = "2.2.1" +description = "Function decoration for backoff and retry" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8"}, + {file = "backoff-2.2.1.tar.gz", hash = "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba"}, +] + +[[package]] +name = "bcrypt" +version = "4.0.1" +description = "Modern password hashing for your software and your servers" +optional = false +python-versions = ">=3.6" +files = [ + {file = "bcrypt-4.0.1-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:b1023030aec778185a6c16cf70f359cbb6e0c289fd564a7cfa29e727a1c38f8f"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:08d2947c490093a11416df18043c27abe3921558d2c03e2076ccb28a116cb6d0"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0eaa47d4661c326bfc9d08d16debbc4edf78778e6aaba29c1bc7ce67214d4410"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae88eca3024bb34bb3430f964beab71226e761f51b912de5133470b649d82344"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:a522427293d77e1c29e303fc282e2d71864579527a04ddcfda6d4f8396c6c36a"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:fbdaec13c5105f0c4e5c52614d04f0bca5f5af007910daa8b6b12095edaa67b3"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:ca3204d00d3cb2dfed07f2d74a25f12fc12f73e606fcaa6975d1f7ae69cacbb2"}, + {file = "bcrypt-4.0.1-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:089098effa1bc35dc055366740a067a2fc76987e8ec75349eb9484061c54f535"}, + {file = "bcrypt-4.0.1-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:e9a51bbfe7e9802b5f3508687758b564069ba937748ad7b9e890086290d2f79e"}, + {file = "bcrypt-4.0.1-cp36-abi3-win32.whl", hash = "sha256:2caffdae059e06ac23fce178d31b4a702f2a3264c20bfb5ff541b338194d8fab"}, + {file = "bcrypt-4.0.1-cp36-abi3-win_amd64.whl", hash = "sha256:8a68f4341daf7522fe8d73874de8906f3a339048ba406be6ddc1b3ccb16fc0d9"}, + {file = "bcrypt-4.0.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf4fa8b2ca74381bb5442c089350f09a3f17797829d958fad058d6e44d9eb83c"}, + {file = "bcrypt-4.0.1-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:67a97e1c405b24f19d08890e7ae0c4f7ce1e56a712a016746c8b2d7732d65d4b"}, + {file = "bcrypt-4.0.1-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b3b85202d95dd568efcb35b53936c5e3b3600c7cdcc6115ba461df3a8e89f38d"}, + {file = "bcrypt-4.0.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cbb03eec97496166b704ed663a53680ab57c5084b2fc98ef23291987b525cb7d"}, + {file = "bcrypt-4.0.1-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:5ad4d32a28b80c5fa6671ccfb43676e8c1cc232887759d1cd7b6f56ea4355215"}, + {file = "bcrypt-4.0.1-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b57adba8a1444faf784394de3436233728a1ecaeb6e07e8c22c8848f179b893c"}, + {file = "bcrypt-4.0.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:705b2cea8a9ed3d55b4491887ceadb0106acf7c6387699fca771af56b1cdeeda"}, + {file = "bcrypt-4.0.1-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:2b3ac11cf45161628f1f3733263e63194f22664bf4d0c0f3ab34099c02134665"}, + {file = "bcrypt-4.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3100851841186c25f127731b9fa11909ab7b1df6fc4b9f8353f4f1fd952fbf71"}, + {file = "bcrypt-4.0.1.tar.gz", hash = "sha256:27d375903ac8261cfe4047f6709d16f7d18d39b1ec92aaf72af989552a650ebd"}, +] + +[package.extras] +tests = ["pytest (>=3.2.1,!=3.3.0)"] +typecheck = ["mypy"] + +[[package]] +name = "bidict" +version = "0.23.1" +description = "The bidirectional mapping library for Python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "bidict-0.23.1-py3-none-any.whl", hash = "sha256:5dae8d4d79b552a71cbabc7deb25dfe8ce710b17ff41711e13010ead2abfc3e5"}, + {file = "bidict-0.23.1.tar.gz", hash = "sha256:03069d763bc387bbd20e7d49914e75fc4132a41937fa3405417e1a5a2d006d71"}, +] + +[[package]] +name = "blinker" +version = "1.7.0" +description = "Fast, simple object-to-object and broadcast signaling" +optional = false +python-versions = ">=3.8" +files = [ + {file = "blinker-1.7.0-py3-none-any.whl", hash = "sha256:c3f865d4d54db7abc53758a01601cf343fe55b84c1de4e3fa910e420b438d5b9"}, + {file = "blinker-1.7.0.tar.gz", hash = "sha256:e6820ff6fa4e4d1d8e2747c2283749c3f547e4fee112b98555cdcdae32996182"}, +] + +[[package]] +name = "brotli" +version = "1.1.0" +description = "Python bindings for the Brotli compression library" +optional = false +python-versions = "*" +files = [ + {file = "Brotli-1.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e1140c64812cb9b06c922e77f1c26a75ec5e3f0fb2bf92cc8c58720dec276752"}, + {file = "Brotli-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c8fd5270e906eef71d4a8d19b7c6a43760c6abcfcc10c9101d14eb2357418de9"}, + {file = "Brotli-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ae56aca0402a0f9a3431cddda62ad71666ca9d4dc3a10a142b9dce2e3c0cda3"}, + {file = "Brotli-1.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:43ce1b9935bfa1ede40028054d7f48b5469cd02733a365eec8a329ffd342915d"}, + {file = "Brotli-1.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:7c4855522edb2e6ae7fdb58e07c3ba9111e7621a8956f481c68d5d979c93032e"}, + {file = "Brotli-1.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:38025d9f30cf4634f8309c6874ef871b841eb3c347e90b0851f63d1ded5212da"}, + {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e6a904cb26bfefc2f0a6f240bdf5233be78cd2488900a2f846f3c3ac8489ab80"}, + {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a37b8f0391212d29b3a91a799c8e4a2855e0576911cdfb2515487e30e322253d"}, + {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e84799f09591700a4154154cab9787452925578841a94321d5ee8fb9a9a328f0"}, + {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f66b5337fa213f1da0d9000bc8dc0cb5b896b726eefd9c6046f699b169c41b9e"}, + {file = "Brotli-1.1.0-cp310-cp310-win32.whl", hash = "sha256:be36e3d172dc816333f33520154d708a2657ea63762ec16b62ece02ab5e4daf2"}, + {file = "Brotli-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:0c6244521dda65ea562d5a69b9a26120769b7a9fb3db2fe9545935ed6735b128"}, + {file = "Brotli-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a3daabb76a78f829cafc365531c972016e4aa8d5b4bf60660ad8ecee19df7ccc"}, + {file = "Brotli-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c8146669223164fc87a7e3de9f81e9423c67a79d6b3447994dfb9c95da16e2d6"}, + {file = "Brotli-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30924eb4c57903d5a7526b08ef4a584acc22ab1ffa085faceb521521d2de32dd"}, + {file = "Brotli-1.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ceb64bbc6eac5a140ca649003756940f8d6a7c444a68af170b3187623b43bebf"}, + {file = "Brotli-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a469274ad18dc0e4d316eefa616d1d0c2ff9da369af19fa6f3daa4f09671fd61"}, + {file = "Brotli-1.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:524f35912131cc2cabb00edfd8d573b07f2d9f21fa824bd3fb19725a9cf06327"}, + {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5b3cc074004d968722f51e550b41a27be656ec48f8afaeeb45ebf65b561481dd"}, + {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:19c116e796420b0cee3da1ccec3b764ed2952ccfcc298b55a10e5610ad7885f9"}, + {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:510b5b1bfbe20e1a7b3baf5fed9e9451873559a976c1a78eebaa3b86c57b4265"}, + {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a1fd8a29719ccce974d523580987b7f8229aeace506952fa9ce1d53a033873c8"}, + {file = "Brotli-1.1.0-cp311-cp311-win32.whl", hash = "sha256:39da8adedf6942d76dc3e46653e52df937a3c4d6d18fdc94a7c29d263b1f5b50"}, + {file = "Brotli-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:aac0411d20e345dc0920bdec5548e438e999ff68d77564d5e9463a7ca9d3e7b1"}, + {file = "Brotli-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:316cc9b17edf613ac76b1f1f305d2a748f1b976b033b049a6ecdfd5612c70409"}, + {file = "Brotli-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:caf9ee9a5775f3111642d33b86237b05808dafcd6268faa492250e9b78046eb2"}, + {file = "Brotli-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70051525001750221daa10907c77830bc889cb6d865cc0b813d9db7fefc21451"}, + {file = "Brotli-1.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7f4bf76817c14aa98cc6697ac02f3972cb8c3da93e9ef16b9c66573a68014f91"}, + {file = "Brotli-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0c5516f0aed654134a2fc936325cc2e642f8a0e096d075209672eb321cff408"}, + {file = "Brotli-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c3020404e0b5eefd7c9485ccf8393cfb75ec38ce75586e046573c9dc29967a0"}, + {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4ed11165dd45ce798d99a136808a794a748d5dc38511303239d4e2363c0695dc"}, + {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4093c631e96fdd49e0377a9c167bfd75b6d0bad2ace734c6eb20b348bc3ea180"}, + {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e4c4629ddad63006efa0ef968c8e4751c5868ff0b1c5c40f76524e894c50248"}, + {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:861bf317735688269936f755fa136a99d1ed526883859f86e41a5d43c61d8966"}, + {file = "Brotli-1.1.0-cp312-cp312-win32.whl", hash = "sha256:5f4d5ea15c9382135076d2fb28dde923352fe02951e66935a9efaac8f10e81b0"}, + {file = "Brotli-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:906bc3a79de8c4ae5b86d3d75a8b77e44404b0f4261714306e3ad248d8ab0951"}, + {file = "Brotli-1.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a090ca607cbb6a34b0391776f0cb48062081f5f60ddcce5d11838e67a01928d1"}, + {file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2de9d02f5bda03d27ede52e8cfe7b865b066fa49258cbab568720aa5be80a47d"}, + {file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2333e30a5e00fe0fe55903c8832e08ee9c3b1382aacf4db26664a16528d51b4b"}, + {file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4d4a848d1837973bf0f4b5e54e3bec977d99be36a7895c61abb659301b02c112"}, + {file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:fdc3ff3bfccdc6b9cc7c342c03aa2400683f0cb891d46e94b64a197910dc4064"}, + {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:5eeb539606f18a0b232d4ba45adccde4125592f3f636a6182b4a8a436548b914"}, + {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:fd5f17ff8f14003595ab414e45fce13d073e0762394f957182e69035c9f3d7c2"}, + {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:069a121ac97412d1fe506da790b3e69f52254b9df4eb665cd42460c837193354"}, + {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:e93dfc1a1165e385cc8239fab7c036fb2cd8093728cbd85097b284d7b99249a2"}, + {file = "Brotli-1.1.0-cp36-cp36m-win32.whl", hash = "sha256:a599669fd7c47233438a56936988a2478685e74854088ef5293802123b5b2460"}, + {file = "Brotli-1.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:d143fd47fad1db3d7c27a1b1d66162e855b5d50a89666af46e1679c496e8e579"}, + {file = "Brotli-1.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:11d00ed0a83fa22d29bc6b64ef636c4552ebafcef57154b4ddd132f5638fbd1c"}, + {file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f733d788519c7e3e71f0855c96618720f5d3d60c3cb829d8bbb722dddce37985"}, + {file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:929811df5462e182b13920da56c6e0284af407d1de637d8e536c5cd00a7daf60"}, + {file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0b63b949ff929fbc2d6d3ce0e924c9b93c9785d877a21a1b678877ffbbc4423a"}, + {file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d192f0f30804e55db0d0e0a35d83a9fead0e9a359a9ed0285dbacea60cc10a84"}, + {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:f296c40e23065d0d6650c4aefe7470d2a25fffda489bcc3eb66083f3ac9f6643"}, + {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:919e32f147ae93a09fe064d77d5ebf4e35502a8df75c29fb05788528e330fe74"}, + {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:23032ae55523cc7bccb4f6a0bf368cd25ad9bcdcc1990b64a647e7bbcce9cb5b"}, + {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:224e57f6eac61cc449f498cc5f0e1725ba2071a3d4f48d5d9dffba42db196438"}, + {file = "Brotli-1.1.0-cp37-cp37m-win32.whl", hash = "sha256:587ca6d3cef6e4e868102672d3bd9dc9698c309ba56d41c2b9c85bbb903cdb95"}, + {file = "Brotli-1.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2954c1c23f81c2eaf0b0717d9380bd348578a94161a65b3a2afc62c86467dd68"}, + {file = "Brotli-1.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:efa8b278894b14d6da122a72fefcebc28445f2d3f880ac59d46c90f4c13be9a3"}, + {file = "Brotli-1.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:03d20af184290887bdea3f0f78c4f737d126c74dc2f3ccadf07e54ceca3bf208"}, + {file = "Brotli-1.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6172447e1b368dcbc458925e5ddaf9113477b0ed542df258d84fa28fc45ceea7"}, + {file = "Brotli-1.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a743e5a28af5f70f9c080380a5f908d4d21d40e8f0e0c8901604d15cfa9ba751"}, + {file = "Brotli-1.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0541e747cce78e24ea12d69176f6a7ddb690e62c425e01d31cc065e69ce55b48"}, + {file = "Brotli-1.1.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cdbc1fc1bc0bff1cef838eafe581b55bfbffaed4ed0318b724d0b71d4d377619"}, + {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:890b5a14ce214389b2cc36ce82f3093f96f4cc730c1cffdbefff77a7c71f2a97"}, + {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ab4fbee0b2d9098c74f3057b2bc055a8bd92ccf02f65944a241b4349229185a"}, + {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:141bd4d93984070e097521ed07e2575b46f817d08f9fa42b16b9b5f27b5ac088"}, + {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fce1473f3ccc4187f75b4690cfc922628aed4d3dd013d047f95a9b3919a86596"}, + {file = "Brotli-1.1.0-cp38-cp38-win32.whl", hash = "sha256:db85ecf4e609a48f4b29055f1e144231b90edc90af7481aa731ba2d059226b1b"}, + {file = "Brotli-1.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3d7954194c36e304e1523f55d7042c59dc53ec20dd4e9ea9d151f1b62b4415c0"}, + {file = "Brotli-1.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5fb2ce4b8045c78ebbc7b8f3c15062e435d47e7393cc57c25115cfd49883747a"}, + {file = "Brotli-1.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7905193081db9bfa73b1219140b3d315831cbff0d8941f22da695832f0dd188f"}, + {file = "Brotli-1.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a77def80806c421b4b0af06f45d65a136e7ac0bdca3c09d9e2ea4e515367c7e9"}, + {file = "Brotli-1.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dadd1314583ec0bf2d1379f7008ad627cd6336625d6679cf2f8e67081b83acf"}, + {file = "Brotli-1.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:901032ff242d479a0efa956d853d16875d42157f98951c0230f69e69f9c09bac"}, + {file = "Brotli-1.1.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:22fc2a8549ffe699bfba2256ab2ed0421a7b8fadff114a3d201794e45a9ff578"}, + {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ae15b066e5ad21366600ebec29a7ccbc86812ed267e4b28e860b8ca16a2bc474"}, + {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:949f3b7c29912693cee0afcf09acd6ebc04c57af949d9bf77d6101ebb61e388c"}, + {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:89f4988c7203739d48c6f806f1e87a1d96e0806d44f0fba61dba81392c9e474d"}, + {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:de6551e370ef19f8de1807d0a9aa2cdfdce2e85ce88b122fe9f6b2b076837e59"}, + {file = "Brotli-1.1.0-cp39-cp39-win32.whl", hash = "sha256:f0d8a7a6b5983c2496e364b969f0e526647a06b075d034f3297dc66f3b360c64"}, + {file = "Brotli-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:cdad5b9014d83ca68c25d2e9444e28e967ef16e80f6b436918c700c117a85467"}, + {file = "Brotli-1.1.0.tar.gz", hash = "sha256:81de08ac11bcb85841e440c13611c00b67d3bf82698314928d0b676362546724"}, +] + +[[package]] +name = "build" +version = "1.2.1" +description = "A simple, correct Python build frontend" +optional = false +python-versions = ">=3.8" +files = [ + {file = "build-1.2.1-py3-none-any.whl", hash = "sha256:75e10f767a433d9a86e50d83f418e83efc18ede923ee5ff7df93b6cb0306c5d4"}, + {file = "build-1.2.1.tar.gz", hash = "sha256:526263f4870c26f26c433545579475377b2b7588b6f1eac76a001e873ae3e19d"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "os_name == \"nt\""} +importlib-metadata = {version = ">=4.6", markers = "python_full_version < \"3.10.2\""} +packaging = ">=19.1" +pyproject_hooks = "*" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} + +[package.extras] +docs = ["furo (>=2023.08.17)", "sphinx (>=7.0,<8.0)", "sphinx-argparse-cli (>=1.5)", "sphinx-autodoc-typehints (>=1.10)", "sphinx-issues (>=3.0.0)"] +test = ["build[uv,virtualenv]", "filelock (>=3)", "pytest (>=6.2.4)", "pytest-cov (>=2.12)", "pytest-mock (>=2)", "pytest-rerunfailures (>=9.1)", "pytest-xdist (>=1.34)", "setuptools (>=42.0.0)", "setuptools (>=56.0.0)", "setuptools (>=56.0.0)", "setuptools (>=67.8.0)", "wheel (>=0.36.0)"] +typing = ["build[uv]", "importlib-metadata (>=5.1)", "mypy (>=1.9.0,<1.10.0)", "tomli", "typing-extensions (>=3.7.4.3)"] +uv = ["uv (>=0.1.18)"] +virtualenv = ["virtualenv (>=20.0.35)"] + +[[package]] +name = "cachetools" +version = "5.3.3" +description = "Extensible memoizing collections and decorators" +optional = false +python-versions = ">=3.7" +files = [ + {file = "cachetools-5.3.3-py3-none-any.whl", hash = "sha256:0abad1021d3f8325b2fc1d2e9c8b9c9d57b04c3932657a72465447332c24d945"}, + {file = "cachetools-5.3.3.tar.gz", hash = "sha256:ba29e2dfa0b8b556606f097407ed1aa62080ee108ab0dc5ec9d6a723a007d105"}, +] + +[[package]] +name = "cassandra-driver" +version = "3.29.1" +description = "DataStax Driver for Apache Cassandra" +optional = false +python-versions = "*" +files = [ + {file = "cassandra-driver-3.29.1.tar.gz", hash = "sha256:38e9c2a2f2a9664bb03f1f852d5fccaeff2163942b5db35dffcf8bf32a51cfe5"}, + {file = "cassandra_driver-3.29.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a8f175c7616a63ca48cb8bd4acc443e2a3d889964d5157cead761f23cc8db7bd"}, + {file = "cassandra_driver-3.29.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7d66398952b9cd21c40edff56e22b6d3bce765edc94b207ddb5896e7bc9aa088"}, + {file = "cassandra_driver-3.29.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bbc6f575ef109ce5d4abfa2033bf36c394032abd83e32ab671159ce68e7e17b"}, + {file = "cassandra_driver-3.29.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78f241af75696adb3e470209e2fbb498804c99e2b197d24d74774eee6784f283"}, + {file = "cassandra_driver-3.29.1-cp310-cp310-win32.whl", hash = "sha256:54d9e651a742d6ca3d874ef8d06a40fa032d2dba97142da2d36f60c5675e39f8"}, + {file = "cassandra_driver-3.29.1-cp310-cp310-win_amd64.whl", hash = "sha256:630dc5423cd40eba0ee9db31065e2238098ff1a25a6b1bd36360f85738f26e4b"}, + {file = "cassandra_driver-3.29.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0b841d38c96bb878d31df393954863652d6d3a85f47bcc00fd1d70a5ea73023f"}, + {file = "cassandra_driver-3.29.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:19cc7375f673e215bd4cbbefae2de9f07830be7dabef55284a2d2ff8d8691efe"}, + {file = "cassandra_driver-3.29.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b74b355be3dcafe652fffda8f14f385ccc1a8dae9df28e6080cc660da39b45f"}, + {file = "cassandra_driver-3.29.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e6dac7eddd3f4581859f180383574068a3f113907811b4dad755a8ace4c3fbd"}, + {file = "cassandra_driver-3.29.1-cp311-cp311-win32.whl", hash = "sha256:293a79dba417112b56320ed0013d71fd7520f5fc4a5fd2ac8000c762c6dd5b07"}, + {file = "cassandra_driver-3.29.1-cp311-cp311-win_amd64.whl", hash = "sha256:7c2374fdf1099047a6c9c8329c79d71ad11e61d9cca7de92a0f49655da4bdd8a"}, + {file = "cassandra_driver-3.29.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4431a0c836f33a33c733c84997fbdb6398be005c4d18a8c8525c469fdc29393c"}, + {file = "cassandra_driver-3.29.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d23b08381b171a9e42ace483a82457edcddada9e8367e31677b97538cde2dc34"}, + {file = "cassandra_driver-3.29.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4beb29a0139e63a10a5b9a3c7b72c30a4e6e20c9f0574f9d22c0d4144fe3d348"}, + {file = "cassandra_driver-3.29.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b206423cc454a78f16b411e7cb641dddc26168ac2e18f2c13665f5f3c89868c"}, + {file = "cassandra_driver-3.29.1-cp312-cp312-win32.whl", hash = "sha256:ac898cca7303a3a2a3070513eee12ef0f1be1a0796935c5b8aa13dae8c0a7f7e"}, + {file = "cassandra_driver-3.29.1-cp312-cp312-win_amd64.whl", hash = "sha256:4ad0c9fb2229048ad6ff8c6ddbf1fdc78b111f2b061c66237c2257fcc4a31b14"}, + {file = "cassandra_driver-3.29.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4282c5deac462e4bb0f6fd0553a33d514dbd5ee99d0812594210080330ddd1a2"}, + {file = "cassandra_driver-3.29.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:41ca7eea069754002418d3bdfbd3dfd150ea12cb9db474ab1a01fa4679a05bcb"}, + {file = "cassandra_driver-3.29.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6639ccb268c4dc754bc45e03551711780d0e02cb298ab26cde1f42b7bcc74f8"}, + {file = "cassandra_driver-3.29.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a9d7d3b1be24a7f113b5404186ccccc977520401303a8fe78ba34134cad2482"}, + {file = "cassandra_driver-3.29.1-cp38-cp38-win32.whl", hash = "sha256:81c8fd556c6e1bb93577e69c1f10a3fadf7ddb93958d226ccbb72389396e9a92"}, + {file = "cassandra_driver-3.29.1-cp38-cp38-win_amd64.whl", hash = "sha256:cfe70ed0f27af949de2767ea9cef4092584e8748759374a55bf23c30746c7b23"}, + {file = "cassandra_driver-3.29.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a2c03c1d834ac1a0ae39f9af297a8cd38829003ce910b08b324fb3abe488ce2b"}, + {file = "cassandra_driver-3.29.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9a3e1e2b01f3b7a5cf75c97401bce830071d99c42464352087d7475e0161af93"}, + {file = "cassandra_driver-3.29.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90c42006665a4e490b0766b70f3d637f36a30accbef2da35d6d4081c0e0bafc3"}, + {file = "cassandra_driver-3.29.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c1aca41f45772f9759e8246030907d92bc35fbbdc91525a3cb9b49939b80ad7"}, + {file = "cassandra_driver-3.29.1-cp39-cp39-win32.whl", hash = "sha256:ce4a66245d4a0c8b07fdcb6398698c2c42eb71245fb49cff39435bb702ff7be6"}, + {file = "cassandra_driver-3.29.1-cp39-cp39-win_amd64.whl", hash = "sha256:4cae69ceb1b1d9383e988a1b790115253eacf7867ceb15ed2adb736e3ce981be"}, +] + +[package.dependencies] +geomet = ">=0.1,<0.3" + +[package.extras] +cle = ["cryptography (>=35.0)"] +graph = ["gremlinpython (==3.4.6)"] + +[[package]] +name = "cassio" +version = "0.1.5" +description = "A framework-agnostic Python library to seamlessly integrate Apache Cassandra(R) with ML/LLM/genAI workloads." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cassio-0.1.5-py3-none-any.whl", hash = "sha256:cf1d11f255c040bc0aede4963ca020840133377aa54f7f15d2f819d6553d52ce"}, + {file = "cassio-0.1.5.tar.gz", hash = "sha256:88c50c34d46a1bfffca1e0b600318a6efef45e6c18a56ddabe208cbede8dcc27"}, +] + +[package.dependencies] +cassandra-driver = ">=3.28.0" +numpy = ">=1.0" +requests = ">=2" + +[[package]] +name = "certifi" +version = "2024.2.2" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, + {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, +] + +[[package]] +name = "cffi" +version = "1.16.0" +description = "Foreign Function Interface for Python calling C code." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, + {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, + {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, + {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, + {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, + {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, + {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, + {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, + {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, + {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, + {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, + {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, + {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, + {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, + {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, +] + +[package.dependencies] +pycparser = "*" + +[[package]] +name = "charset-normalizer" +version = "3.3.2" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, +] + +[[package]] +name = "chroma-hnswlib" +version = "0.7.3" +description = "Chromas fork of hnswlib" +optional = false +python-versions = "*" +files = [ + {file = "chroma-hnswlib-0.7.3.tar.gz", hash = "sha256:b6137bedde49fffda6af93b0297fe00429fc61e5a072b1ed9377f909ed95a932"}, + {file = "chroma_hnswlib-0.7.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:59d6a7c6f863c67aeb23e79a64001d537060b6995c3eca9a06e349ff7b0998ca"}, + {file = "chroma_hnswlib-0.7.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d71a3f4f232f537b6152947006bd32bc1629a8686df22fd97777b70f416c127a"}, + {file = "chroma_hnswlib-0.7.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c92dc1ebe062188e53970ba13f6b07e0ae32e64c9770eb7f7ffa83f149d4210"}, + {file = "chroma_hnswlib-0.7.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49da700a6656fed8753f68d44b8cc8ae46efc99fc8a22a6d970dc1697f49b403"}, + {file = "chroma_hnswlib-0.7.3-cp310-cp310-win_amd64.whl", hash = "sha256:108bc4c293d819b56476d8f7865803cb03afd6ca128a2a04d678fffc139af029"}, + {file = "chroma_hnswlib-0.7.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:11e7ca93fb8192214ac2b9c0943641ac0daf8f9d4591bb7b73be808a83835667"}, + {file = "chroma_hnswlib-0.7.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6f552e4d23edc06cdeb553cdc757d2fe190cdeb10d43093d6a3319f8d4bf1c6b"}, + {file = "chroma_hnswlib-0.7.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f96f4d5699e486eb1fb95849fe35ab79ab0901265805be7e60f4eaa83ce263ec"}, + {file = "chroma_hnswlib-0.7.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:368e57fe9ebae05ee5844840fa588028a023d1182b0cfdb1d13f607c9ea05756"}, + {file = "chroma_hnswlib-0.7.3-cp311-cp311-win_amd64.whl", hash = "sha256:b7dca27b8896b494456db0fd705b689ac6b73af78e186eb6a42fea2de4f71c6f"}, + {file = "chroma_hnswlib-0.7.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:70f897dc6218afa1d99f43a9ad5eb82f392df31f57ff514ccf4eeadecd62f544"}, + {file = "chroma_hnswlib-0.7.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5aef10b4952708f5a1381c124a29aead0c356f8d7d6e0b520b778aaa62a356f4"}, + {file = "chroma_hnswlib-0.7.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ee2d8d1529fca3898d512079144ec3e28a81d9c17e15e0ea4665697a7923253"}, + {file = "chroma_hnswlib-0.7.3-cp37-cp37m-win_amd64.whl", hash = "sha256:a4021a70e898783cd6f26e00008b494c6249a7babe8774e90ce4766dd288c8ba"}, + {file = "chroma_hnswlib-0.7.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a8f61fa1d417fda848e3ba06c07671f14806a2585272b175ba47501b066fe6b1"}, + {file = "chroma_hnswlib-0.7.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d7563be58bc98e8f0866907368e22ae218d6060601b79c42f59af4eccbbd2e0a"}, + {file = "chroma_hnswlib-0.7.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:51b8d411486ee70d7b66ec08cc8b9b6620116b650df9c19076d2d8b6ce2ae914"}, + {file = "chroma_hnswlib-0.7.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d706782b628e4f43f1b8a81e9120ac486837fbd9bcb8ced70fe0d9b95c72d77"}, + {file = "chroma_hnswlib-0.7.3-cp38-cp38-win_amd64.whl", hash = "sha256:54f053dedc0e3ba657f05fec6e73dd541bc5db5b09aa8bc146466ffb734bdc86"}, + {file = "chroma_hnswlib-0.7.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e607c5a71c610a73167a517062d302c0827ccdd6e259af6e4869a5c1306ffb5d"}, + {file = "chroma_hnswlib-0.7.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c2358a795870156af6761890f9eb5ca8cade57eb10c5f046fe94dae1faa04b9e"}, + {file = "chroma_hnswlib-0.7.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7cea425df2e6b8a5e201fff0d922a1cc1d165b3cfe762b1408075723c8892218"}, + {file = "chroma_hnswlib-0.7.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:454df3dd3e97aa784fba7cf888ad191e0087eef0fd8c70daf28b753b3b591170"}, + {file = "chroma_hnswlib-0.7.3-cp39-cp39-win_amd64.whl", hash = "sha256:df587d15007ca701c6de0ee7d5585dd5e976b7edd2b30ac72bc376b3c3f85882"}, +] + +[package.dependencies] +numpy = "*" + +[[package]] +name = "chromadb" +version = "0.4.24" +description = "Chroma." +optional = false +python-versions = ">=3.8" +files = [ + {file = "chromadb-0.4.24-py3-none-any.whl", hash = "sha256:3a08e237a4ad28b5d176685bd22429a03717fe09d35022fb230d516108da01da"}, + {file = "chromadb-0.4.24.tar.gz", hash = "sha256:a5c80b4e4ad9b236ed2d4899a5b9e8002b489293f2881cb2cadab5b199ee1c72"}, +] + +[package.dependencies] +bcrypt = ">=4.0.1" +build = ">=1.0.3" +chroma-hnswlib = "0.7.3" +fastapi = ">=0.95.2" +grpcio = ">=1.58.0" +importlib-resources = "*" +kubernetes = ">=28.1.0" +mmh3 = ">=4.0.1" +numpy = ">=1.22.5" +onnxruntime = ">=1.14.1" +opentelemetry-api = ">=1.2.0" +opentelemetry-exporter-otlp-proto-grpc = ">=1.2.0" +opentelemetry-instrumentation-fastapi = ">=0.41b0" +opentelemetry-sdk = ">=1.2.0" +orjson = ">=3.9.12" +overrides = ">=7.3.1" +posthog = ">=2.4.0" +pulsar-client = ">=3.1.0" +pydantic = ">=1.9" +pypika = ">=0.48.9" +PyYAML = ">=6.0.0" +requests = ">=2.28" +tenacity = ">=8.2.3" +tokenizers = ">=0.13.2" +tqdm = ">=4.65.0" +typer = ">=0.9.0" +typing-extensions = ">=4.5.0" +uvicorn = {version = ">=0.18.3", extras = ["standard"]} + +[[package]] +name = "click" +version = "8.1.7" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "coloredlogs" +version = "15.0.1" +description = "Colored terminal output for Python's logging module" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "coloredlogs-15.0.1-py2.py3-none-any.whl", hash = "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934"}, + {file = "coloredlogs-15.0.1.tar.gz", hash = "sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0"}, +] + +[package.dependencies] +humanfriendly = ">=9.1" + +[package.extras] +cron = ["capturer (>=2.4)"] + +[[package]] +name = "comm" +version = "0.2.2" +description = "Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc." +optional = false +python-versions = ">=3.8" +files = [ + {file = "comm-0.2.2-py3-none-any.whl", hash = "sha256:e6fb86cb70ff661ee8c9c14e7d36d6de3b4066f1441be4063df9c5009f0a64d3"}, + {file = "comm-0.2.2.tar.gz", hash = "sha256:3fd7a84065306e07bea1773df6eb8282de51ba82f77c72f9c85716ab11fe980e"}, +] + +[package.dependencies] +traitlets = ">=4" + +[package.extras] +test = ["pytest"] + +[[package]] +name = "configargparse" +version = "1.7" +description = "A drop-in replacement for argparse that allows options to also be set via config files and/or environment variables." +optional = false +python-versions = ">=3.5" +files = [ + {file = "ConfigArgParse-1.7-py3-none-any.whl", hash = "sha256:d249da6591465c6c26df64a9f73d2536e743be2f244eb3ebe61114af2f94f86b"}, + {file = "ConfigArgParse-1.7.tar.gz", hash = "sha256:e7067471884de5478c58a511e529f0f9bd1c66bfef1dea90935438d6c23306d1"}, +] + +[package.extras] +test = ["PyYAML", "mock", "pytest"] +yaml = ["PyYAML"] + +[[package]] +name = "coverage" +version = "7.4.4" +description = "Code coverage measurement for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "coverage-7.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0be5efd5127542ef31f165de269f77560d6cdef525fffa446de6f7e9186cfb2"}, + {file = "coverage-7.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ccd341521be3d1b3daeb41960ae94a5e87abe2f46f17224ba5d6f2b8398016cf"}, + {file = "coverage-7.4.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09fa497a8ab37784fbb20ab699c246053ac294d13fc7eb40ec007a5043ec91f8"}, + {file = "coverage-7.4.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b1a93009cb80730c9bca5d6d4665494b725b6e8e157c1cb7f2db5b4b122ea562"}, + {file = "coverage-7.4.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:690db6517f09336559dc0b5f55342df62370a48f5469fabf502db2c6d1cffcd2"}, + {file = "coverage-7.4.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:09c3255458533cb76ef55da8cc49ffab9e33f083739c8bd4f58e79fecfe288f7"}, + {file = "coverage-7.4.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8ce1415194b4a6bd0cdcc3a1dfbf58b63f910dcb7330fe15bdff542c56949f87"}, + {file = "coverage-7.4.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b91cbc4b195444e7e258ba27ac33769c41b94967919f10037e6355e998af255c"}, + {file = "coverage-7.4.4-cp310-cp310-win32.whl", hash = "sha256:598825b51b81c808cb6f078dcb972f96af96b078faa47af7dfcdf282835baa8d"}, + {file = "coverage-7.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:09ef9199ed6653989ebbcaacc9b62b514bb63ea2f90256e71fea3ed74bd8ff6f"}, + {file = "coverage-7.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0f9f50e7ef2a71e2fae92774c99170eb8304e3fdf9c8c3c7ae9bab3e7229c5cf"}, + {file = "coverage-7.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:623512f8ba53c422fcfb2ce68362c97945095b864cda94a92edbaf5994201083"}, + {file = "coverage-7.4.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0513b9508b93da4e1716744ef6ebc507aff016ba115ffe8ecff744d1322a7b63"}, + {file = "coverage-7.4.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40209e141059b9370a2657c9b15607815359ab3ef9918f0196b6fccce8d3230f"}, + {file = "coverage-7.4.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a2b2b78c78293782fd3767d53e6474582f62443d0504b1554370bde86cc8227"}, + {file = "coverage-7.4.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:73bfb9c09951125d06ee473bed216e2c3742f530fc5acc1383883125de76d9cd"}, + {file = "coverage-7.4.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1f384c3cc76aeedce208643697fb3e8437604b512255de6d18dae3f27655a384"}, + {file = "coverage-7.4.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:54eb8d1bf7cacfbf2a3186019bcf01d11c666bd495ed18717162f7eb1e9dd00b"}, + {file = "coverage-7.4.4-cp311-cp311-win32.whl", hash = "sha256:cac99918c7bba15302a2d81f0312c08054a3359eaa1929c7e4b26ebe41e9b286"}, + {file = "coverage-7.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:b14706df8b2de49869ae03a5ccbc211f4041750cd4a66f698df89d44f4bd30ec"}, + {file = "coverage-7.4.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:201bef2eea65e0e9c56343115ba3814e896afe6d36ffd37bab783261db430f76"}, + {file = "coverage-7.4.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:41c9c5f3de16b903b610d09650e5e27adbfa7f500302718c9ffd1c12cf9d6818"}, + {file = "coverage-7.4.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d898fe162d26929b5960e4e138651f7427048e72c853607f2b200909794ed978"}, + {file = "coverage-7.4.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ea79bb50e805cd6ac058dfa3b5c8f6c040cb87fe83de10845857f5535d1db70"}, + {file = "coverage-7.4.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce4b94265ca988c3f8e479e741693d143026632672e3ff924f25fab50518dd51"}, + {file = "coverage-7.4.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:00838a35b882694afda09f85e469c96367daa3f3f2b097d846a7216993d37f4c"}, + {file = "coverage-7.4.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:fdfafb32984684eb03c2d83e1e51f64f0906b11e64482df3c5db936ce3839d48"}, + {file = "coverage-7.4.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:69eb372f7e2ece89f14751fbcbe470295d73ed41ecd37ca36ed2eb47512a6ab9"}, + {file = "coverage-7.4.4-cp312-cp312-win32.whl", hash = "sha256:137eb07173141545e07403cca94ab625cc1cc6bc4c1e97b6e3846270e7e1fea0"}, + {file = "coverage-7.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:d71eec7d83298f1af3326ce0ff1d0ea83c7cb98f72b577097f9083b20bdaf05e"}, + {file = "coverage-7.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d5ae728ff3b5401cc320d792866987e7e7e880e6ebd24433b70a33b643bb0384"}, + {file = "coverage-7.4.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cc4f1358cb0c78edef3ed237ef2c86056206bb8d9140e73b6b89fbcfcbdd40e1"}, + {file = "coverage-7.4.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8130a2aa2acb8788e0b56938786c33c7c98562697bf9f4c7d6e8e5e3a0501e4a"}, + {file = "coverage-7.4.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf271892d13e43bc2b51e6908ec9a6a5094a4df1d8af0bfc360088ee6c684409"}, + {file = "coverage-7.4.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a4cdc86d54b5da0df6d3d3a2f0b710949286094c3a6700c21e9015932b81447e"}, + {file = "coverage-7.4.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ae71e7ddb7a413dd60052e90528f2f65270aad4b509563af6d03d53e979feafd"}, + {file = "coverage-7.4.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:38dd60d7bf242c4ed5b38e094baf6401faa114fc09e9e6632374388a404f98e7"}, + {file = "coverage-7.4.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aa5b1c1bfc28384f1f53b69a023d789f72b2e0ab1b3787aae16992a7ca21056c"}, + {file = "coverage-7.4.4-cp38-cp38-win32.whl", hash = "sha256:dfa8fe35a0bb90382837b238fff375de15f0dcdb9ae68ff85f7a63649c98527e"}, + {file = "coverage-7.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:b2991665420a803495e0b90a79233c1433d6ed77ef282e8e152a324bbbc5e0c8"}, + {file = "coverage-7.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3b799445b9f7ee8bf299cfaed6f5b226c0037b74886a4e11515e569b36fe310d"}, + {file = "coverage-7.4.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b4d33f418f46362995f1e9d4f3a35a1b6322cb959c31d88ae56b0298e1c22357"}, + {file = "coverage-7.4.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aadacf9a2f407a4688d700e4ebab33a7e2e408f2ca04dbf4aef17585389eff3e"}, + {file = "coverage-7.4.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c95949560050d04d46b919301826525597f07b33beba6187d04fa64d47ac82e"}, + {file = "coverage-7.4.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff7687ca3d7028d8a5f0ebae95a6e4827c5616b31a4ee1192bdfde697db110d4"}, + {file = "coverage-7.4.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5fc1de20b2d4a061b3df27ab9b7c7111e9a710f10dc2b84d33a4ab25065994ec"}, + {file = "coverage-7.4.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c74880fc64d4958159fbd537a091d2a585448a8f8508bf248d72112723974cbd"}, + {file = "coverage-7.4.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:742a76a12aa45b44d236815d282b03cfb1de3b4323f3e4ec933acfae08e54ade"}, + {file = "coverage-7.4.4-cp39-cp39-win32.whl", hash = "sha256:d89d7b2974cae412400e88f35d86af72208e1ede1a541954af5d944a8ba46c57"}, + {file = "coverage-7.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:9ca28a302acb19b6af89e90f33ee3e1906961f94b54ea37de6737b7ca9d8827c"}, + {file = "coverage-7.4.4-pp38.pp39.pp310-none-any.whl", hash = "sha256:b2c5edc4ac10a7ef6605a966c58929ec6c1bd0917fb8c15cb3363f65aa40e677"}, + {file = "coverage-7.4.4.tar.gz", hash = "sha256:c901df83d097649e257e803be22592aedfd5182f07b3cc87d640bbb9afd50f49"}, +] + +[package.dependencies] +tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} + +[package.extras] +toml = ["tomli"] + +[[package]] +name = "cryptography" +version = "42.0.5" +description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +optional = false +python-versions = ">=3.7" +files = [ + {file = "cryptography-42.0.5-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:a30596bae9403a342c978fb47d9b0ee277699fa53bbafad14706af51fe543d16"}, + {file = "cryptography-42.0.5-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:b7ffe927ee6531c78f81aa17e684e2ff617daeba7f189f911065b2ea2d526dec"}, + {file = "cryptography-42.0.5-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2424ff4c4ac7f6b8177b53c17ed5d8fa74ae5955656867f5a8affaca36a27abb"}, + {file = "cryptography-42.0.5-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:329906dcc7b20ff3cad13c069a78124ed8247adcac44b10bea1130e36caae0b4"}, + {file = "cryptography-42.0.5-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:b03c2ae5d2f0fc05f9a2c0c997e1bc18c8229f392234e8a0194f202169ccd278"}, + {file = "cryptography-42.0.5-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f8837fe1d6ac4a8052a9a8ddab256bc006242696f03368a4009be7ee3075cdb7"}, + {file = "cryptography-42.0.5-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:0270572b8bd2c833c3981724b8ee9747b3ec96f699a9665470018594301439ee"}, + {file = "cryptography-42.0.5-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:b8cac287fafc4ad485b8a9b67d0ee80c66bf3574f655d3b97ef2e1082360faf1"}, + {file = "cryptography-42.0.5-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:16a48c23a62a2f4a285699dba2e4ff2d1cff3115b9df052cdd976a18856d8e3d"}, + {file = "cryptography-42.0.5-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:2bce03af1ce5a5567ab89bd90d11e7bbdff56b8af3acbbec1faded8f44cb06da"}, + {file = "cryptography-42.0.5-cp37-abi3-win32.whl", hash = "sha256:b6cd2203306b63e41acdf39aa93b86fb566049aeb6dc489b70e34bcd07adca74"}, + {file = "cryptography-42.0.5-cp37-abi3-win_amd64.whl", hash = "sha256:98d8dc6d012b82287f2c3d26ce1d2dd130ec200c8679b6213b3c73c08b2b7940"}, + {file = "cryptography-42.0.5-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:5e6275c09d2badf57aea3afa80d975444f4be8d3bc58f7f80d2a484c6f9485c8"}, + {file = "cryptography-42.0.5-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4985a790f921508f36f81831817cbc03b102d643b5fcb81cd33df3fa291a1a1"}, + {file = "cryptography-42.0.5-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7cde5f38e614f55e28d831754e8a3bacf9ace5d1566235e39d91b35502d6936e"}, + {file = "cryptography-42.0.5-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:7367d7b2eca6513681127ebad53b2582911d1736dc2ffc19f2c3ae49997496bc"}, + {file = "cryptography-42.0.5-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:cd2030f6650c089aeb304cf093f3244d34745ce0cfcc39f20c6fbfe030102e2a"}, + {file = "cryptography-42.0.5-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a2913c5375154b6ef2e91c10b5720ea6e21007412f6437504ffea2109b5a33d7"}, + {file = "cryptography-42.0.5-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:c41fb5e6a5fe9ebcd58ca3abfeb51dffb5d83d6775405305bfa8715b76521922"}, + {file = "cryptography-42.0.5-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:3eaafe47ec0d0ffcc9349e1708be2aaea4c6dd4978d76bf6eb0cb2c13636c6fc"}, + {file = "cryptography-42.0.5-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1b95b98b0d2af784078fa69f637135e3c317091b615cd0905f8b8a087e86fa30"}, + {file = "cryptography-42.0.5-cp39-abi3-win32.whl", hash = "sha256:1f71c10d1e88467126f0efd484bd44bca5e14c664ec2ede64c32f20875c0d413"}, + {file = "cryptography-42.0.5-cp39-abi3-win_amd64.whl", hash = "sha256:a011a644f6d7d03736214d38832e030d8268bcff4a41f728e6030325fea3e400"}, + {file = "cryptography-42.0.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:9481ffe3cf013b71b2428b905c4f7a9a4f76ec03065b05ff499bb5682a8d9ad8"}, + {file = "cryptography-42.0.5-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:ba334e6e4b1d92442b75ddacc615c5476d4ad55cc29b15d590cc6b86efa487e2"}, + {file = "cryptography-42.0.5-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:ba3e4a42397c25b7ff88cdec6e2a16c2be18720f317506ee25210f6d31925f9c"}, + {file = "cryptography-42.0.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:111a0d8553afcf8eb02a4fea6ca4f59d48ddb34497aa8706a6cf536f1a5ec576"}, + {file = "cryptography-42.0.5-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cd65d75953847815962c84a4654a84850b2bb4aed3f26fadcc1c13892e1e29f6"}, + {file = "cryptography-42.0.5-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:e807b3188f9eb0eaa7bbb579b462c5ace579f1cedb28107ce8b48a9f7ad3679e"}, + {file = "cryptography-42.0.5-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f12764b8fffc7a123f641d7d049d382b73f96a34117e0b637b80643169cec8ac"}, + {file = "cryptography-42.0.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:37dd623507659e08be98eec89323469e8c7b4c1407c85112634ae3dbdb926fdd"}, + {file = "cryptography-42.0.5.tar.gz", hash = "sha256:6fe07eec95dfd477eb9530aef5bead34fec819b3aaf6c5bd6d20565da607bfe1"}, +] + +[package.dependencies] +cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} + +[package.extras] +docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] +docstest = ["pyenchant (>=1.6.11)", "readme-renderer", "sphinxcontrib-spelling (>=4.0.1)"] +nox = ["nox"] +pep8test = ["check-sdist", "click", "mypy", "ruff"] +sdist = ["build"] +ssh = ["bcrypt (>=3.1.5)"] +test = ["certifi", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] +test-randomorder = ["pytest-randomly"] + +[[package]] +name = "dataclasses-json" +version = "0.6.4" +description = "Easily serialize dataclasses to and from JSON." +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "dataclasses_json-0.6.4-py3-none-any.whl", hash = "sha256:f90578b8a3177f7552f4e1a6e535e84293cd5da421fcce0642d49c0d7bdf8df2"}, + {file = "dataclasses_json-0.6.4.tar.gz", hash = "sha256:73696ebf24936560cca79a2430cbc4f3dd23ac7bf46ed17f38e5e5e7657a6377"}, +] + +[package.dependencies] +marshmallow = ">=3.18.0,<4.0.0" +typing-inspect = ">=0.4.0,<1" + +[[package]] +name = "debugpy" +version = "1.8.1" +description = "An implementation of the Debug Adapter Protocol for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "debugpy-1.8.1-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:3bda0f1e943d386cc7a0e71bfa59f4137909e2ed947fb3946c506e113000f741"}, + {file = "debugpy-1.8.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dda73bf69ea479c8577a0448f8c707691152e6c4de7f0c4dec5a4bc11dee516e"}, + {file = "debugpy-1.8.1-cp310-cp310-win32.whl", hash = "sha256:3a79c6f62adef994b2dbe9fc2cc9cc3864a23575b6e387339ab739873bea53d0"}, + {file = "debugpy-1.8.1-cp310-cp310-win_amd64.whl", hash = "sha256:7eb7bd2b56ea3bedb009616d9e2f64aab8fc7000d481faec3cd26c98a964bcdd"}, + {file = "debugpy-1.8.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:016a9fcfc2c6b57f939673c874310d8581d51a0fe0858e7fac4e240c5eb743cb"}, + {file = "debugpy-1.8.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd97ed11a4c7f6d042d320ce03d83b20c3fb40da892f994bc041bbc415d7a099"}, + {file = "debugpy-1.8.1-cp311-cp311-win32.whl", hash = "sha256:0de56aba8249c28a300bdb0672a9b94785074eb82eb672db66c8144fff673146"}, + {file = "debugpy-1.8.1-cp311-cp311-win_amd64.whl", hash = "sha256:1a9fe0829c2b854757b4fd0a338d93bc17249a3bf69ecf765c61d4c522bb92a8"}, + {file = "debugpy-1.8.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:3ebb70ba1a6524d19fa7bb122f44b74170c447d5746a503e36adc244a20ac539"}, + {file = "debugpy-1.8.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2e658a9630f27534e63922ebf655a6ab60c370f4d2fc5c02a5b19baf4410ace"}, + {file = "debugpy-1.8.1-cp312-cp312-win32.whl", hash = "sha256:caad2846e21188797a1f17fc09c31b84c7c3c23baf2516fed5b40b378515bbf0"}, + {file = "debugpy-1.8.1-cp312-cp312-win_amd64.whl", hash = "sha256:edcc9f58ec0fd121a25bc950d4578df47428d72e1a0d66c07403b04eb93bcf98"}, + {file = "debugpy-1.8.1-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:7a3afa222f6fd3d9dfecd52729bc2e12c93e22a7491405a0ecbf9e1d32d45b39"}, + {file = "debugpy-1.8.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d915a18f0597ef685e88bb35e5d7ab968964b7befefe1aaea1eb5b2640b586c7"}, + {file = "debugpy-1.8.1-cp38-cp38-win32.whl", hash = "sha256:92116039b5500633cc8d44ecc187abe2dfa9b90f7a82bbf81d079fcdd506bae9"}, + {file = "debugpy-1.8.1-cp38-cp38-win_amd64.whl", hash = "sha256:e38beb7992b5afd9d5244e96ad5fa9135e94993b0c551ceebf3fe1a5d9beb234"}, + {file = "debugpy-1.8.1-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:bfb20cb57486c8e4793d41996652e5a6a885b4d9175dd369045dad59eaacea42"}, + {file = "debugpy-1.8.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efd3fdd3f67a7e576dd869c184c5dd71d9aaa36ded271939da352880c012e703"}, + {file = "debugpy-1.8.1-cp39-cp39-win32.whl", hash = "sha256:58911e8521ca0c785ac7a0539f1e77e0ce2df753f786188f382229278b4cdf23"}, + {file = "debugpy-1.8.1-cp39-cp39-win_amd64.whl", hash = "sha256:6df9aa9599eb05ca179fb0b810282255202a66835c6efb1d112d21ecb830ddd3"}, + {file = "debugpy-1.8.1-py2.py3-none-any.whl", hash = "sha256:28acbe2241222b87e255260c76741e1fbf04fdc3b6d094fcf57b6c6f75ce1242"}, + {file = "debugpy-1.8.1.zip", hash = "sha256:f696d6be15be87aef621917585f9bb94b1dc9e8aced570db1b8a6fc14e8f9b42"}, +] + +[[package]] +name = "decorator" +version = "5.1.1" +description = "Decorators for Humans" +optional = false +python-versions = ">=3.5" +files = [ + {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, + {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, +] + +[[package]] +name = "defusedxml" +version = "0.7.1" +description = "XML bomb protection for Python stdlib modules" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, + {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, +] + +[[package]] +name = "deprecated" +version = "1.2.14" +description = "Python @deprecated decorator to deprecate old python classes, functions or methods." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c"}, + {file = "Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3"}, +] + +[package.dependencies] +wrapt = ">=1.10,<2" + +[package.extras] +dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] + +[[package]] +name = "deprecation" +version = "2.1.0" +description = "A library to handle automated deprecations" +optional = false +python-versions = "*" +files = [ + {file = "deprecation-2.1.0-py2.py3-none-any.whl", hash = "sha256:a10811591210e1fb0e768a8c25517cabeabcba6f0bf96564f8ff45189f90b14a"}, + {file = "deprecation-2.1.0.tar.gz", hash = "sha256:72b3bde64e5d778694b0cf68178aed03d15e15477116add3fb773e581f9518ff"}, +] + +[package.dependencies] +packaging = "*" + +[[package]] +name = "dill" +version = "0.3.8" +description = "serialize all of Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "dill-0.3.8-py3-none-any.whl", hash = "sha256:c36ca9ffb54365bdd2f8eb3eff7d2a21237f8452b57ace88b1ac615b7e815bd7"}, + {file = "dill-0.3.8.tar.gz", hash = "sha256:3ebe3c479ad625c4553aca177444d89b486b1d84982eeacded644afc0cf797ca"}, +] + +[package.extras] +graph = ["objgraph (>=1.7.2)"] +profile = ["gprof2dot (>=2022.7.29)"] + +[[package]] +name = "distro" +version = "1.9.0" +description = "Distro - an OS platform information API" +optional = false +python-versions = ">=3.6" +files = [ + {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"}, + {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, +] + +[[package]] +name = "docstring-parser" +version = "0.15" +description = "Parse Python docstrings in reST, Google and Numpydoc format" +optional = false +python-versions = ">=3.6,<4.0" +files = [ + {file = "docstring_parser-0.15-py3-none-any.whl", hash = "sha256:d1679b86250d269d06a99670924d6bce45adc00b08069dae8c47d98e89b667a9"}, + {file = "docstring_parser-0.15.tar.gz", hash = "sha256:48ddc093e8b1865899956fcc03b03e66bb7240c310fac5af81814580c55bf682"}, +] + +[[package]] +name = "duckdb" +version = "0.9.2" +description = "DuckDB embedded database" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "duckdb-0.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:aadcea5160c586704c03a8a796c06a8afffbefefb1986601104a60cb0bfdb5ab"}, + {file = "duckdb-0.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:08215f17147ed83cbec972175d9882387366de2ed36c21cbe4add04b39a5bcb4"}, + {file = "duckdb-0.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ee6c2a8aba6850abef5e1be9dbc04b8e72a5b2c2b67f77892317a21fae868fe7"}, + {file = "duckdb-0.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ff49f3da9399900fd58b5acd0bb8bfad22c5147584ad2427a78d937e11ec9d0"}, + {file = "duckdb-0.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd5ac5baf8597efd2bfa75f984654afcabcd698342d59b0e265a0bc6f267b3f0"}, + {file = "duckdb-0.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:81c6df905589a1023a27e9712edb5b724566587ef280a0c66a7ec07c8083623b"}, + {file = "duckdb-0.9.2-cp310-cp310-win32.whl", hash = "sha256:a298cd1d821c81d0dec8a60878c4b38c1adea04a9675fb6306c8f9083bbf314d"}, + {file = "duckdb-0.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:492a69cd60b6cb4f671b51893884cdc5efc4c3b2eb76057a007d2a2295427173"}, + {file = "duckdb-0.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:061a9ea809811d6e3025c5de31bc40e0302cfb08c08feefa574a6491e882e7e8"}, + {file = "duckdb-0.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a43f93be768af39f604b7b9b48891f9177c9282a408051209101ff80f7450d8f"}, + {file = "duckdb-0.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ac29c8c8f56fff5a681f7bf61711ccb9325c5329e64f23cb7ff31781d7b50773"}, + {file = "duckdb-0.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b14d98d26bab139114f62ade81350a5342f60a168d94b27ed2c706838f949eda"}, + {file = "duckdb-0.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:796a995299878913e765b28cc2b14c8e44fae2f54ab41a9ee668c18449f5f833"}, + {file = "duckdb-0.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6cb64ccfb72c11ec9c41b3cb6181b6fd33deccceda530e94e1c362af5f810ba1"}, + {file = "duckdb-0.9.2-cp311-cp311-win32.whl", hash = "sha256:930740cb7b2cd9e79946e1d3a8f66e15dc5849d4eaeff75c8788d0983b9256a5"}, + {file = "duckdb-0.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:c28f13c45006fd525001b2011cdf91fa216530e9751779651e66edc0e446be50"}, + {file = "duckdb-0.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fbce7bbcb4ba7d99fcec84cec08db40bc0dd9342c6c11930ce708817741faeeb"}, + {file = "duckdb-0.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15a82109a9e69b1891f0999749f9e3265f550032470f51432f944a37cfdc908b"}, + {file = "duckdb-0.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9490fb9a35eb74af40db5569d90df8a04a6f09ed9a8c9caa024998c40e2506aa"}, + {file = "duckdb-0.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:696d5c6dee86c1a491ea15b74aafe34ad2b62dcd46ad7e03b1d00111ca1a8c68"}, + {file = "duckdb-0.9.2-cp37-cp37m-win32.whl", hash = "sha256:4f0935300bdf8b7631ddfc838f36a858c1323696d8c8a2cecbd416bddf6b0631"}, + {file = "duckdb-0.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:0aab900f7510e4d2613263865570203ddfa2631858c7eb8cbed091af6ceb597f"}, + {file = "duckdb-0.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:7d8130ed6a0c9421b135d0743705ea95b9a745852977717504e45722c112bf7a"}, + {file = "duckdb-0.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:974e5de0294f88a1a837378f1f83330395801e9246f4e88ed3bfc8ada65dcbee"}, + {file = "duckdb-0.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4fbc297b602ef17e579bb3190c94d19c5002422b55814421a0fc11299c0c1100"}, + {file = "duckdb-0.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1dd58a0d84a424924a35b3772419f8cd78a01c626be3147e4934d7a035a8ad68"}, + {file = "duckdb-0.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11a1194a582c80dfb57565daa06141727e415ff5d17e022dc5f31888a5423d33"}, + {file = "duckdb-0.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:be45d08541002a9338e568dca67ab4f20c0277f8f58a73dfc1435c5b4297c996"}, + {file = "duckdb-0.9.2-cp38-cp38-win32.whl", hash = "sha256:dd6f88aeb7fc0bfecaca633629ff5c986ac966fe3b7dcec0b2c48632fd550ba2"}, + {file = "duckdb-0.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:28100c4a6a04e69aa0f4a6670a6d3d67a65f0337246a0c1a429f3f28f3c40b9a"}, + {file = "duckdb-0.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7ae5bf0b6ad4278e46e933e51473b86b4b932dbc54ff097610e5b482dd125552"}, + {file = "duckdb-0.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e5d0bb845a80aa48ed1fd1d2d285dd352e96dc97f8efced2a7429437ccd1fe1f"}, + {file = "duckdb-0.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ce262d74a52500d10888110dfd6715989926ec936918c232dcbaddb78fc55b4"}, + {file = "duckdb-0.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6935240da090a7f7d2666f6d0a5e45ff85715244171ca4e6576060a7f4a1200e"}, + {file = "duckdb-0.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5cfb93e73911696a98b9479299d19cfbc21dd05bb7ab11a923a903f86b4d06e"}, + {file = "duckdb-0.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:64e3bc01751f31e7572d2716c3e8da8fe785f1cdc5be329100818d223002213f"}, + {file = "duckdb-0.9.2-cp39-cp39-win32.whl", hash = "sha256:6e5b80f46487636368e31b61461940e3999986359a78660a50dfdd17dd72017c"}, + {file = "duckdb-0.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:e6142a220180dbeea4f341708bd5f9501c5c962ce7ef47c1cadf5e8810b4cb13"}, + {file = "duckdb-0.9.2.tar.gz", hash = "sha256:3843afeab7c3fc4a4c0b53686a4cc1d9cdbdadcbb468d60fef910355ecafd447"}, +] + +[[package]] +name = "ecdsa" +version = "0.18.0" +description = "ECDSA cryptographic signature library (pure python)" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "ecdsa-0.18.0-py2.py3-none-any.whl", hash = "sha256:80600258e7ed2f16b9aa1d7c295bd70194109ad5a30fdee0eaeefef1d4c559dd"}, + {file = "ecdsa-0.18.0.tar.gz", hash = "sha256:190348041559e21b22a1d65cee485282ca11a6f81d503fddb84d5017e9ed1e49"}, +] + +[package.dependencies] +six = ">=1.9.0" + +[package.extras] +gmpy = ["gmpy"] +gmpy2 = ["gmpy2"] + +[[package]] +name = "emoji" +version = "2.11.0" +description = "Emoji for Python" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" +files = [ + {file = "emoji-2.11.0-py2.py3-none-any.whl", hash = "sha256:63fc9107f06c6c2e48e5078ce9575cef98518f5ac09474f6148a43e989989582"}, + {file = "emoji-2.11.0.tar.gz", hash = "sha256:772eaa30f4e0b1ce95148a092df4c7dc97644532c03225326b0fd05e8a9f72a3"}, +] + +[package.extras] +dev = ["coverage", "coveralls", "pytest"] + +[[package]] +name = "exceptiongroup" +version = "1.2.0" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, + {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "execnet" +version = "2.0.2" +description = "execnet: rapid multi-Python deployment" +optional = false +python-versions = ">=3.7" +files = [ + {file = "execnet-2.0.2-py3-none-any.whl", hash = "sha256:88256416ae766bc9e8895c76a87928c0012183da3cc4fc18016e6f050e025f41"}, + {file = "execnet-2.0.2.tar.gz", hash = "sha256:cc59bc4423742fd71ad227122eb0dd44db51efb3dc4095b45ac9a08c770096af"}, +] + +[package.extras] +testing = ["hatch", "pre-commit", "pytest", "tox"] + +[[package]] +name = "executing" +version = "2.0.1" +description = "Get the currently executing AST node of a frame, and other information" +optional = false +python-versions = ">=3.5" +files = [ + {file = "executing-2.0.1-py2.py3-none-any.whl", hash = "sha256:eac49ca94516ccc753f9fb5ce82603156e590b27525a8bc32cce8ae302eb61bc"}, + {file = "executing-2.0.1.tar.gz", hash = "sha256:35afe2ce3affba8ee97f2d69927fa823b08b472b7b994e36a52a964b93d16147"}, +] + +[package.extras] +tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"] + +[[package]] +name = "fastapi" +version = "0.109.2" +description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" +optional = false +python-versions = ">=3.8" +files = [ + {file = "fastapi-0.109.2-py3-none-any.whl", hash = "sha256:2c9bab24667293b501cad8dd388c05240c850b58ec5876ee3283c47d6e1e3a4d"}, + {file = "fastapi-0.109.2.tar.gz", hash = "sha256:f3817eac96fe4f65a2ebb4baa000f394e55f5fccdaf7f75250804bc58f354f73"}, +] + +[package.dependencies] +pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0" +starlette = ">=0.36.3,<0.37.0" +typing-extensions = ">=4.8.0" + +[package.extras] +all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] + +[[package]] +name = "filelock" +version = "3.13.3" +description = "A platform independent file lock." +optional = false +python-versions = ">=3.8" +files = [ + {file = "filelock-3.13.3-py3-none-any.whl", hash = "sha256:5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb"}, + {file = "filelock-3.13.3.tar.gz", hash = "sha256:a79895a25bbefdf55d1a2a0a80968f7dbb28edcd6d4234a0afb3f37ecde4b546"}, +] + +[package.extras] +docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] +typing = ["typing-extensions (>=4.8)"] + +[[package]] +name = "flask" +version = "3.0.2" +description = "A simple framework for building complex web applications." +optional = false +python-versions = ">=3.8" +files = [ + {file = "flask-3.0.2-py3-none-any.whl", hash = "sha256:3232e0e9c850d781933cf0207523d1ece087eb8d87b23777ae38456e2fbe7c6e"}, + {file = "flask-3.0.2.tar.gz", hash = "sha256:822c03f4b799204250a7ee84b1eddc40665395333973dfb9deebfe425fefcb7d"}, +] + +[package.dependencies] +blinker = ">=1.6.2" +click = ">=8.1.3" +itsdangerous = ">=2.1.2" +Jinja2 = ">=3.1.2" +Werkzeug = ">=3.0.0" + +[package.extras] +async = ["asgiref (>=3.2)"] +dotenv = ["python-dotenv"] + +[[package]] +name = "flask-cors" +version = "4.0.0" +description = "A Flask extension adding a decorator for CORS support" +optional = false +python-versions = "*" +files = [ + {file = "Flask-Cors-4.0.0.tar.gz", hash = "sha256:f268522fcb2f73e2ecdde1ef45e2fd5c71cc48fe03cffb4b441c6d1b40684eb0"}, + {file = "Flask_Cors-4.0.0-py2.py3-none-any.whl", hash = "sha256:bc3492bfd6368d27cfe79c7821df5a8a319e1a6d5eab277a3794be19bdc51783"}, +] + +[package.dependencies] +Flask = ">=0.9" + +[[package]] +name = "flask-login" +version = "0.6.3" +description = "User authentication and session management for Flask." +optional = false +python-versions = ">=3.7" +files = [ + {file = "Flask-Login-0.6.3.tar.gz", hash = "sha256:5e23d14a607ef12806c699590b89d0f0e0d67baeec599d75947bf9c147330333"}, + {file = "Flask_Login-0.6.3-py3-none-any.whl", hash = "sha256:849b25b82a436bf830a054e74214074af59097171562ab10bfa999e6b78aae5d"}, +] + +[package.dependencies] +Flask = ">=1.0.4" +Werkzeug = ">=1.0.1" + +[[package]] +name = "flatbuffers" +version = "24.3.25" +description = "The FlatBuffers serialization format for Python" +optional = false +python-versions = "*" +files = [ + {file = "flatbuffers-24.3.25-py2.py3-none-any.whl", hash = "sha256:8dbdec58f935f3765e4f7f3cf635ac3a77f83568138d6a2311f524ec96364812"}, + {file = "flatbuffers-24.3.25.tar.gz", hash = "sha256:de2ec5b203f21441716617f38443e0a8ebf3d25bf0d9c0bb0ce68fa00ad546a4"}, +] + +[[package]] +name = "frozenlist" +version = "1.4.1" +description = "A list-like structure which implements collections.abc.MutableSequence" +optional = false +python-versions = ">=3.8" +files = [ + {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac"}, + {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868"}, + {file = "frozenlist-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc"}, + {file = "frozenlist-1.4.1-cp310-cp310-win32.whl", hash = "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1"}, + {file = "frozenlist-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2"}, + {file = "frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17"}, + {file = "frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8"}, + {file = "frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89"}, + {file = "frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7"}, + {file = "frozenlist-1.4.1-cp38-cp38-win32.whl", hash = "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497"}, + {file = "frozenlist-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6"}, + {file = "frozenlist-1.4.1-cp39-cp39-win32.whl", hash = "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932"}, + {file = "frozenlist-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0"}, + {file = "frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7"}, + {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"}, +] + +[[package]] +name = "fsspec" +version = "2024.3.1" +description = "File-system specification" +optional = false +python-versions = ">=3.8" +files = [ + {file = "fsspec-2024.3.1-py3-none-any.whl", hash = "sha256:918d18d41bf73f0e2b261824baeb1b124bcf771767e3a26425cd7dec3332f512"}, + {file = "fsspec-2024.3.1.tar.gz", hash = "sha256:f39780e282d7d117ffb42bb96992f8a90795e4d0fb0f661a70ca39fe9c43ded9"}, +] + +[package.extras] +abfs = ["adlfs"] +adl = ["adlfs"] +arrow = ["pyarrow (>=1)"] +dask = ["dask", "distributed"] +devel = ["pytest", "pytest-cov"] +dropbox = ["dropbox", "dropboxdrivefs", "requests"] +full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "dask", "distributed", "dropbox", "dropboxdrivefs", "fusepy", "gcsfs", "libarchive-c", "ocifs", "panel", "paramiko", "pyarrow (>=1)", "pygit2", "requests", "s3fs", "smbprotocol", "tqdm"] +fuse = ["fusepy"] +gcs = ["gcsfs"] +git = ["pygit2"] +github = ["requests"] +gs = ["gcsfs"] +gui = ["panel"] +hdfs = ["pyarrow (>=1)"] +http = ["aiohttp (!=4.0.0a0,!=4.0.0a1)"] +libarchive = ["libarchive-c"] +oci = ["ocifs"] +s3 = ["s3fs"] +sftp = ["paramiko"] +smb = ["smbprotocol"] +ssh = ["paramiko"] +tqdm = ["tqdm"] + +[[package]] +name = "geomet" +version = "0.2.1.post1" +description = "GeoJSON <-> WKT/WKB conversion utilities" +optional = false +python-versions = ">2.6, !=3.3.*, <4" +files = [ + {file = "geomet-0.2.1.post1-py3-none-any.whl", hash = "sha256:a41a1e336b381416d6cbed7f1745c848e91defaa4d4c1bdc1312732e46ffad2b"}, + {file = "geomet-0.2.1.post1.tar.gz", hash = "sha256:91d754f7c298cbfcabd3befdb69c641c27fe75e808b27aa55028605761d17e95"}, +] + +[package.dependencies] +click = "*" +six = "*" + +[[package]] +name = "gevent" +version = "24.2.1" +description = "Coroutine-based network library" +optional = false +python-versions = ">=3.8" +files = [ + {file = "gevent-24.2.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:6f947a9abc1a129858391b3d9334c45041c08a0f23d14333d5b844b6e5c17a07"}, + {file = "gevent-24.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bde283313daf0b34a8d1bab30325f5cb0f4e11b5869dbe5bc61f8fe09a8f66f3"}, + {file = "gevent-24.2.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a1df555431f5cd5cc189a6ee3544d24f8c52f2529134685f1e878c4972ab026"}, + {file = "gevent-24.2.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:14532a67f7cb29fb055a0e9b39f16b88ed22c66b96641df8c04bdc38c26b9ea5"}, + {file = "gevent-24.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd23df885318391856415e20acfd51a985cba6919f0be78ed89f5db9ff3a31cb"}, + {file = "gevent-24.2.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:ca80b121bbec76d7794fcb45e65a7eca660a76cc1a104ed439cdbd7df5f0b060"}, + {file = "gevent-24.2.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b9913c45d1be52d7a5db0c63977eebb51f68a2d5e6fd922d1d9b5e5fd758cc98"}, + {file = "gevent-24.2.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:918cdf8751b24986f915d743225ad6b702f83e1106e08a63b736e3a4c6ead789"}, + {file = "gevent-24.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:3d5325ccfadfd3dcf72ff88a92fb8fc0b56cacc7225f0f4b6dcf186c1a6eeabc"}, + {file = "gevent-24.2.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:03aa5879acd6b7076f6a2a307410fb1e0d288b84b03cdfd8c74db8b4bc882fc5"}, + {file = "gevent-24.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8bb35ce57a63c9a6896c71a285818a3922d8ca05d150fd1fe49a7f57287b836"}, + {file = "gevent-24.2.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d7f87c2c02e03d99b95cfa6f7a776409083a9e4d468912e18c7680437b29222c"}, + {file = "gevent-24.2.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:968581d1717bbcf170758580f5f97a2925854943c45a19be4d47299507db2eb7"}, + {file = "gevent-24.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7899a38d0ae7e817e99adb217f586d0a4620e315e4de577444ebeeed2c5729be"}, + {file = "gevent-24.2.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:f5e8e8d60e18d5f7fd49983f0c4696deeddaf6e608fbab33397671e2fcc6cc91"}, + {file = "gevent-24.2.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fbfdce91239fe306772faab57597186710d5699213f4df099d1612da7320d682"}, + {file = "gevent-24.2.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cdf66977a976d6a3cfb006afdf825d1482f84f7b81179db33941f2fc9673bb1d"}, + {file = "gevent-24.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:1dffb395e500613e0452b9503153f8f7ba587c67dd4a85fc7cd7aa7430cb02cc"}, + {file = "gevent-24.2.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:6c47ae7d1174617b3509f5d884935e788f325eb8f1a7efc95d295c68d83cce40"}, + {file = "gevent-24.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7cac622e11b4253ac4536a654fe221249065d9a69feb6cdcd4d9af3503602e0"}, + {file = "gevent-24.2.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bf5b9c72b884c6f0c4ed26ef204ee1f768b9437330422492c319470954bc4cc7"}, + {file = "gevent-24.2.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f5de3c676e57177b38857f6e3cdfbe8f38d1cd754b63200c0615eaa31f514b4f"}, + {file = "gevent-24.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4faf846ed132fd7ebfbbf4fde588a62d21faa0faa06e6f468b7faa6f436b661"}, + {file = "gevent-24.2.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:368a277bd9278ddb0fde308e6a43f544222d76ed0c4166e0d9f6b036586819d9"}, + {file = "gevent-24.2.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f8a04cf0c5b7139bc6368b461257d4a757ea2fe89b3773e494d235b7dd51119f"}, + {file = "gevent-24.2.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9d8d0642c63d453179058abc4143e30718b19a85cbf58c2744c9a63f06a1d388"}, + {file = "gevent-24.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:94138682e68ec197db42ad7442d3cf9b328069c3ad8e4e5022e6b5cd3e7ffae5"}, + {file = "gevent-24.2.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:8f4b8e777d39013595a7740b4463e61b1cfe5f462f1b609b28fbc1e4c4ff01e5"}, + {file = "gevent-24.2.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:141a2b24ad14f7b9576965c0c84927fc85f824a9bb19f6ec1e61e845d87c9cd8"}, + {file = "gevent-24.2.1-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:9202f22ef811053077d01f43cc02b4aaf4472792f9fd0f5081b0b05c926cca19"}, + {file = "gevent-24.2.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2955eea9c44c842c626feebf4459c42ce168685aa99594e049d03bedf53c2800"}, + {file = "gevent-24.2.1-cp38-cp38-win32.whl", hash = "sha256:44098038d5e2749b0784aabb27f1fcbb3f43edebedf64d0af0d26955611be8d6"}, + {file = "gevent-24.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:117e5837bc74a1673605fb53f8bfe22feb6e5afa411f524c835b2ddf768db0de"}, + {file = "gevent-24.2.1-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:2ae3a25ecce0a5b0cd0808ab716bfca180230112bb4bc89b46ae0061d62d4afe"}, + {file = "gevent-24.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a7ceb59986456ce851160867ce4929edaffbd2f069ae25717150199f8e1548b8"}, + {file = "gevent-24.2.1-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:2e9ac06f225b696cdedbb22f9e805e2dd87bf82e8fa5e17756f94e88a9d37cf7"}, + {file = "gevent-24.2.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:90cbac1ec05b305a1b90ede61ef73126afdeb5a804ae04480d6da12c56378df1"}, + {file = "gevent-24.2.1-cp39-cp39-win32.whl", hash = "sha256:782a771424fe74bc7e75c228a1da671578c2ba4ddb2ca09b8f959abdf787331e"}, + {file = "gevent-24.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:3adfb96637f44010be8abd1b5e73b5070f851b817a0b182e601202f20fa06533"}, + {file = "gevent-24.2.1-pp310-pypy310_pp73-macosx_11_0_universal2.whl", hash = "sha256:7b00f8c9065de3ad226f7979154a7b27f3b9151c8055c162332369262fc025d8"}, + {file = "gevent-24.2.1.tar.gz", hash = "sha256:432fc76f680acf7cf188c2ee0f5d3ab73b63c1f03114c7cd8a34cebbe5aa2056"}, +] + +[package.dependencies] +cffi = {version = ">=1.12.2", markers = "platform_python_implementation == \"CPython\" and sys_platform == \"win32\""} +greenlet = [ + {version = ">=2.0.0", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.11\""}, + {version = ">=3.0rc3", markers = "platform_python_implementation == \"CPython\" and python_version >= \"3.11\""}, +] +"zope.event" = "*" +"zope.interface" = "*" + +[package.extras] +dnspython = ["dnspython (>=1.16.0,<2.0)", "idna"] +docs = ["furo", "repoze.sphinx.autointerface", "sphinx", "sphinxcontrib-programoutput", "zope.schema"] +monitor = ["psutil (>=5.7.0)"] +recommended = ["cffi (>=1.12.2)", "dnspython (>=1.16.0,<2.0)", "idna", "psutil (>=5.7.0)"] +test = ["cffi (>=1.12.2)", "coverage (>=5.0)", "dnspython (>=1.16.0,<2.0)", "idna", "objgraph", "psutil (>=5.7.0)", "requests"] + +[[package]] +name = "geventhttpclient" +version = "2.0.12" +description = "http client library for gevent" +optional = false +python-versions = "*" +files = [ + {file = "geventhttpclient-2.0.12-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6d0fafc15bbd93b1f271b4c14b327d15c6930c8d78d8ee0d8a55c9cd3e34c18f"}, + {file = "geventhttpclient-2.0.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3f429ece7b6612ef333e9bbeb205513cec33a178f545b3612530a9c5c36a0310"}, + {file = "geventhttpclient-2.0.12-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:20ffc5a2b9cb5557d529d9296ffdaa5057a23e6bb439a905160a787079ec78a2"}, + {file = "geventhttpclient-2.0.12-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:80a96670c5ab668f52dcaf705640b442faeafb2bfd2e54d5f08ac29ac80aab12"}, + {file = "geventhttpclient-2.0.12-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4766aff690198119c998474d9c20c1b3ffaff337d0d62a6d8b19cc871c3a276d"}, + {file = "geventhttpclient-2.0.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f6d15f459737178e2b9a1d37b32161955a7d72062a3fc473d88c9e9f146cff22"}, + {file = "geventhttpclient-2.0.12-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a75007314fc15947fd94f154e139a6f78a4d40ed70d52dbb1724e7ea2d732ca7"}, + {file = "geventhttpclient-2.0.12-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:16e440152ea4f943dfc476462c1c3f29d47d583e679b58bccac9bfaa33eedcfd"}, + {file = "geventhttpclient-2.0.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e1d9c9b533b6c0b5a7eac23f68b25c8d3db1d38b8e504756c53366d2622a24a5"}, + {file = "geventhttpclient-2.0.12-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:758dd4a3172f740255f755fd393f0888e879a7102a537bba98a35a417be30d3e"}, + {file = "geventhttpclient-2.0.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:933426c92e85d8f6717c4d61f2c6c99fbb7d84c91373400eaf381052a35ea414"}, + {file = "geventhttpclient-2.0.12-cp310-cp310-win32.whl", hash = "sha256:e70247c900c4e4413af155e49f342055af9eb20c141735cce36d8a9dc10dc314"}, + {file = "geventhttpclient-2.0.12-cp310-cp310-win_amd64.whl", hash = "sha256:8dac40240fe446b94dd8645e2691d077b98b1e109ed945d2c91923c300c6f66d"}, + {file = "geventhttpclient-2.0.12-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3e3b3b2857ed48dd8af15c8e09539c8e0bf3721f515c0a8f3cfcbe0090196cc4"}, + {file = "geventhttpclient-2.0.12-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:114cfa7f4db7dcb5603ade4744bc6f5d6d168c94b05aca052e2fc84c906d2009"}, + {file = "geventhttpclient-2.0.12-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:904aaab04a8c4ebf52217930242693509cfbbd90f2b2afc454e14da82710367f"}, + {file = "geventhttpclient-2.0.12-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56935ebec38a7c9ccc3dcadaebf2624601567504cd3a44794dc9262aca147040"}, + {file = "geventhttpclient-2.0.12-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bff88eededd1f915cd86de5e8a891e1988b6d42093cc07be5fe3133f8baf170c"}, + {file = "geventhttpclient-2.0.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:212014f4133938ba6453dbfa6d3a643c915dd4873d1de1d6172e4c6c178e4a6c"}, + {file = "geventhttpclient-2.0.12-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d471e79a55d37ad021a4832b0895bccb638f70664040a29230e156a0b92b23d"}, + {file = "geventhttpclient-2.0.12-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:599c4d37d928323b5f0353434f73de9e88f305f59a5472ffc7f5c131a2485512"}, + {file = "geventhttpclient-2.0.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:fddf2b3c4d5d99b826561173be04adbc92cab52081ba142c2158e0ba3b08b762"}, + {file = "geventhttpclient-2.0.12-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:5075c7f15e0a39b7ceae6afcb0b3a66c0ab9364a9eb589b7f51b567835fae5d7"}, + {file = "geventhttpclient-2.0.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:58a6f9d93ef2b1a09479564c951bc7b058350bd757628a32945f274cd314fb98"}, + {file = "geventhttpclient-2.0.12-cp311-cp311-win32.whl", hash = "sha256:a0bb5a35b199356b0c9b5ec3c3152ebfe4ecbd79e00d486d461920a9d96d1fd2"}, + {file = "geventhttpclient-2.0.12-cp311-cp311-win_amd64.whl", hash = "sha256:972a92f4a453a3ef4737e79e7e64f3089a06f385e13493fa19381486e893bd98"}, + {file = "geventhttpclient-2.0.12-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0bee74f32eed6278f3837e07983b5a6b186920c7eb3b35bc6e97360697632655"}, + {file = "geventhttpclient-2.0.12-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fb85d8ed42cc389e5cdac06221f16cb6bca9dbbf5219c44d0731f742a6bffc09"}, + {file = "geventhttpclient-2.0.12-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c302a16328406003cf4d7d71f59cafc2d42f13d5dc9ea4c8bd248390de985a86"}, + {file = "geventhttpclient-2.0.12-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3266ef4da21a47d0181d4e3cb5209494e3ce6e4d4cc71414ea74b3a1f7e0e921"}, + {file = "geventhttpclient-2.0.12-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:acb7a257e8f4f0c0335a259f2e9eae527fa042db9ea2e4580a381e9c01fc49f4"}, + {file = "geventhttpclient-2.0.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4741d66098b2b289f584effa7de3ae7bf1efb06e2d83abdbbc468a0a4dec6b3a"}, + {file = "geventhttpclient-2.0.12-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ef2b523043ab9c6057ed19993f629e3fa47f8f92a319f5682de05e604ed8cc9"}, + {file = "geventhttpclient-2.0.12-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:235058a6e420b2aae196a4ba7e23f81ebc2dc3acf6baa9d85dc99963b3e0f0cf"}, + {file = "geventhttpclient-2.0.12-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:c918d731e0fe676b4c06f53081526f4d3f4836b7a72be7b46c90603a280260fa"}, + {file = "geventhttpclient-2.0.12-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:9e7696a61b384f8d2a075cca9633fdcc897c43eabbcf70fca492206241fa1a3b"}, + {file = "geventhttpclient-2.0.12-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:105a1aa161223079dbd669b4334cd765964b5917ca4f3da8c5b59c4ef36a0adf"}, + {file = "geventhttpclient-2.0.12-cp312-cp312-win32.whl", hash = "sha256:09e13c05633d1eeb2cba68835618f4ee25c5a7b466c47cfdb01174f61e51a23d"}, + {file = "geventhttpclient-2.0.12-cp312-cp312-win_amd64.whl", hash = "sha256:f853438a1850d45fb434e42ffbb06be81af558e5dd9243d530c2cdc5f804627f"}, + {file = "geventhttpclient-2.0.12-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:62ad2ac321967ff92768e93ea18cb59f8920fbae5b42340b93e7cf11ee4f35d3"}, + {file = "geventhttpclient-2.0.12-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de8b6618a354bded39224def8b6e8b939c468f0edeb2570fdacd9003fd14c57c"}, + {file = "geventhttpclient-2.0.12-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:902ba66284d40dd97a693e952e4bb2f59528806ee40ecd586471fd5bca7fb295"}, + {file = "geventhttpclient-2.0.12-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9ef6c9acff6ce379c8a851554954eee6481c35531d82888a46ccada0ea17a791"}, + {file = "geventhttpclient-2.0.12-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e8abf4ccd59d58f7aa91f4c68760d82534bac5c5c9b7d2ccb4c0a5fc69585ff"}, + {file = "geventhttpclient-2.0.12-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:bdeed563faa09fd51ee4606b92f69ecd42b67277ed590f2921816941ed031177"}, + {file = "geventhttpclient-2.0.12-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:5a7d9b7e2dbc962f143938cdef8a657af1ccf423b2443a194b86ba0e85735c23"}, + {file = "geventhttpclient-2.0.12-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:a9a7ea4665418abe093e48576769181ae3c75a97cafe107c0463a169af755b2c"}, + {file = "geventhttpclient-2.0.12-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:19488a212c858792fd4fa83be568d4cdbbd4c1267b03b10b6a8a654fd862d2f9"}, + {file = "geventhttpclient-2.0.12-cp36-cp36m-win32.whl", hash = "sha256:445b80548062ef6c1b30e5e1b4ec471937fda64b783da953462972f48c2038de"}, + {file = "geventhttpclient-2.0.12-cp36-cp36m-win_amd64.whl", hash = "sha256:bf283bdbb4b935bfef114e1af19535a602e717ae9a7e8408ab61775d06a463b4"}, + {file = "geventhttpclient-2.0.12-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:370086ced942449f9b60590d215eec7f81fe54d7e3ee3add6b2f014ccac4f38d"}, + {file = "geventhttpclient-2.0.12-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e405735db8261ca99d9b80fda3f46d457f04b98a7ce0e49bb35ca32c2a5bbb2d"}, + {file = "geventhttpclient-2.0.12-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6f4680b0ed5e588437797026f25829eb9681954ac64470dc8014436910b2fb09"}, + {file = "geventhttpclient-2.0.12-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ad053e7b4ac2f9fcdb02a5d9b99fd72acf28265ba8be7392a25235bb631d2511"}, + {file = "geventhttpclient-2.0.12-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64232158542f2adfde24f41c1e3ed731cca67e469e653ac7634815af168551b4"}, + {file = "geventhttpclient-2.0.12-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:9be5c3f68e4f41aceccae38508029a70b1fb3f9fc840b7c55971f5fbe099d7e4"}, + {file = "geventhttpclient-2.0.12-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:06b4276075f4f3eeb30a3c1476f40d53030159450def58c1d8c3b724411d8ed9"}, + {file = "geventhttpclient-2.0.12-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:b311beb0657394b5df09af05ec5d84058f3531f3176ab1a0f7f4eae7b56bc315"}, + {file = "geventhttpclient-2.0.12-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:b6a9d00b58527328d9f7a0a20b715d4e780a990b0fb75b556085417c22d73dd0"}, + {file = "geventhttpclient-2.0.12-cp37-cp37m-win32.whl", hash = "sha256:987ef3bd0d7e3b01cafc8e135ab6e8f977b60eeda096ead2cb5504124896b1a2"}, + {file = "geventhttpclient-2.0.12-cp37-cp37m-win_amd64.whl", hash = "sha256:dca64867b2d79433eb8557db00e74e17a2f0d444a9a90fb6f49cadaeddf703a5"}, + {file = "geventhttpclient-2.0.12-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:707467d6e8ad19749e7130b7c7bcb3a446c8e4f66454e1d47f4dfffa974683da"}, + {file = "geventhttpclient-2.0.12-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c2e436a2c41c71db17fd46df4925eb5e4d3856eb1b5fda0ce6b1137a6c6c87fa"}, + {file = "geventhttpclient-2.0.12-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f88d2f3a20afa999548622b31dbc3db5aa355c3032f3ae96a4195c5f938fee92"}, + {file = "geventhttpclient-2.0.12-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:31a6581b8de9fa4b44916dcfabdc608409cfcf02fac39a62d40f6bcf6af726ad"}, + {file = "geventhttpclient-2.0.12-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c91e0ee50f8a1ea3a268f06c5bd44efe86b7f57961d7c923602038fcc010c3c"}, + {file = "geventhttpclient-2.0.12-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e3031817b8f2411086765de4bb1080c755b009ee8dc4a6111ad74f6ff4a363f"}, + {file = "geventhttpclient-2.0.12-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ff9a95e2d2035c1f5ac726166a598ea4071412c304a74a8cd5d2d8dfbf40b5e"}, + {file = "geventhttpclient-2.0.12-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:04f41d8f14e241e8d0c828ff59634674e98f96f39f6d12f43009a7332c4e2c82"}, + {file = "geventhttpclient-2.0.12-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:bea7376205629e8964f624b08d6836892e8d17ed8b8a57d5d2edbd7983440652"}, + {file = "geventhttpclient-2.0.12-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:fd9baf30e2bdd3110394365998037a45b43f86804b8f3c77f194f64eddc7dc54"}, + {file = "geventhttpclient-2.0.12-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:23c27b04ad25258959c088c0d87832befc7be2b09c5c35fdd76e417f5b546da0"}, + {file = "geventhttpclient-2.0.12-cp38-cp38-win32.whl", hash = "sha256:792e154009f6f63e3fbbe4b3109780ada275c4ed29659430c06dc8e1b2ed03ef"}, + {file = "geventhttpclient-2.0.12-cp38-cp38-win_amd64.whl", hash = "sha256:7b41a0510297a8ebbeffbef082e0896ecf37d5302999a3b58d208193c3c3e362"}, + {file = "geventhttpclient-2.0.12-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5006e34586bba4ebd5a7a5482f9e7743e1b3b9ff50c994105fb45e43044c38c9"}, + {file = "geventhttpclient-2.0.12-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d812074192822f57603973d6bcced0f02c6cc371cf63e729793f193c874f30ce"}, + {file = "geventhttpclient-2.0.12-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2a64bd8bce446be4fe869b64af310cd218d2329aa4e9d85b6a060da93c62296b"}, + {file = "geventhttpclient-2.0.12-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7fc536f2972c75da85f9360d0a3e5433baf6d777442a013052f9a501311ddcd"}, + {file = "geventhttpclient-2.0.12-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a60dec2ac44f494af9e42889dd7f7d653545b4c4892da4acbe383c0ffc305a1"}, + {file = "geventhttpclient-2.0.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa2ef1b92662ee9866bda52123f6f266ff4479437e7b5037a6427cf09e071e25"}, + {file = "geventhttpclient-2.0.12-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b8215e9a018a3634bdef4891634ceb9b10f47292b0091a1d96c363d8d5d7fdd"}, + {file = "geventhttpclient-2.0.12-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:90d5c0974518d35514a8896529d113e778e9d42d10699ac6051cd3e8f1ff81f6"}, + {file = "geventhttpclient-2.0.12-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:83c28617b02b6ab53653324b2a9ff2d4a4b1f1582fbc4e70f47d2ef9fe6ab1f7"}, + {file = "geventhttpclient-2.0.12-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:d8c7dfa2bcd15988a350e90b32c6b5426924f2ffd0ce75f52ca2d5ef540b3fbc"}, + {file = "geventhttpclient-2.0.12-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ded99bdbe7953f0734720d9908ed6f808fd12e97de05508822695a87b69f10f2"}, + {file = "geventhttpclient-2.0.12-cp39-cp39-win32.whl", hash = "sha256:ebcd7311901e52929d2bd3af9442970fdd12b200285d9a55d52994e033e73050"}, + {file = "geventhttpclient-2.0.12-cp39-cp39-win_amd64.whl", hash = "sha256:204c3976b2a4fcefe8f157fe303da45b85fc31147bdfce7b53b1098f05f1cad2"}, + {file = "geventhttpclient-2.0.12-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c651d22fae3084502afc876e8c73d521496f512e16828939333f17cad64ea47f"}, + {file = "geventhttpclient-2.0.12-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45c111addb5b27431805a8ad544dec292a7153cc44b68df28e782821431970d8"}, + {file = "geventhttpclient-2.0.12-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14cb7f4854d77c63506e31677fb548d137b20cbe34a11b5442f065b1e46c2246"}, + {file = "geventhttpclient-2.0.12-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8ac257aa714999b523282c0da6faf4d333d44131cea3b15fe802e00d35dd5c2"}, + {file = "geventhttpclient-2.0.12-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d97a41f959cd331eb8a633ed8edf6cc002a2a41a21e94876db833729b803924f"}, + {file = "geventhttpclient-2.0.12-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6ecb9a600a2da862b079ef3ebdffc9acec089c914bebc0c54614049584bfbb94"}, + {file = "geventhttpclient-2.0.12-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:662bb04e99466c25a1bf8b47351f79b339b6627721bb357bf3bc0d263c394176"}, + {file = "geventhttpclient-2.0.12-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:80a6b4c9e1ade3ae090b7b679d5b691d0c87460612983d4ab951043f859adffb"}, + {file = "geventhttpclient-2.0.12-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13a359605dab2b92df4ef1bab7f1bec26e82acdc4253828a508f55375af50b48"}, + {file = "geventhttpclient-2.0.12-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:fc17f57be8254329715702d00536a443c29b52f2ef750bc0650554fb3b7e33e7"}, + {file = "geventhttpclient-2.0.12-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b58096bcaaa259e8d107749539b1d3804fc6ec395e91dec8040d448d298861c8"}, + {file = "geventhttpclient-2.0.12-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9eb66bff9ed4d4f0bced3498746d86c949bf99e2440ceb968e6e7c542b3982b0"}, + {file = "geventhttpclient-2.0.12-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0158f45fd611b585c54380d981181c303313f3e059395310112805f53998d061"}, + {file = "geventhttpclient-2.0.12-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13129723ba3568f0a373cbd612130e2d78b3f284cf6a62385e26a92d7627a570"}, + {file = "geventhttpclient-2.0.12-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:571be0c875503ef5088cb417e84b707c922e3e2bd5e302e609d25e008cf037eb"}, + {file = "geventhttpclient-2.0.12-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:46e1706e3a44bb3423fc8d10b44e71c8a52c6535e22d483519dde008723c4f25"}, + {file = "geventhttpclient-2.0.12-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9de259de7ccc19b47537e21b47a74442ad64d1a1a262b971713d6af8cc8f16f9"}, + {file = "geventhttpclient-2.0.12-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4d777dced8a8e04fd8e0811c3b764d9a476b6a4c865f10079cc4f27b95b37196"}, + {file = "geventhttpclient-2.0.12-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fcd4f45055a2e2f66e67016599d3fac33bc67b3bd67b672c1503a5de7543c1b6"}, + {file = "geventhttpclient-2.0.12-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:61b078cfc4b34a0d50224adf80c7eeae8e23fe6d8cb35926ccd3f3a6b86f921f"}, + {file = "geventhttpclient-2.0.12.tar.gz", hash = "sha256:ebea08e79c1aa7d03b43936b347c0f87356e6fb1c6845735a11f23c949c655f7"}, +] + +[package.dependencies] +brotli = "*" +certifi = "*" +gevent = ">=0.13" +six = "*" + +[[package]] +name = "google-auth" +version = "2.29.0" +description = "Google Authentication Library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "google-auth-2.29.0.tar.gz", hash = "sha256:672dff332d073227550ffc7457868ac4218d6c500b155fe6cc17d2b13602c360"}, + {file = "google_auth-2.29.0-py2.py3-none-any.whl", hash = "sha256:d452ad095688cd52bae0ad6fafe027f6a6d6f560e810fec20914e17a09526415"}, +] + +[package.dependencies] +cachetools = ">=2.0.0,<6.0" +pyasn1-modules = ">=0.2.1" +rsa = ">=3.1.4,<5" + +[package.extras] +aiohttp = ["aiohttp (>=3.6.2,<4.0.0.dev0)", "requests (>=2.20.0,<3.0.0.dev0)"] +enterprise-cert = ["cryptography (==36.0.2)", "pyopenssl (==22.0.0)"] +pyopenssl = ["cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] +reauth = ["pyu2f (>=0.1.5)"] +requests = ["requests (>=2.20.0,<3.0.0.dev0)"] + +[[package]] +name = "googleapis-common-protos" +version = "1.63.0" +description = "Common protobufs used in Google APIs" +optional = false +python-versions = ">=3.7" +files = [ + {file = "googleapis-common-protos-1.63.0.tar.gz", hash = "sha256:17ad01b11d5f1d0171c06d3ba5c04c54474e883b66b949722b4938ee2694ef4e"}, + {file = "googleapis_common_protos-1.63.0-py2.py3-none-any.whl", hash = "sha256:ae45f75702f7c08b541f750854a678bd8f534a1a6bace6afe975f1d0a82d6632"}, +] + +[package.dependencies] +protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0.dev0" + +[package.extras] +grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"] + +[[package]] +name = "greenlet" +version = "3.0.3" +description = "Lightweight in-process concurrent programming" +optional = false +python-versions = ">=3.7" +files = [ + {file = "greenlet-3.0.3-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9da2bd29ed9e4f15955dd1595ad7bc9320308a3b766ef7f837e23ad4b4aac31a"}, + {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d353cadd6083fdb056bb46ed07e4340b0869c305c8ca54ef9da3421acbdf6881"}, + {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dca1e2f3ca00b84a396bc1bce13dd21f680f035314d2379c4160c98153b2059b"}, + {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3ed7fb269f15dc662787f4119ec300ad0702fa1b19d2135a37c2c4de6fadfd4a"}, + {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd4f49ae60e10adbc94b45c0b5e6a179acc1736cf7a90160b404076ee283cf83"}, + {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:73a411ef564e0e097dbe7e866bb2dda0f027e072b04da387282b02c308807405"}, + {file = "greenlet-3.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7f362975f2d179f9e26928c5b517524e89dd48530a0202570d55ad6ca5d8a56f"}, + {file = "greenlet-3.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:649dde7de1a5eceb258f9cb00bdf50e978c9db1b996964cd80703614c86495eb"}, + {file = "greenlet-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:68834da854554926fbedd38c76e60c4a2e3198c6fbed520b106a8986445caaf9"}, + {file = "greenlet-3.0.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:b1b5667cced97081bf57b8fa1d6bfca67814b0afd38208d52538316e9422fc61"}, + {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52f59dd9c96ad2fc0d5724107444f76eb20aaccb675bf825df6435acb7703559"}, + {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:afaff6cf5200befd5cec055b07d1c0a5a06c040fe5ad148abcd11ba6ab9b114e"}, + {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe754d231288e1e64323cfad462fcee8f0288654c10bdf4f603a39ed923bef33"}, + {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2797aa5aedac23af156bbb5a6aa2cd3427ada2972c828244eb7d1b9255846379"}, + {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7f009caad047246ed379e1c4dbcb8b020f0a390667ea74d2387be2998f58a22"}, + {file = "greenlet-3.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c5e1536de2aad7bf62e27baf79225d0d64360d4168cf2e6becb91baf1ed074f3"}, + {file = "greenlet-3.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:894393ce10ceac937e56ec00bb71c4c2f8209ad516e96033e4b3b1de270e200d"}, + {file = "greenlet-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:1ea188d4f49089fc6fb283845ab18a2518d279c7cd9da1065d7a84e991748728"}, + {file = "greenlet-3.0.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:70fb482fdf2c707765ab5f0b6655e9cfcf3780d8d87355a063547b41177599be"}, + {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4d1ac74f5c0c0524e4a24335350edad7e5f03b9532da7ea4d3c54d527784f2e"}, + {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:149e94a2dd82d19838fe4b2259f1b6b9957d5ba1b25640d2380bea9c5df37676"}, + {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15d79dd26056573940fcb8c7413d84118086f2ec1a8acdfa854631084393efcc"}, + {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b7db1ebff4ba09aaaeae6aa491daeb226c8150fc20e836ad00041bcb11230"}, + {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fcd2469d6a2cf298f198f0487e0a5b1a47a42ca0fa4dfd1b6862c999f018ebbf"}, + {file = "greenlet-3.0.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1f672519db1796ca0d8753f9e78ec02355e862d0998193038c7073045899f305"}, + {file = "greenlet-3.0.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2516a9957eed41dd8f1ec0c604f1cdc86758b587d964668b5b196a9db5bfcde6"}, + {file = "greenlet-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:bba5387a6975598857d86de9eac14210a49d554a77eb8261cc68b7d082f78ce2"}, + {file = "greenlet-3.0.3-cp37-cp37m-macosx_11_0_universal2.whl", hash = "sha256:5b51e85cb5ceda94e79d019ed36b35386e8c37d22f07d6a751cb659b180d5274"}, + {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:daf3cb43b7cf2ba96d614252ce1684c1bccee6b2183a01328c98d36fcd7d5cb0"}, + {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99bf650dc5d69546e076f413a87481ee1d2d09aaaaaca058c9251b6d8c14783f"}, + {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dd6e660effd852586b6a8478a1d244b8dc90ab5b1321751d2ea15deb49ed414"}, + {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3391d1e16e2a5a1507d83e4a8b100f4ee626e8eca43cf2cadb543de69827c4c"}, + {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e1f145462f1fa6e4a4ae3c0f782e580ce44d57c8f2c7aae1b6fa88c0b2efdb41"}, + {file = "greenlet-3.0.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1a7191e42732df52cb5f39d3527217e7ab73cae2cb3694d241e18f53d84ea9a7"}, + {file = "greenlet-3.0.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0448abc479fab28b00cb472d278828b3ccca164531daab4e970a0458786055d6"}, + {file = "greenlet-3.0.3-cp37-cp37m-win32.whl", hash = "sha256:b542be2440edc2d48547b5923c408cbe0fc94afb9f18741faa6ae970dbcb9b6d"}, + {file = "greenlet-3.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:01bc7ea167cf943b4c802068e178bbf70ae2e8c080467070d01bfa02f337ee67"}, + {file = "greenlet-3.0.3-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:1996cb9306c8595335bb157d133daf5cf9f693ef413e7673cb07e3e5871379ca"}, + {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ddc0f794e6ad661e321caa8d2f0a55ce01213c74722587256fb6566049a8b04"}, + {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9db1c18f0eaad2f804728c67d6c610778456e3e1cc4ab4bbd5eeb8e6053c6fc"}, + {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7170375bcc99f1a2fbd9c306f5be8764eaf3ac6b5cb968862cad4c7057756506"}, + {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b66c9c1e7ccabad3a7d037b2bcb740122a7b17a53734b7d72a344ce39882a1b"}, + {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:098d86f528c855ead3479afe84b49242e174ed262456c342d70fc7f972bc13c4"}, + {file = "greenlet-3.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:81bb9c6d52e8321f09c3d165b2a78c680506d9af285bfccbad9fb7ad5a5da3e5"}, + {file = "greenlet-3.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fd096eb7ffef17c456cfa587523c5f92321ae02427ff955bebe9e3c63bc9f0da"}, + {file = "greenlet-3.0.3-cp38-cp38-win32.whl", hash = "sha256:d46677c85c5ba00a9cb6f7a00b2bfa6f812192d2c9f7d9c4f6a55b60216712f3"}, + {file = "greenlet-3.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:419b386f84949bf0e7c73e6032e3457b82a787c1ab4a0e43732898a761cc9dbf"}, + {file = "greenlet-3.0.3-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:da70d4d51c8b306bb7a031d5cff6cc25ad253affe89b70352af5f1cb68e74b53"}, + {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086152f8fbc5955df88382e8a75984e2bb1c892ad2e3c80a2508954e52295257"}, + {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d73a9fe764d77f87f8ec26a0c85144d6a951a6c438dfe50487df5595c6373eac"}, + {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7dcbe92cc99f08c8dd11f930de4d99ef756c3591a5377d1d9cd7dd5e896da71"}, + {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1551a8195c0d4a68fac7a4325efac0d541b48def35feb49d803674ac32582f61"}, + {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:64d7675ad83578e3fc149b617a444fab8efdafc9385471f868eb5ff83e446b8b"}, + {file = "greenlet-3.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b37eef18ea55f2ffd8f00ff8fe7c8d3818abd3e25fb73fae2ca3b672e333a7a6"}, + {file = "greenlet-3.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:77457465d89b8263bca14759d7c1684df840b6811b2499838cc5b040a8b5b113"}, + {file = "greenlet-3.0.3-cp39-cp39-win32.whl", hash = "sha256:57e8974f23e47dac22b83436bdcf23080ade568ce77df33159e019d161ce1d1e"}, + {file = "greenlet-3.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:c5ee858cfe08f34712f548c3c363e807e7186f03ad7a5039ebadb29e8c6be067"}, + {file = "greenlet-3.0.3.tar.gz", hash = "sha256:43374442353259554ce33599da8b692d5aa96f8976d567d4badf263371fbe491"}, +] + +[package.extras] +docs = ["Sphinx", "furo"] +test = ["objgraph", "psutil"] + +[[package]] +name = "grpcio" +version = "1.62.1" +description = "HTTP/2-based RPC framework" +optional = false +python-versions = ">=3.7" +files = [ + {file = "grpcio-1.62.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:179bee6f5ed7b5f618844f760b6acf7e910988de77a4f75b95bbfaa8106f3c1e"}, + {file = "grpcio-1.62.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:48611e4fa010e823ba2de8fd3f77c1322dd60cb0d180dc6630a7e157b205f7ea"}, + {file = "grpcio-1.62.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:b2a0e71b0a2158aa4bce48be9f8f9eb45cbd17c78c7443616d00abbe2a509f6d"}, + {file = "grpcio-1.62.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fbe80577c7880911d3ad65e5ecc997416c98f354efeba2f8d0f9112a67ed65a5"}, + {file = "grpcio-1.62.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58f6c693d446964e3292425e1d16e21a97a48ba9172f2d0df9d7b640acb99243"}, + {file = "grpcio-1.62.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:77c339403db5a20ef4fed02e4d1a9a3d9866bf9c0afc77a42234677313ea22f3"}, + {file = "grpcio-1.62.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b5a4ea906db7dec694098435d84bf2854fe158eb3cd51e1107e571246d4d1d70"}, + {file = "grpcio-1.62.1-cp310-cp310-win32.whl", hash = "sha256:4187201a53f8561c015bc745b81a1b2d278967b8de35f3399b84b0695e281d5f"}, + {file = "grpcio-1.62.1-cp310-cp310-win_amd64.whl", hash = "sha256:844d1f3fb11bd1ed362d3fdc495d0770cfab75761836193af166fee113421d66"}, + {file = "grpcio-1.62.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:833379943d1728a005e44103f17ecd73d058d37d95783eb8f0b28ddc1f54d7b2"}, + {file = "grpcio-1.62.1-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:c7fcc6a32e7b7b58f5a7d27530669337a5d587d4066060bcb9dee7a8c833dfb7"}, + {file = "grpcio-1.62.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:fa7d28eb4d50b7cbe75bb8b45ed0da9a1dc5b219a0af59449676a29c2eed9698"}, + {file = "grpcio-1.62.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48f7135c3de2f298b833be8b4ae20cafe37091634e91f61f5a7eb3d61ec6f660"}, + {file = "grpcio-1.62.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:71f11fd63365ade276c9d4a7b7df5c136f9030e3457107e1791b3737a9b9ed6a"}, + {file = "grpcio-1.62.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4b49fd8fe9f9ac23b78437da94c54aa7e9996fbb220bac024a67469ce5d0825f"}, + {file = "grpcio-1.62.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:482ae2ae78679ba9ed5752099b32e5fe580443b4f798e1b71df412abf43375db"}, + {file = "grpcio-1.62.1-cp311-cp311-win32.whl", hash = "sha256:1faa02530b6c7426404372515fe5ddf66e199c2ee613f88f025c6f3bd816450c"}, + {file = "grpcio-1.62.1-cp311-cp311-win_amd64.whl", hash = "sha256:5bd90b8c395f39bc82a5fb32a0173e220e3f401ff697840f4003e15b96d1befc"}, + {file = "grpcio-1.62.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:b134d5d71b4e0837fff574c00e49176051a1c532d26c052a1e43231f252d813b"}, + {file = "grpcio-1.62.1-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:d1f6c96573dc09d50dbcbd91dbf71d5cf97640c9427c32584010fbbd4c0e0037"}, + {file = "grpcio-1.62.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:359f821d4578f80f41909b9ee9b76fb249a21035a061a327f91c953493782c31"}, + {file = "grpcio-1.62.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a485f0c2010c696be269184bdb5ae72781344cb4e60db976c59d84dd6354fac9"}, + {file = "grpcio-1.62.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b50b09b4dc01767163d67e1532f948264167cd27f49e9377e3556c3cba1268e1"}, + {file = "grpcio-1.62.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3227c667dccbe38f2c4d943238b887bac588d97c104815aecc62d2fd976e014b"}, + {file = "grpcio-1.62.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3952b581eb121324853ce2b191dae08badb75cd493cb4e0243368aa9e61cfd41"}, + {file = "grpcio-1.62.1-cp312-cp312-win32.whl", hash = "sha256:83a17b303425104d6329c10eb34bba186ffa67161e63fa6cdae7776ff76df73f"}, + {file = "grpcio-1.62.1-cp312-cp312-win_amd64.whl", hash = "sha256:6696ffe440333a19d8d128e88d440f91fb92c75a80ce4b44d55800e656a3ef1d"}, + {file = "grpcio-1.62.1-cp37-cp37m-linux_armv7l.whl", hash = "sha256:e3393b0823f938253370ebef033c9fd23d27f3eae8eb9a8f6264900c7ea3fb5a"}, + {file = "grpcio-1.62.1-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:83e7ccb85a74beaeae2634f10eb858a0ed1a63081172649ff4261f929bacfd22"}, + {file = "grpcio-1.62.1-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:882020c87999d54667a284c7ddf065b359bd00251fcd70279ac486776dbf84ec"}, + {file = "grpcio-1.62.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a10383035e864f386fe096fed5c47d27a2bf7173c56a6e26cffaaa5a361addb1"}, + {file = "grpcio-1.62.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:960edebedc6b9ada1ef58e1c71156f28689978188cd8cff3b646b57288a927d9"}, + {file = "grpcio-1.62.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:23e2e04b83f347d0aadde0c9b616f4726c3d76db04b438fd3904b289a725267f"}, + {file = "grpcio-1.62.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:978121758711916d34fe57c1f75b79cdfc73952f1481bb9583399331682d36f7"}, + {file = "grpcio-1.62.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9084086190cc6d628f282e5615f987288b95457292e969b9205e45b442276407"}, + {file = "grpcio-1.62.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:22bccdd7b23c420a27fd28540fb5dcbc97dc6be105f7698cb0e7d7a420d0e362"}, + {file = "grpcio-1.62.1-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:8999bf1b57172dbc7c3e4bb3c732658e918f5c333b2942243f10d0d653953ba9"}, + {file = "grpcio-1.62.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:d9e52558b8b8c2f4ac05ac86344a7417ccdd2b460a59616de49eb6933b07a0bd"}, + {file = "grpcio-1.62.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1714e7bc935780bc3de1b3fcbc7674209adf5208ff825799d579ffd6cd0bd505"}, + {file = "grpcio-1.62.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8842ccbd8c0e253c1f189088228f9b433f7a93b7196b9e5b6f87dba393f5d5d"}, + {file = "grpcio-1.62.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1f1e7b36bdff50103af95a80923bf1853f6823dd62f2d2a2524b66ed74103e49"}, + {file = "grpcio-1.62.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bba97b8e8883a8038606480d6b6772289f4c907f6ba780fa1f7b7da7dfd76f06"}, + {file = "grpcio-1.62.1-cp38-cp38-win32.whl", hash = "sha256:a7f615270fe534548112a74e790cd9d4f5509d744dd718cd442bf016626c22e4"}, + {file = "grpcio-1.62.1-cp38-cp38-win_amd64.whl", hash = "sha256:e6c8c8693df718c5ecbc7babb12c69a4e3677fd11de8886f05ab22d4e6b1c43b"}, + {file = "grpcio-1.62.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:73db2dc1b201d20ab7083e7041946910bb991e7e9761a0394bbc3c2632326483"}, + {file = "grpcio-1.62.1-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:407b26b7f7bbd4f4751dbc9767a1f0716f9fe72d3d7e96bb3ccfc4aace07c8de"}, + {file = "grpcio-1.62.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:f8de7c8cef9261a2d0a62edf2ccea3d741a523c6b8a6477a340a1f2e417658de"}, + {file = "grpcio-1.62.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd5c8a1af40ec305d001c60236308a67e25419003e9bb3ebfab5695a8d0b369"}, + {file = "grpcio-1.62.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be0477cb31da67846a33b1a75c611f88bfbcd427fe17701b6317aefceee1b96f"}, + {file = "grpcio-1.62.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:60dcd824df166ba266ee0cfaf35a31406cd16ef602b49f5d4dfb21f014b0dedd"}, + {file = "grpcio-1.62.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:973c49086cabab773525f6077f95e5a993bfc03ba8fc32e32f2c279497780585"}, + {file = "grpcio-1.62.1-cp39-cp39-win32.whl", hash = "sha256:12859468e8918d3bd243d213cd6fd6ab07208195dc140763c00dfe901ce1e1b4"}, + {file = "grpcio-1.62.1-cp39-cp39-win_amd64.whl", hash = "sha256:b7209117bbeebdfa5d898205cc55153a51285757902dd73c47de498ad4d11332"}, + {file = "grpcio-1.62.1.tar.gz", hash = "sha256:6c455e008fa86d9e9a9d85bb76da4277c0d7d9668a3bfa70dbe86e9f3c759947"}, +] + +[package.extras] +protobuf = ["grpcio-tools (>=1.62.1)"] + +[[package]] +name = "gunicorn" +version = "21.2.0" +description = "WSGI HTTP Server for UNIX" +optional = false +python-versions = ">=3.5" +files = [ + {file = "gunicorn-21.2.0-py3-none-any.whl", hash = "sha256:3213aa5e8c24949e792bcacfc176fef362e7aac80b76c56f6b5122bf350722f0"}, + {file = "gunicorn-21.2.0.tar.gz", hash = "sha256:88ec8bff1d634f98e61b9f65bc4bf3cd918a90806c6f5c48bc5603849ec81033"}, +] + +[package.dependencies] +packaging = "*" + +[package.extras] +eventlet = ["eventlet (>=0.24.1)"] +gevent = ["gevent (>=1.4.0)"] +setproctitle = ["setproctitle"] +tornado = ["tornado (>=0.2)"] + +[[package]] +name = "h11" +version = "0.14.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +optional = false +python-versions = ">=3.7" +files = [ + {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, + {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, +] + +[[package]] +name = "h2" +version = "4.1.0" +description = "HTTP/2 State-Machine based protocol implementation" +optional = false +python-versions = ">=3.6.1" +files = [ + {file = "h2-4.1.0-py3-none-any.whl", hash = "sha256:03a46bcf682256c95b5fd9e9a99c1323584c3eec6440d379b9903d709476bc6d"}, + {file = "h2-4.1.0.tar.gz", hash = "sha256:a83aca08fbe7aacb79fec788c9c0bac936343560ed9ec18b82a13a12c28d2abb"}, +] + +[package.dependencies] +hpack = ">=4.0,<5" +hyperframe = ">=6.0,<7" + +[[package]] +name = "hpack" +version = "4.0.0" +description = "Pure-Python HPACK header compression" +optional = false +python-versions = ">=3.6.1" +files = [ + {file = "hpack-4.0.0-py3-none-any.whl", hash = "sha256:84a076fad3dc9a9f8063ccb8041ef100867b1878b25ef0ee63847a5d53818a6c"}, + {file = "hpack-4.0.0.tar.gz", hash = "sha256:fc41de0c63e687ebffde81187a948221294896f6bdc0ae2312708df339430095"}, +] + +[[package]] +name = "httpcore" +version = "1.0.5" +description = "A minimal low-level HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"}, + {file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"}, +] + +[package.dependencies] +certifi = "*" +h11 = ">=0.13,<0.15" + +[package.extras] +asyncio = ["anyio (>=4.0,<5.0)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +trio = ["trio (>=0.22.0,<0.26.0)"] + +[[package]] +name = "httptools" +version = "0.6.1" +description = "A collection of framework independent HTTP protocol utils." +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "httptools-0.6.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d2f6c3c4cb1948d912538217838f6e9960bc4a521d7f9b323b3da579cd14532f"}, + {file = "httptools-0.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:00d5d4b68a717765b1fabfd9ca755bd12bf44105eeb806c03d1962acd9b8e563"}, + {file = "httptools-0.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:639dc4f381a870c9ec860ce5c45921db50205a37cc3334e756269736ff0aac58"}, + {file = "httptools-0.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e57997ac7fb7ee43140cc03664de5f268813a481dff6245e0075925adc6aa185"}, + {file = "httptools-0.6.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0ac5a0ae3d9f4fe004318d64b8a854edd85ab76cffbf7ef5e32920faef62f142"}, + {file = "httptools-0.6.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3f30d3ce413088a98b9db71c60a6ada2001a08945cb42dd65a9a9fe228627658"}, + {file = "httptools-0.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:1ed99a373e327f0107cb513b61820102ee4f3675656a37a50083eda05dc9541b"}, + {file = "httptools-0.6.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7a7ea483c1a4485c71cb5f38be9db078f8b0e8b4c4dc0210f531cdd2ddac1ef1"}, + {file = "httptools-0.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:85ed077c995e942b6f1b07583e4eb0a8d324d418954fc6af913d36db7c05a5a0"}, + {file = "httptools-0.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b0bb634338334385351a1600a73e558ce619af390c2b38386206ac6a27fecfc"}, + {file = "httptools-0.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d9ceb2c957320def533671fc9c715a80c47025139c8d1f3797477decbc6edd2"}, + {file = "httptools-0.6.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4f0f8271c0a4db459f9dc807acd0eadd4839934a4b9b892f6f160e94da309837"}, + {file = "httptools-0.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6a4f5ccead6d18ec072ac0b84420e95d27c1cdf5c9f1bc8fbd8daf86bd94f43d"}, + {file = "httptools-0.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:5cceac09f164bcba55c0500a18fe3c47df29b62353198e4f37bbcc5d591172c3"}, + {file = "httptools-0.6.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:75c8022dca7935cba14741a42744eee13ba05db00b27a4b940f0d646bd4d56d0"}, + {file = "httptools-0.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:48ed8129cd9a0d62cf4d1575fcf90fb37e3ff7d5654d3a5814eb3d55f36478c2"}, + {file = "httptools-0.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f58e335a1402fb5a650e271e8c2d03cfa7cea46ae124649346d17bd30d59c90"}, + {file = "httptools-0.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93ad80d7176aa5788902f207a4e79885f0576134695dfb0fefc15b7a4648d503"}, + {file = "httptools-0.6.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9bb68d3a085c2174c2477eb3ffe84ae9fb4fde8792edb7bcd09a1d8467e30a84"}, + {file = "httptools-0.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b512aa728bc02354e5ac086ce76c3ce635b62f5fbc32ab7082b5e582d27867bb"}, + {file = "httptools-0.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:97662ce7fb196c785344d00d638fc9ad69e18ee4bfb4000b35a52efe5adcc949"}, + {file = "httptools-0.6.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8e216a038d2d52ea13fdd9b9c9c7459fb80d78302b257828285eca1c773b99b3"}, + {file = "httptools-0.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3e802e0b2378ade99cd666b5bffb8b2a7cc8f3d28988685dc300469ea8dd86cb"}, + {file = "httptools-0.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bd3e488b447046e386a30f07af05f9b38d3d368d1f7b4d8f7e10af85393db97"}, + {file = "httptools-0.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe467eb086d80217b7584e61313ebadc8d187a4d95bb62031b7bab4b205c3ba3"}, + {file = "httptools-0.6.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3c3b214ce057c54675b00108ac42bacf2ab8f85c58e3f324a4e963bbc46424f4"}, + {file = "httptools-0.6.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8ae5b97f690badd2ca27cbf668494ee1b6d34cf1c464271ef7bfa9ca6b83ffaf"}, + {file = "httptools-0.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:405784577ba6540fa7d6ff49e37daf104e04f4b4ff2d1ac0469eaa6a20fde084"}, + {file = "httptools-0.6.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:95fb92dd3649f9cb139e9c56604cc2d7c7bf0fc2e7c8d7fbd58f96e35eddd2a3"}, + {file = "httptools-0.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dcbab042cc3ef272adc11220517278519adf8f53fd3056d0e68f0a6f891ba94e"}, + {file = "httptools-0.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cf2372e98406efb42e93bfe10f2948e467edfd792b015f1b4ecd897903d3e8d"}, + {file = "httptools-0.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:678fcbae74477a17d103b7cae78b74800d795d702083867ce160fc202104d0da"}, + {file = "httptools-0.6.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e0b281cf5a125c35f7f6722b65d8542d2e57331be573e9e88bc8b0115c4a7a81"}, + {file = "httptools-0.6.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:95658c342529bba4e1d3d2b1a874db16c7cca435e8827422154c9da76ac4e13a"}, + {file = "httptools-0.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:7ebaec1bf683e4bf5e9fbb49b8cc36da482033596a415b3e4ebab5a4c0d7ec5e"}, + {file = "httptools-0.6.1.tar.gz", hash = "sha256:c6e26c30455600b95d94b1b836085138e82f177351454ee841c148f93a9bad5a"}, +] + +[package.extras] +test = ["Cython (>=0.29.24,<0.30.0)"] + +[[package]] +name = "httpx" +version = "0.27.0" +description = "The next generation HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5"}, + {file = "httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5"}, +] + +[package.dependencies] +anyio = "*" +certifi = "*" +h2 = {version = ">=3,<5", optional = true, markers = "extra == \"http2\""} +httpcore = "==1.*" +idna = "*" +sniffio = "*" + +[package.extras] +brotli = ["brotli", "brotlicffi"] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] + +[[package]] +name = "huggingface-hub" +version = "0.22.2" +description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "huggingface_hub-0.22.2-py3-none-any.whl", hash = "sha256:3429e25f38ccb834d310804a3b711e7e4953db5a9e420cc147a5e194ca90fd17"}, + {file = "huggingface_hub-0.22.2.tar.gz", hash = "sha256:32e9a9a6843c92f253ff9ca16b9985def4d80a93fb357af5353f770ef74a81be"}, +] + +[package.dependencies] +filelock = "*" +fsspec = ">=2023.5.0" +packaging = ">=20.9" +pyyaml = ">=5.1" +requests = "*" +tqdm = ">=4.42.1" +typing-extensions = ">=3.7.4.3" + +[package.extras] +all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "minijinja (>=1.0)", "mypy (==1.5.1)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.3.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] +cli = ["InquirerPy (==0.3.4)"] +dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "minijinja (>=1.0)", "mypy (==1.5.1)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.3.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] +fastai = ["fastai (>=2.4)", "fastcore (>=1.3.27)", "toml"] +hf-transfer = ["hf-transfer (>=0.1.4)"] +inference = ["aiohttp", "minijinja (>=1.0)"] +quality = ["mypy (==1.5.1)", "ruff (>=0.3.0)"] +tensorflow = ["graphviz", "pydot", "tensorflow"] +tensorflow-testing = ["keras (<3.0)", "tensorflow"] +testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "minijinja (>=1.0)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "soundfile", "urllib3 (<2.0)"] +torch = ["safetensors", "torch"] +typing = ["types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)"] + +[[package]] +name = "humanfriendly" +version = "10.0" +description = "Human friendly output for text interfaces using Python" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "humanfriendly-10.0-py2.py3-none-any.whl", hash = "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477"}, + {file = "humanfriendly-10.0.tar.gz", hash = "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc"}, +] + +[package.dependencies] +pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_version >= \"3.8\""} + +[[package]] +name = "hyperframe" +version = "6.0.1" +description = "HTTP/2 framing layer for Python" +optional = false +python-versions = ">=3.6.1" +files = [ + {file = "hyperframe-6.0.1-py3-none-any.whl", hash = "sha256:0ec6bafd80d8ad2195c4f03aacba3a8265e57bc4cff261e802bf39970ed02a15"}, + {file = "hyperframe-6.0.1.tar.gz", hash = "sha256:ae510046231dc8e9ecb1a6586f63d2347bf4c8905914aa84ba585ae85f28a914"}, +] + +[[package]] +name = "idna" +version = "3.6" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, + {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, +] + +[[package]] +name = "importlib-metadata" +version = "7.0.0" +description = "Read metadata from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_metadata-7.0.0-py3-none-any.whl", hash = "sha256:d97503976bb81f40a193d41ee6570868479c69d5068651eb039c40d850c59d67"}, + {file = "importlib_metadata-7.0.0.tar.gz", hash = "sha256:7fc841f8b8332803464e5dc1c63a2e59121f46ca186c0e2e182e80bf8c1319f7"}, +] + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +perf = ["ipython"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] + +[[package]] +name = "importlib-resources" +version = "6.4.0" +description = "Read resources from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_resources-6.4.0-py3-none-any.whl", hash = "sha256:50d10f043df931902d4194ea07ec57960f66a80449ff867bfe782b4c486ba78c"}, + {file = "importlib_resources-6.4.0.tar.gz", hash = "sha256:cdb2b453b8046ca4e3798eb1d84f3cce1446a0e8e7b5ef4efb600f19fc398145"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["jaraco.test (>=5.4)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-ruff (>=0.2.1)", "zipp (>=3.17)"] + +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + +[[package]] +name = "ipykernel" +version = "6.29.4" +description = "IPython Kernel for Jupyter" +optional = false +python-versions = ">=3.8" +files = [ + {file = "ipykernel-6.29.4-py3-none-any.whl", hash = "sha256:1181e653d95c6808039c509ef8e67c4126b3b3af7781496c7cbfb5ed938a27da"}, + {file = "ipykernel-6.29.4.tar.gz", hash = "sha256:3d44070060f9475ac2092b760123fadf105d2e2493c24848b6691a7c4f42af5c"}, +] + +[package.dependencies] +appnope = {version = "*", markers = "platform_system == \"Darwin\""} +comm = ">=0.1.1" +debugpy = ">=1.6.5" +ipython = ">=7.23.1" +jupyter-client = ">=6.1.12" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +matplotlib-inline = ">=0.1" +nest-asyncio = "*" +packaging = "*" +psutil = "*" +pyzmq = ">=24" +tornado = ">=6.1" +traitlets = ">=5.4.0" + +[package.extras] +cov = ["coverage[toml]", "curio", "matplotlib", "pytest-cov", "trio"] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "trio"] +pyqt5 = ["pyqt5"] +pyside6 = ["pyside6"] +test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (>=0.23.5)", "pytest-cov", "pytest-timeout"] + +[[package]] +name = "ipython" +version = "8.23.0" +description = "IPython: Productive Interactive Computing" +optional = false +python-versions = ">=3.10" +files = [ + {file = "ipython-8.23.0-py3-none-any.whl", hash = "sha256:07232af52a5ba146dc3372c7bf52a0f890a23edf38d77caef8d53f9cdc2584c1"}, + {file = "ipython-8.23.0.tar.gz", hash = "sha256:7468edaf4f6de3e1b912e57f66c241e6fd3c7099f2ec2136e239e142e800274d"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +decorator = "*" +exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} +jedi = ">=0.16" +matplotlib-inline = "*" +pexpect = {version = ">4.3", markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\""} +prompt-toolkit = ">=3.0.41,<3.1.0" +pygments = ">=2.4.0" +stack-data = "*" +traitlets = ">=5.13.0" +typing-extensions = {version = "*", markers = "python_version < \"3.12\""} + +[package.extras] +all = ["ipython[black,doc,kernel,matplotlib,nbconvert,nbformat,notebook,parallel,qtconsole]", "ipython[test,test-extra]"] +black = ["black"] +doc = ["docrepr", "exceptiongroup", "ipykernel", "ipython[test]", "matplotlib", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "sphinxcontrib-jquery", "stack-data", "typing-extensions"] +kernel = ["ipykernel"] +matplotlib = ["matplotlib"] +nbconvert = ["nbconvert"] +nbformat = ["nbformat"] +notebook = ["ipywidgets", "notebook"] +parallel = ["ipyparallel"] +qtconsole = ["qtconsole"] +test = ["pickleshare", "pytest (<8)", "pytest-asyncio (<0.22)", "testpath"] +test-extra = ["curio", "ipython[test]", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.23)", "pandas", "trio"] + +[[package]] +name = "itsdangerous" +version = "2.1.2" +description = "Safely pass data to untrusted environments and back." +optional = false +python-versions = ">=3.7" +files = [ + {file = "itsdangerous-2.1.2-py3-none-any.whl", hash = "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44"}, + {file = "itsdangerous-2.1.2.tar.gz", hash = "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"}, +] + +[[package]] +name = "jedi" +version = "0.19.1" +description = "An autocompletion tool for Python that can be used for text editors." +optional = false +python-versions = ">=3.6" +files = [ + {file = "jedi-0.19.1-py2.py3-none-any.whl", hash = "sha256:e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0"}, + {file = "jedi-0.19.1.tar.gz", hash = "sha256:cf0496f3651bc65d7174ac1b7d043eff454892c708a87d1b683e57b569927ffd"}, +] + +[package.dependencies] +parso = ">=0.8.3,<0.9.0" + +[package.extras] +docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"] +qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] +testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] + +[[package]] +name = "jinja2" +version = "3.1.3" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"}, + {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "jq" +version = "1.7.0" +description = "jq is a lightweight and flexible JSON processor." +optional = false +python-versions = ">=3.5" +files = [ + {file = "jq-1.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d8fae014fa8b2704322a5baa39c112176d9acb71e22ebdb8e21c1c864ecff654"}, + {file = "jq-1.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:40fe068d1fdf2c712885b69be90ddb3e61bca3e4346ab3994641a4fbbeb7be82"}, + {file = "jq-1.7.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8ec105a0057f2f922d195e1d75d4b0ae41c4b38655ead04d1a3a47988fcb1939"}, + {file = "jq-1.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38e2041ca578275334eff9e1d913ae386210345e5ae71cd9c16e3f208dc81deb"}, + {file = "jq-1.7.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce1df1b6fffeeeb265d4ea3397e9875ab170ba5a7af6b7997c2fd755934df065"}, + {file = "jq-1.7.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:05ebdaa868f068967d9e7cbf76e59e61fbdafa565dbc3579c387fb1f248592bb"}, + {file = "jq-1.7.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:b3f916cb812fcd26bb1b006634d9c0eff240090196ca0ebb5d229b344f624e53"}, + {file = "jq-1.7.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9ad7749a16a16bafd6cebafd5e40990b641b4b6b7b661326864677effc44a500"}, + {file = "jq-1.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2e99ea17b708f55e8bed2f4f68c022119184b17eb15987b384db12e8b6702bd5"}, + {file = "jq-1.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:76735cd19de65c15964d330adbc2c84add8e55dea35ebfe17b9acf88a06a7d57"}, + {file = "jq-1.7.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6b841ddd9089429fc0621d07d1c34ff24f7d6a6245c10125b82806f61e36ae8"}, + {file = "jq-1.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d6b1fc2515b7be92195d50b68f82329cc0250c7fbca790b887d74902ba33870"}, + {file = "jq-1.7.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb6546a57a3ceeed41961be2f1417b4e7a5b3170cca7bb82f5974d2ba9acaab6"}, + {file = "jq-1.7.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3427ad0f377f188953958e36b76167c8d11b8c8c61575c22deafa4aba58d601f"}, + {file = "jq-1.7.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:79b9603219fa5082df97d265d71c426613286bd0e5378a8739ce39056fa1e2dc"}, + {file = "jq-1.7.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a2981a24765a747163e0daa23648372b72a006e727895b95d032632aa51094bd"}, + {file = "jq-1.7.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a0cc15b2ed511a1a8784c7c7dc07781e28d84a65934062de52487578732e0514"}, + {file = "jq-1.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:90032c2c4e710157d333d166818ede8b9c8ef0f697e59c9427304edc47146f3d"}, + {file = "jq-1.7.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e715d5f0bdfc0be0ff33cd0a3f6f51f8bc5ad464fab737e2048a1b46b45bb582"}, + {file = "jq-1.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76cc5a1ca3a540a5753dbd592f701c1ec7c9cc256becba604490283c055f3f1c"}, + {file = "jq-1.7.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:293b6e8e4b652d96fdeae7dd5ffb1644199d8b6fc1f95d528c16451925c0482e"}, + {file = "jq-1.7.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f103868b8902d4ee7f643248bdd7a2de9f9396e4b262f42745b9f624c834d07a"}, + {file = "jq-1.7.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e9c5ccfa3cf65f92b60c5805ef725f7cd799f2dc16e8601c6e8f12f38a9f48f3"}, + {file = "jq-1.7.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0ca25608d51fdbf8bd5c682b433e1cb9f497155a7c1ea5901524df099f1ceff3"}, + {file = "jq-1.7.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6a2d34d962ce2da5136dab2664fc7efad9f71024d0dc328702f2dc70b4e2735c"}, + {file = "jq-1.7.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:757e8c4cb0cb1175f0aaa227f0a26e4765ba5da04d0bc875b0bd933eff6bd0a0"}, + {file = "jq-1.7.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d097098a628171b87961fb0400117ac340b1eb40cbbee2e58208c4254c23c20"}, + {file = "jq-1.7.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:45bc842806d71bd5839c190a88fd071ac5a0a8a1dd601e83228494a19f14559c"}, + {file = "jq-1.7.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:f0629743417f8709305d1f77d3929493912efdc3fd1cce3a7fcc76b81bc6b82d"}, + {file = "jq-1.7.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:9b9a49e8b14d3a368011ed1412c8c3e193a7135d5eb4310d77ee643470112b47"}, + {file = "jq-1.7.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:a10e3f88b6d2bbb4c47b368f919ec7b648196bf9c60a5cc921d04239d68240c2"}, + {file = "jq-1.7.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:aa85b47effb4152e1cf1120607f475a1c11395d072323ff23e8bb59ce6752713"}, + {file = "jq-1.7.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9413f67ea28037e37ccf8951f9f0b380f31d79162f33e216faa6bd0d8eca0dc7"}, + {file = "jq-1.7.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3daf3b3443c4e871c23ac1e698eb70d1225b46a4ac79c73968234adcd70f3ed8"}, + {file = "jq-1.7.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbe03f95ab02dc045691c3b5c7da8d8c2128e60450fb2124ea8b49034c74f158"}, + {file = "jq-1.7.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:a6b2e9f4e63644a30726c58c25d80015f9b83325b125615a46e10d4439b9dc99"}, + {file = "jq-1.7.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9fffcffc8e56585223878edd7c5d719eb8547281d64af2bac43911f1bb9e7029"}, + {file = "jq-1.7.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:95d4bcd5a999ce0aaadaadcaca967989f0efc96c1097a81746b21b6126cf7aaf"}, + {file = "jq-1.7.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0137445eb67c43eb0eb46933aff7e8afbbd6c5aaf8574efd5df536dc9d177d1d"}, + {file = "jq-1.7.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ee0e9307b6d4fe89a8556a92c1db65e0d66218bcc13fdeb92a09645a55ff87a"}, + {file = "jq-1.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e0f95cecb690df66f23a8d76c746d2ed15671de3f6101140e3fe2b98b97e0a8"}, + {file = "jq-1.7.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:95e472aa54efe418d3627dcd2a369ac0b21e1a5e352550144fd5f0c40585a5b7"}, + {file = "jq-1.7.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4be2a2b56fa139f3235cdb8422ea16eccdd48d62bf91d9fac10761cd55d26c84"}, + {file = "jq-1.7.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7db8260ecb57827bb3fb6f44d4a6f0db0570ded990eee95a5fd3ac9ba14f60d7"}, + {file = "jq-1.7.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fdbb7ff2dfce2cc0f421f498dcb64176997bd9d9e6cab474e59577e7bff3090d"}, + {file = "jq-1.7.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:396bef4b4c9c1ebe3e0e04e287bc79a861b991e12db45681c398d3906ee85468"}, + {file = "jq-1.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:18d8a81c6e241585a0bf748903082d65c4eaa6ba80248f507e5cebda36e05c6c"}, + {file = "jq-1.7.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ade00a39990fdfe0acc7d2a900e3e5e6b11a71eb5289954ff0df31ac0afae25b"}, + {file = "jq-1.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c777e88f3cce496c17f5c3bdbc7d74ff12b5cbdaea30f3a374f3cc92e5bba8d"}, + {file = "jq-1.7.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:79957008c67d8f1d9134cd0e01044bff5d795f7e94db9532a9fe9212e1f88a77"}, + {file = "jq-1.7.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2bc5cb77dd12e861296cfa69587aa6797ccfee4f5f3aa571b02f0273ab1efec1"}, + {file = "jq-1.7.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8e10a5937aab9c383632ab151f73d43dc0c4be99f62221a7044988dc8ddd4bdc"}, + {file = "jq-1.7.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1e6e13e0f8d3204aefe861159160116e822c90bae773a3ccdd4d9e79a06e086e"}, + {file = "jq-1.7.0-pp310-pypy310_pp73-macosx_10_13_x86_64.whl", hash = "sha256:0cdbd32463ef632b0b4ca6dab434e2387342bc5c895b411ec6b2a14bbf4b2c12"}, + {file = "jq-1.7.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:558a5c6b4430e05fa59c4b5631c0d3fc0f163100390c03edc1993663f59d8a9b"}, + {file = "jq-1.7.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bbf77138cdd8d306bf335d998525a0477e4cb6f00eb6f361288f5b82274e84c"}, + {file = "jq-1.7.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2e6919481ff43754ae9b17a98c877995d5e1346be114c71cd0dfd8ff7d0cd60"}, + {file = "jq-1.7.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0b0584ff33b2a9cc021edec325af4e0fa9fbd54cce80c1f7b8e0ba4cf2d75508"}, + {file = "jq-1.7.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a6e7259880ab7e75e845fb4d56c6d18922c68789d25d7cdbb6f433d9e714613a"}, + {file = "jq-1.7.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d472cdd0bcb3d47c87b00ff841edff41c79fe4422523c4a7c8bf913fb950f7f"}, + {file = "jq-1.7.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a3430de179f8a7b0baf5675d5ee400f97344085d79f190a90fc0c7df990cbcc"}, + {file = "jq-1.7.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:acbb375bdb2a44f1a643123b8ec57563bb5542673f0399799ab5662ce90bf4a5"}, + {file = "jq-1.7.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:39a0c71ed2f1ec0462d54678333f1b14d9f25fd62a9f46df140d68552f79d204"}, + {file = "jq-1.7.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:306c1e3ba531d7dc3284e128689f0b75409a4e8e8a3bdac2c51cc26f2d3cca58"}, + {file = "jq-1.7.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88b8b0cc838c7387dc5e8c45b192c7504acd0510514658d2d5cd1716fcf15fe3"}, + {file = "jq-1.7.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c75e16e542f4abaae25727b9fc4eeaf69cb07122be8a2a7672d02feb3a1cc9a"}, + {file = "jq-1.7.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b4828ac689a67fd9c021796bcacd95811bab806939dd6316eb0c2d3de016c584"}, + {file = "jq-1.7.0-pp39-pypy39_pp73-macosx_10_13_x86_64.whl", hash = "sha256:c94f95b27720d2db7f1039fdd371f70bc0cac8e204cbfd0626176d7b8a3053d6"}, + {file = "jq-1.7.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:d5ff445fc9b1eb4623a914e04bea9511e654e9143cde82b039383af4f7dc36f2"}, + {file = "jq-1.7.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07e369ff021fad38a29d6a7a3fc24f7d313e9a239b15ce4eefaffee637466400"}, + {file = "jq-1.7.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:553dfbf674069cb20533d7d74cd8a9d7982bab8e4a5b473fde105d99278df09f"}, + {file = "jq-1.7.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e9fbc76f6fec66e5e58cc84f20a5de80addd3c64ad87a748f5c5f6b4ef01bc8c"}, + {file = "jq-1.7.0.tar.gz", hash = "sha256:f460d1f2c3791617e4fb339fa24efbdbebe672b02c861f057358553642047040"}, +] + +[[package]] +name = "jsonpatch" +version = "1.33" +description = "Apply JSON-Patches (RFC 6902)" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" +files = [ + {file = "jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade"}, + {file = "jsonpatch-1.33.tar.gz", hash = "sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c"}, +] + +[package.dependencies] +jsonpointer = ">=1.9" + +[[package]] +name = "jsonpointer" +version = "2.4" +description = "Identify specific nodes in a JSON document (RFC 6901)" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" +files = [ + {file = "jsonpointer-2.4-py2.py3-none-any.whl", hash = "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a"}, + {file = "jsonpointer-2.4.tar.gz", hash = "sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88"}, +] + +[[package]] +name = "jupyter-client" +version = "8.6.1" +description = "Jupyter protocol implementation and client libraries" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyter_client-8.6.1-py3-none-any.whl", hash = "sha256:3b7bd22f058434e3b9a7ea4b1500ed47de2713872288c0d511d19926f99b459f"}, + {file = "jupyter_client-8.6.1.tar.gz", hash = "sha256:e842515e2bab8e19186d89fdfea7abd15e39dd581f94e399f00e2af5a1652d3f"}, +] + +[package.dependencies] +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +python-dateutil = ">=2.8.2" +pyzmq = ">=23.0" +tornado = ">=6.2" +traitlets = ">=5.3" + +[package.extras] +docs = ["ipykernel", "myst-parser", "pydata-sphinx-theme", "sphinx (>=4)", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] +test = ["coverage", "ipykernel (>=6.14)", "mypy", "paramiko", "pre-commit", "pytest", "pytest-cov", "pytest-jupyter[client] (>=0.4.1)", "pytest-timeout"] + +[[package]] +name = "jupyter-core" +version = "5.7.2" +description = "Jupyter core package. A base package on which Jupyter projects rely." +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyter_core-5.7.2-py3-none-any.whl", hash = "sha256:4f7315d2f6b4bcf2e3e7cb6e46772eba760ae459cd1f59d29eb57b0a01bd7409"}, + {file = "jupyter_core-5.7.2.tar.gz", hash = "sha256:aa5f8d32bbf6b431ac830496da7392035d6f61b4f54872f15c4bd2a9c3f536d9"}, +] + +[package.dependencies] +platformdirs = ">=2.5" +pywin32 = {version = ">=300", markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\""} +traitlets = ">=5.3" + +[package.extras] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "traitlets"] +test = ["ipykernel", "pre-commit", "pytest (<8)", "pytest-cov", "pytest-timeout"] + +[[package]] +name = "kubernetes" +version = "29.0.0" +description = "Kubernetes python client" +optional = false +python-versions = ">=3.6" +files = [ + {file = "kubernetes-29.0.0-py2.py3-none-any.whl", hash = "sha256:ab8cb0e0576ccdfb71886366efb102c6a20f268d817be065ce7f9909c631e43e"}, + {file = "kubernetes-29.0.0.tar.gz", hash = "sha256:c4812e227ae74d07d53c88293e564e54b850452715a59a927e7e1bc6b9a60459"}, +] + +[package.dependencies] +certifi = ">=14.05.14" +google-auth = ">=1.0.1" +oauthlib = ">=3.2.2" +python-dateutil = ">=2.5.3" +pyyaml = ">=5.4.1" +requests = "*" +requests-oauthlib = "*" +six = ">=1.9.0" +urllib3 = ">=1.24.2" +websocket-client = ">=0.32.0,<0.40.0 || >0.40.0,<0.41.dev0 || >=0.43.dev0" + +[package.extras] +adal = ["adal (>=1.0.2)"] + +[[package]] +name = "langchain" +version = "0.1.14" +description = "Building applications with LLMs through composability" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "langchain-0.1.14-py3-none-any.whl", hash = "sha256:94f9b5df2421faaf762d4f43b9d65c270c2f701934580d281e4c6226deef7234"}, + {file = "langchain-0.1.14.tar.gz", hash = "sha256:124c6244cf3957616b98f2df07dc2992fc40dff6ed1a62d8ee8a40f1e0260a40"}, +] + +[package.dependencies] +aiohttp = ">=3.8.3,<4.0.0" +async-timeout = {version = ">=4.0.0,<5.0.0", markers = "python_version < \"3.11\""} +dataclasses-json = ">=0.5.7,<0.7" +jsonpatch = ">=1.33,<2.0" +langchain-community = ">=0.0.30,<0.1" +langchain-core = ">=0.1.37,<0.2.0" +langchain-text-splitters = ">=0.0.1,<0.1" +langsmith = ">=0.1.17,<0.2.0" +numpy = ">=1,<2" +pydantic = ">=1,<3" +PyYAML = ">=5.3" +requests = ">=2,<3" +SQLAlchemy = ">=1.4,<3" +tenacity = ">=8.1.0,<9.0.0" + +[package.extras] +azure = ["azure-ai-formrecognizer (>=3.2.1,<4.0.0)", "azure-ai-textanalytics (>=5.3.0,<6.0.0)", "azure-cognitiveservices-speech (>=1.28.0,<2.0.0)", "azure-core (>=1.26.4,<2.0.0)", "azure-cosmos (>=4.4.0b1,<5.0.0)", "azure-identity (>=1.12.0,<2.0.0)", "azure-search-documents (==11.4.0b8)", "openai (<2)"] +clarifai = ["clarifai (>=9.1.0)"] +cli = ["typer (>=0.9.0,<0.10.0)"] +cohere = ["cohere (>=4,<6)"] +docarray = ["docarray[hnswlib] (>=0.32.0,<0.33.0)"] +embeddings = ["sentence-transformers (>=2,<3)"] +extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cohere (>=4,<6)", "couchbase (>=4.1.9,<5.0.0)", "dashvector (>=1.0.1,<2.0.0)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "langchain-openai (>=0.0.2,<0.1)", "lxml (>=4.9.3,<6.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "upstash-redis (>=0.15.0,<0.16.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"] +javascript = ["esprima (>=4.0.1,<5.0.0)"] +llms = ["clarifai (>=9.1.0)", "cohere (>=4,<6)", "huggingface_hub (>=0,<1)", "manifest-ml (>=0.0.1,<0.0.2)", "nlpcloud (>=1,<2)", "openai (<2)", "openlm (>=0.0.5,<0.0.6)", "torch (>=1,<3)", "transformers (>=4,<5)"] +openai = ["openai (<2)", "tiktoken (>=0.3.2,<0.6.0)"] +qdrant = ["qdrant-client (>=1.3.1,<2.0.0)"] +text-helpers = ["chardet (>=5.1.0,<6.0.0)"] + +[[package]] +name = "langchain-anthropic" +version = "0.1.4" +description = "An integration package connecting AnthropicMessages and LangChain" +optional = false +python-versions = ">=3.8.1,<4.0" +files = [ + {file = "langchain_anthropic-0.1.4-py3-none-any.whl", hash = "sha256:9b3e28c1c0f7a502495b240c6c015d7fc57d04fb381fae389ecdce8847de5777"}, + {file = "langchain_anthropic-0.1.4.tar.gz", hash = "sha256:d772f7111335953d23393cac8173a0a1ee65b5fe0dc137c6b7a6db2a06fbcac4"}, +] + +[package.dependencies] +anthropic = ">=0.17.0,<1" +defusedxml = ">=0.7.1,<0.8.0" +langchain-core = ">=0.1,<0.2" + +[[package]] +name = "langchain-astradb" +version = "0.1.0" +description = "An integration package connecting Astra DB and LangChain" +optional = false +python-versions = ">=3.8.1,<4.0" +files = [ + {file = "langchain_astradb-0.1.0-py3-none-any.whl", hash = "sha256:c6686089da343fce8c31e36c9162323e88888300b09d56b72347a19449d7361f"}, + {file = "langchain_astradb-0.1.0.tar.gz", hash = "sha256:c8a3426c9daa2beeec2dc7a718186b0b9c388082e9543e0bc07363712cc3b947"}, +] + +[package.dependencies] +astrapy = ">=0.7.7,<0.8.0" +langchain-core = ">=0.1.31,<0.2.0" +numpy = ">=1,<2" + +[[package]] +name = "langchain-community" +version = "0.0.31" +description = "Community contributed LangChain integrations." +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "langchain_community-0.0.31-py3-none-any.whl", hash = "sha256:905c01b978a1cef7fdcddd2d9241dedc9987db6f23ba1b58d974e38b1cdf2775"}, + {file = "langchain_community-0.0.31.tar.gz", hash = "sha256:9a970bc2bb59bb4c204b696d8c62c2534f6ddb31005005cc1b7d7f934e58a5fc"}, +] + +[package.dependencies] +aiohttp = ">=3.8.3,<4.0.0" +dataclasses-json = ">=0.5.7,<0.7" +langchain-core = ">=0.1.37,<0.2.0" +langsmith = ">=0.1.0,<0.2.0" +numpy = ">=1,<2" +PyYAML = ">=5.3" +requests = ">=2,<3" +SQLAlchemy = ">=1.4,<3" +tenacity = ">=8.1.0,<9.0.0" + +[package.extras] +cli = ["typer (>=0.9.0,<0.10.0)"] +extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "azure-ai-documentintelligence (>=1.0.0b1,<2.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cloudpickle (>=2.0.0)", "cohere (>=4,<5)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "elasticsearch (>=8.12.0,<9.0.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "friendli-client (>=1.2.4,<2.0.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "gradientai (>=1.4.0,<2.0.0)", "hdbcli (>=2.19.21,<3.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "httpx (>=0.24.1,<0.25.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "lxml (>=4.9.3,<6.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "nvidia-riva-client (>=2.14.0,<3.0.0)", "oci (>=2.119.1,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "oracle-ads (>=2.9.1,<3.0.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "premai (>=0.3.25,<0.4.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "tidb-vector (>=0.0.3,<1.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "tree-sitter (>=0.20.2,<0.21.0)", "tree-sitter-languages (>=1.8.0,<2.0.0)", "upstash-redis (>=0.15.0,<0.16.0)", "vdms (>=0.0.20,<0.0.21)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)", "zhipuai (>=1.0.7,<2.0.0)"] + +[[package]] +name = "langchain-core" +version = "0.1.40" +description = "Building applications with LLMs through composability" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "langchain_core-0.1.40-py3-none-any.whl", hash = "sha256:618dbb7ab44d8b263b91e384db1ff07d0db256ae5bdafa0123a115b6a75a13f1"}, + {file = "langchain_core-0.1.40.tar.gz", hash = "sha256:34c06fc0e6d3534b738c63f85403446b4be71161665b7e091f9bb19c914ec100"}, +] + +[package.dependencies] +jsonpatch = ">=1.33,<2.0" +langsmith = ">=0.1.0,<0.2.0" +packaging = ">=23.2,<24.0" +pydantic = ">=1,<3" +PyYAML = ">=5.3" +tenacity = ">=8.1.0,<9.0.0" + +[package.extras] +extended-testing = ["jinja2 (>=3,<4)"] + +[[package]] +name = "langchain-experimental" +version = "0.0.56" +description = "Building applications with LLMs through composability" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "langchain_experimental-0.0.56-py3-none-any.whl", hash = "sha256:91fd7a723b0ef3193a63726745523efdd5dd7134116d838c312cfdbf4b354298"}, + {file = "langchain_experimental-0.0.56.tar.gz", hash = "sha256:ebb1c34815739d3af50c9b709c57b91d0357d567ad2042acb724853c6ba1d735"}, +] + +[package.dependencies] +langchain = ">=0.1.14,<0.2.0" +langchain-core = ">=0.1.37,<0.2.0" + +[package.extras] +extended-testing = ["faker (>=19.3.1,<20.0.0)", "jinja2 (>=3,<4)", "pandas (>=2.0.1,<3.0.0)", "presidio-analyzer (>=2.2.352,<3.0.0)", "presidio-anonymizer (>=2.2.352,<3.0.0)", "sentence-transformers (>=2,<3)", "tabulate (>=0.9.0,<0.10.0)", "vowpal-wabbit-next (==0.6.0)"] + +[[package]] +name = "langchain-openai" +version = "0.1.1" +description = "An integration package connecting OpenAI and LangChain" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "langchain_openai-0.1.1-py3-none-any.whl", hash = "sha256:5cf4df5d2550af673337eafedaeec014ba52f9a25aeb8451206ca254bed01e5c"}, + {file = "langchain_openai-0.1.1.tar.gz", hash = "sha256:d10e9a9fc4c8ea99ca98f23808ce44c7dcdd65354ac07ad10afe874ecf3401ca"}, +] + +[package.dependencies] +langchain-core = ">=0.1.33,<0.2.0" +openai = ">=1.10.0,<2.0.0" +tiktoken = ">=0.5.2,<1" + +[[package]] +name = "langchain-text-splitters" +version = "0.0.1" +description = "LangChain text splitting utilities" +optional = false +python-versions = ">=3.8.1,<4.0" +files = [ + {file = "langchain_text_splitters-0.0.1-py3-none-any.whl", hash = "sha256:f5b802f873f5ff6a8b9259ff34d53ed989666ef4e1582e6d1adb3b5520e3839a"}, + {file = "langchain_text_splitters-0.0.1.tar.gz", hash = "sha256:ac459fa98799f5117ad5425a9330b21961321e30bc19a2a2f9f761ddadd62aa1"}, +] + +[package.dependencies] +langchain-core = ">=0.1.28,<0.2.0" + +[package.extras] +extended-testing = ["lxml (>=5.1.0,<6.0.0)"] + +[[package]] +name = "langsmith" +version = "0.1.39" +description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "langsmith-0.1.39-py3-none-any.whl", hash = "sha256:85c19177162585728001cb7ae91ab48ca4abe39b7bc1ff783212ac426ded222b"}, + {file = "langsmith-0.1.39.tar.gz", hash = "sha256:2aec9d2f9cc664042d2121b13da569b0902aff842c86b17b440245d57da84ec5"}, +] + +[package.dependencies] +orjson = ">=3.9.14,<4.0.0" +pydantic = ">=1,<3" +requests = ">=2,<3" + +[[package]] +name = "locust" +version = "2.24.1" +description = "Developer friendly load testing framework" +optional = false +python-versions = ">=3.8" +files = [ + {file = "locust-2.24.1-py3-none-any.whl", hash = "sha256:7f6ed4dc289aad66c304582e6d25e4de5d7c3b175b580332442ab2be35b9d916"}, + {file = "locust-2.24.1.tar.gz", hash = "sha256:094161d44d94839bf1120fd7898b7abb9c143833743ba7c096beb470a236b9a7"}, +] + +[package.dependencies] +ConfigArgParse = ">=1.5.5" +flask = ">=2.0.0" +Flask-Cors = ">=3.0.10" +Flask-Login = ">=0.6.3" +gevent = ">=22.10.2" +geventhttpclient = ">=2.0.11" +msgpack = ">=1.0.0" +psutil = ">=5.9.1" +pywin32 = {version = "*", markers = "platform_system == \"Windows\""} +pyzmq = ">=25.0.0" +requests = ">=2.26.0" +roundrobin = ">=0.0.2" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +Werkzeug = ">=2.0.0" + +[[package]] +name = "loguru" +version = "0.7.2" +description = "Python logging made (stupidly) simple" +optional = false +python-versions = ">=3.5" +files = [ + {file = "loguru-0.7.2-py3-none-any.whl", hash = "sha256:003d71e3d3ed35f0f8984898359d65b79e5b21943f78af86aa5491210429b8eb"}, + {file = "loguru-0.7.2.tar.gz", hash = "sha256:e671a53522515f34fd406340ee968cb9ecafbc4b36c679da03c18fd8d0bd51ac"}, +] + +[package.dependencies] +colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} +win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} + +[package.extras] +dev = ["Sphinx (==7.2.5)", "colorama (==0.4.5)", "colorama (==0.4.6)", "exceptiongroup (==1.1.3)", "freezegun (==1.1.0)", "freezegun (==1.2.2)", "mypy (==v0.910)", "mypy (==v0.971)", "mypy (==v1.4.1)", "mypy (==v1.5.1)", "pre-commit (==3.4.0)", "pytest (==6.1.2)", "pytest (==7.4.0)", "pytest-cov (==2.12.1)", "pytest-cov (==4.1.0)", "pytest-mypy-plugins (==1.9.3)", "pytest-mypy-plugins (==3.0.0)", "sphinx-autobuild (==2021.3.14)", "sphinx-rtd-theme (==1.3.0)", "tox (==3.27.1)", "tox (==4.11.0)"] + +[[package]] +name = "lxml" +version = "5.2.1" +description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." +optional = false +python-versions = ">=3.6" +files = [ + {file = "lxml-5.2.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1f7785f4f789fdb522729ae465adcaa099e2a3441519df750ebdccc481d961a1"}, + {file = "lxml-5.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6cc6ee342fb7fa2471bd9b6d6fdfc78925a697bf5c2bcd0a302e98b0d35bfad3"}, + {file = "lxml-5.2.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:794f04eec78f1d0e35d9e0c36cbbb22e42d370dda1609fb03bcd7aeb458c6377"}, + {file = "lxml-5.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c817d420c60a5183953c783b0547d9eb43b7b344a2c46f69513d5952a78cddf3"}, + {file = "lxml-5.2.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2213afee476546a7f37c7a9b4ad4d74b1e112a6fafffc9185d6d21f043128c81"}, + {file = "lxml-5.2.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b070bbe8d3f0f6147689bed981d19bbb33070225373338df755a46893528104a"}, + {file = "lxml-5.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e02c5175f63effbd7c5e590399c118d5db6183bbfe8e0d118bdb5c2d1b48d937"}, + {file = "lxml-5.2.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:3dc773b2861b37b41a6136e0b72a1a44689a9c4c101e0cddb6b854016acc0aa8"}, + {file = "lxml-5.2.1-cp310-cp310-manylinux_2_28_ppc64le.whl", hash = "sha256:d7520db34088c96cc0e0a3ad51a4fd5b401f279ee112aa2b7f8f976d8582606d"}, + {file = "lxml-5.2.1-cp310-cp310-manylinux_2_28_s390x.whl", hash = "sha256:bcbf4af004f98793a95355980764b3d80d47117678118a44a80b721c9913436a"}, + {file = "lxml-5.2.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a2b44bec7adf3e9305ce6cbfa47a4395667e744097faed97abb4728748ba7d47"}, + {file = "lxml-5.2.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:1c5bb205e9212d0ebddf946bc07e73fa245c864a5f90f341d11ce7b0b854475d"}, + {file = "lxml-5.2.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2c9d147f754b1b0e723e6afb7ba1566ecb162fe4ea657f53d2139bbf894d050a"}, + {file = "lxml-5.2.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:3545039fa4779be2df51d6395e91a810f57122290864918b172d5dc7ca5bb433"}, + {file = "lxml-5.2.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a91481dbcddf1736c98a80b122afa0f7296eeb80b72344d7f45dc9f781551f56"}, + {file = "lxml-5.2.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2ddfe41ddc81f29a4c44c8ce239eda5ade4e7fc305fb7311759dd6229a080052"}, + {file = "lxml-5.2.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a7baf9ffc238e4bf401299f50e971a45bfcc10a785522541a6e3179c83eabf0a"}, + {file = "lxml-5.2.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:31e9a882013c2f6bd2f2c974241bf4ba68c85eba943648ce88936d23209a2e01"}, + {file = "lxml-5.2.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0a15438253b34e6362b2dc41475e7f80de76320f335e70c5528b7148cac253a1"}, + {file = "lxml-5.2.1-cp310-cp310-win32.whl", hash = "sha256:6992030d43b916407c9aa52e9673612ff39a575523c5f4cf72cdef75365709a5"}, + {file = "lxml-5.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:da052e7962ea2d5e5ef5bc0355d55007407087392cf465b7ad84ce5f3e25fe0f"}, + {file = "lxml-5.2.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:70ac664a48aa64e5e635ae5566f5227f2ab7f66a3990d67566d9907edcbbf867"}, + {file = "lxml-5.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1ae67b4e737cddc96c99461d2f75d218bdf7a0c3d3ad5604d1f5e7464a2f9ffe"}, + {file = "lxml-5.2.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f18a5a84e16886898e51ab4b1d43acb3083c39b14c8caeb3589aabff0ee0b270"}, + {file = "lxml-5.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6f2c8372b98208ce609c9e1d707f6918cc118fea4e2c754c9f0812c04ca116d"}, + {file = "lxml-5.2.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:394ed3924d7a01b5bd9a0d9d946136e1c2f7b3dc337196d99e61740ed4bc6fe1"}, + {file = "lxml-5.2.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d077bc40a1fe984e1a9931e801e42959a1e6598edc8a3223b061d30fbd26bbc"}, + {file = "lxml-5.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:764b521b75701f60683500d8621841bec41a65eb739b8466000c6fdbc256c240"}, + {file = "lxml-5.2.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:3a6b45da02336895da82b9d472cd274b22dc27a5cea1d4b793874eead23dd14f"}, + {file = "lxml-5.2.1-cp311-cp311-manylinux_2_28_ppc64le.whl", hash = "sha256:5ea7b6766ac2dfe4bcac8b8595107665a18ef01f8c8343f00710b85096d1b53a"}, + {file = "lxml-5.2.1-cp311-cp311-manylinux_2_28_s390x.whl", hash = "sha256:e196a4ff48310ba62e53a8e0f97ca2bca83cdd2fe2934d8b5cb0df0a841b193a"}, + {file = "lxml-5.2.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:200e63525948e325d6a13a76ba2911f927ad399ef64f57898cf7c74e69b71095"}, + {file = "lxml-5.2.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:dae0ed02f6b075426accbf6b2863c3d0a7eacc1b41fb40f2251d931e50188dad"}, + {file = "lxml-5.2.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:ab31a88a651039a07a3ae327d68ebdd8bc589b16938c09ef3f32a4b809dc96ef"}, + {file = "lxml-5.2.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:df2e6f546c4df14bc81f9498bbc007fbb87669f1bb707c6138878c46b06f6510"}, + {file = "lxml-5.2.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5dd1537e7cc06efd81371f5d1a992bd5ab156b2b4f88834ca852de4a8ea523fa"}, + {file = "lxml-5.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9b9ec9c9978b708d488bec36b9e4c94d88fd12ccac3e62134a9d17ddba910ea9"}, + {file = "lxml-5.2.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:8e77c69d5892cb5ba71703c4057091e31ccf534bd7f129307a4d084d90d014b8"}, + {file = "lxml-5.2.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:a8d5c70e04aac1eda5c829a26d1f75c6e5286c74743133d9f742cda8e53b9c2f"}, + {file = "lxml-5.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c94e75445b00319c1fad60f3c98b09cd63fe1134a8a953dcd48989ef42318534"}, + {file = "lxml-5.2.1-cp311-cp311-win32.whl", hash = "sha256:4951e4f7a5680a2db62f7f4ab2f84617674d36d2d76a729b9a8be4b59b3659be"}, + {file = "lxml-5.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:5c670c0406bdc845b474b680b9a5456c561c65cf366f8db5a60154088c92d102"}, + {file = "lxml-5.2.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:abc25c3cab9ec7fcd299b9bcb3b8d4a1231877e425c650fa1c7576c5107ab851"}, + {file = "lxml-5.2.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6935bbf153f9a965f1e07c2649c0849d29832487c52bb4a5c5066031d8b44fd5"}, + {file = "lxml-5.2.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d793bebb202a6000390a5390078e945bbb49855c29c7e4d56a85901326c3b5d9"}, + {file = "lxml-5.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afd5562927cdef7c4f5550374acbc117fd4ecc05b5007bdfa57cc5355864e0a4"}, + {file = "lxml-5.2.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0e7259016bc4345a31af861fdce942b77c99049d6c2107ca07dc2bba2435c1d9"}, + {file = "lxml-5.2.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:530e7c04f72002d2f334d5257c8a51bf409db0316feee7c87e4385043be136af"}, + {file = "lxml-5.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59689a75ba8d7ffca577aefd017d08d659d86ad4585ccc73e43edbfc7476781a"}, + {file = "lxml-5.2.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:f9737bf36262046213a28e789cc82d82c6ef19c85a0cf05e75c670a33342ac2c"}, + {file = "lxml-5.2.1-cp312-cp312-manylinux_2_28_ppc64le.whl", hash = "sha256:3a74c4f27167cb95c1d4af1c0b59e88b7f3e0182138db2501c353555f7ec57f4"}, + {file = "lxml-5.2.1-cp312-cp312-manylinux_2_28_s390x.whl", hash = "sha256:68a2610dbe138fa8c5826b3f6d98a7cfc29707b850ddcc3e21910a6fe51f6ca0"}, + {file = "lxml-5.2.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:f0a1bc63a465b6d72569a9bba9f2ef0334c4e03958e043da1920299100bc7c08"}, + {file = "lxml-5.2.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c2d35a1d047efd68027817b32ab1586c1169e60ca02c65d428ae815b593e65d4"}, + {file = "lxml-5.2.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:79bd05260359170f78b181b59ce871673ed01ba048deef4bf49a36ab3e72e80b"}, + {file = "lxml-5.2.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:865bad62df277c04beed9478fe665b9ef63eb28fe026d5dedcb89b537d2e2ea6"}, + {file = "lxml-5.2.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:44f6c7caff88d988db017b9b0e4ab04934f11e3e72d478031efc7edcac6c622f"}, + {file = "lxml-5.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:71e97313406ccf55d32cc98a533ee05c61e15d11b99215b237346171c179c0b0"}, + {file = "lxml-5.2.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:057cdc6b86ab732cf361f8b4d8af87cf195a1f6dc5b0ff3de2dced242c2015e0"}, + {file = "lxml-5.2.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:f3bbbc998d42f8e561f347e798b85513ba4da324c2b3f9b7969e9c45b10f6169"}, + {file = "lxml-5.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:491755202eb21a5e350dae00c6d9a17247769c64dcf62d8c788b5c135e179dc4"}, + {file = "lxml-5.2.1-cp312-cp312-win32.whl", hash = "sha256:8de8f9d6caa7f25b204fc861718815d41cbcf27ee8f028c89c882a0cf4ae4134"}, + {file = "lxml-5.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:f2a9efc53d5b714b8df2b4b3e992accf8ce5bbdfe544d74d5c6766c9e1146a3a"}, + {file = "lxml-5.2.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:70a9768e1b9d79edca17890175ba915654ee1725975d69ab64813dd785a2bd5c"}, + {file = "lxml-5.2.1-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c38d7b9a690b090de999835f0443d8aa93ce5f2064035dfc48f27f02b4afc3d0"}, + {file = "lxml-5.2.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5670fb70a828663cc37552a2a85bf2ac38475572b0e9b91283dc09efb52c41d1"}, + {file = "lxml-5.2.1-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:958244ad566c3ffc385f47dddde4145088a0ab893504b54b52c041987a8c1863"}, + {file = "lxml-5.2.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:2a66bf12fbd4666dd023b6f51223aed3d9f3b40fef06ce404cb75bafd3d89536"}, + {file = "lxml-5.2.1-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:9123716666e25b7b71c4e1789ec829ed18663152008b58544d95b008ed9e21e9"}, + {file = "lxml-5.2.1-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:0c3f67e2aeda739d1cc0b1102c9a9129f7dc83901226cc24dd72ba275ced4218"}, + {file = "lxml-5.2.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:5d5792e9b3fb8d16a19f46aa8208987cfeafe082363ee2745ea8b643d9cc5b45"}, + {file = "lxml-5.2.1-cp36-cp36m-musllinux_1_2_aarch64.whl", hash = "sha256:88e22fc0a6684337d25c994381ed8a1580a6f5ebebd5ad41f89f663ff4ec2885"}, + {file = "lxml-5.2.1-cp36-cp36m-musllinux_1_2_ppc64le.whl", hash = "sha256:21c2e6b09565ba5b45ae161b438e033a86ad1736b8c838c766146eff8ceffff9"}, + {file = "lxml-5.2.1-cp36-cp36m-musllinux_1_2_s390x.whl", hash = "sha256:afbbdb120d1e78d2ba8064a68058001b871154cc57787031b645c9142b937a62"}, + {file = "lxml-5.2.1-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:627402ad8dea044dde2eccde4370560a2b750ef894c9578e1d4f8ffd54000461"}, + {file = "lxml-5.2.1-cp36-cp36m-win32.whl", hash = "sha256:e89580a581bf478d8dcb97d9cd011d567768e8bc4095f8557b21c4d4c5fea7d0"}, + {file = "lxml-5.2.1-cp36-cp36m-win_amd64.whl", hash = "sha256:59565f10607c244bc4c05c0c5fa0c190c990996e0c719d05deec7030c2aa8289"}, + {file = "lxml-5.2.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:857500f88b17a6479202ff5fe5f580fc3404922cd02ab3716197adf1ef628029"}, + {file = "lxml-5.2.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:56c22432809085b3f3ae04e6e7bdd36883d7258fcd90e53ba7b2e463efc7a6af"}, + {file = "lxml-5.2.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a55ee573116ba208932e2d1a037cc4b10d2c1cb264ced2184d00b18ce585b2c0"}, + {file = "lxml-5.2.1-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:6cf58416653c5901e12624e4013708b6e11142956e7f35e7a83f1ab02f3fe456"}, + {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:64c2baa7774bc22dd4474248ba16fe1a7f611c13ac6123408694d4cc93d66dbd"}, + {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:74b28c6334cca4dd704e8004cba1955af0b778cf449142e581e404bd211fb619"}, + {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:7221d49259aa1e5a8f00d3d28b1e0b76031655ca74bb287123ef56c3db92f213"}, + {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3dbe858ee582cbb2c6294dc85f55b5f19c918c2597855e950f34b660f1a5ede6"}, + {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:04ab5415bf6c86e0518d57240a96c4d1fcfc3cb370bb2ac2a732b67f579e5a04"}, + {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:6ab833e4735a7e5533711a6ea2df26459b96f9eec36d23f74cafe03631647c41"}, + {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f443cdef978430887ed55112b491f670bba6462cea7a7742ff8f14b7abb98d75"}, + {file = "lxml-5.2.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:9e2addd2d1866fe112bc6f80117bcc6bc25191c5ed1bfbcf9f1386a884252ae8"}, + {file = "lxml-5.2.1-cp37-cp37m-win32.whl", hash = "sha256:f51969bac61441fd31f028d7b3b45962f3ecebf691a510495e5d2cd8c8092dbd"}, + {file = "lxml-5.2.1-cp37-cp37m-win_amd64.whl", hash = "sha256:b0b58fbfa1bf7367dde8a557994e3b1637294be6cf2169810375caf8571a085c"}, + {file = "lxml-5.2.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3e183c6e3298a2ed5af9d7a356ea823bccaab4ec2349dc9ed83999fd289d14d5"}, + {file = "lxml-5.2.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:804f74efe22b6a227306dd890eecc4f8c59ff25ca35f1f14e7482bbce96ef10b"}, + {file = "lxml-5.2.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:08802f0c56ed150cc6885ae0788a321b73505d2263ee56dad84d200cab11c07a"}, + {file = "lxml-5.2.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f8c09ed18ecb4ebf23e02b8e7a22a05d6411911e6fabef3a36e4f371f4f2585"}, + {file = "lxml-5.2.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3d30321949861404323c50aebeb1943461a67cd51d4200ab02babc58bd06a86"}, + {file = "lxml-5.2.1-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:b560e3aa4b1d49e0e6c847d72665384db35b2f5d45f8e6a5c0072e0283430533"}, + {file = "lxml-5.2.1-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:058a1308914f20784c9f4674036527e7c04f7be6fb60f5d61353545aa7fcb739"}, + {file = "lxml-5.2.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:adfb84ca6b87e06bc6b146dc7da7623395db1e31621c4785ad0658c5028b37d7"}, + {file = "lxml-5.2.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:417d14450f06d51f363e41cace6488519038f940676ce9664b34ebf5653433a5"}, + {file = "lxml-5.2.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a2dfe7e2473f9b59496247aad6e23b405ddf2e12ef0765677b0081c02d6c2c0b"}, + {file = "lxml-5.2.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bf2e2458345d9bffb0d9ec16557d8858c9c88d2d11fed53998512504cd9df49b"}, + {file = "lxml-5.2.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:58278b29cb89f3e43ff3e0c756abbd1518f3ee6adad9e35b51fb101c1c1daaec"}, + {file = "lxml-5.2.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:64641a6068a16201366476731301441ce93457eb8452056f570133a6ceb15fca"}, + {file = "lxml-5.2.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:78bfa756eab503673991bdcf464917ef7845a964903d3302c5f68417ecdc948c"}, + {file = "lxml-5.2.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:11a04306fcba10cd9637e669fd73aa274c1c09ca64af79c041aa820ea992b637"}, + {file = "lxml-5.2.1-cp38-cp38-win32.whl", hash = "sha256:66bc5eb8a323ed9894f8fa0ee6cb3e3fb2403d99aee635078fd19a8bc7a5a5da"}, + {file = "lxml-5.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:9676bfc686fa6a3fa10cd4ae6b76cae8be26eb5ec6811d2a325636c460da1806"}, + {file = "lxml-5.2.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:cf22b41fdae514ee2f1691b6c3cdeae666d8b7fa9434de445f12bbeee0cf48dd"}, + {file = "lxml-5.2.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ec42088248c596dbd61d4ae8a5b004f97a4d91a9fd286f632e42e60b706718d7"}, + {file = "lxml-5.2.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd53553ddad4a9c2f1f022756ae64abe16da1feb497edf4d9f87f99ec7cf86bd"}, + {file = "lxml-5.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feaa45c0eae424d3e90d78823f3828e7dc42a42f21ed420db98da2c4ecf0a2cb"}, + {file = "lxml-5.2.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddc678fb4c7e30cf830a2b5a8d869538bc55b28d6c68544d09c7d0d8f17694dc"}, + {file = "lxml-5.2.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:853e074d4931dbcba7480d4dcab23d5c56bd9607f92825ab80ee2bd916edea53"}, + {file = "lxml-5.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc4691d60512798304acb9207987e7b2b7c44627ea88b9d77489bbe3e6cc3bd4"}, + {file = "lxml-5.2.1-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:beb72935a941965c52990f3a32d7f07ce869fe21c6af8b34bf6a277b33a345d3"}, + {file = "lxml-5.2.1-cp39-cp39-manylinux_2_28_ppc64le.whl", hash = "sha256:6588c459c5627fefa30139be4d2e28a2c2a1d0d1c265aad2ba1935a7863a4913"}, + {file = "lxml-5.2.1-cp39-cp39-manylinux_2_28_s390x.whl", hash = "sha256:588008b8497667f1ddca7c99f2f85ce8511f8f7871b4a06ceede68ab62dff64b"}, + {file = "lxml-5.2.1-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b6787b643356111dfd4032b5bffe26d2f8331556ecb79e15dacb9275da02866e"}, + {file = "lxml-5.2.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7c17b64b0a6ef4e5affae6a3724010a7a66bda48a62cfe0674dabd46642e8b54"}, + {file = "lxml-5.2.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:27aa20d45c2e0b8cd05da6d4759649170e8dfc4f4e5ef33a34d06f2d79075d57"}, + {file = "lxml-5.2.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:d4f2cc7060dc3646632d7f15fe68e2fa98f58e35dd5666cd525f3b35d3fed7f8"}, + {file = "lxml-5.2.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff46d772d5f6f73564979cd77a4fffe55c916a05f3cb70e7c9c0590059fb29ef"}, + {file = "lxml-5.2.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:96323338e6c14e958d775700ec8a88346014a85e5de73ac7967db0367582049b"}, + {file = "lxml-5.2.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:52421b41ac99e9d91934e4d0d0fe7da9f02bfa7536bb4431b4c05c906c8c6919"}, + {file = "lxml-5.2.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:7a7efd5b6d3e30d81ec68ab8a88252d7c7c6f13aaa875009fe3097eb4e30b84c"}, + {file = "lxml-5.2.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0ed777c1e8c99b63037b91f9d73a6aad20fd035d77ac84afcc205225f8f41188"}, + {file = "lxml-5.2.1-cp39-cp39-win32.whl", hash = "sha256:644df54d729ef810dcd0f7732e50e5ad1bd0a135278ed8d6bcb06f33b6b6f708"}, + {file = "lxml-5.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:9ca66b8e90daca431b7ca1408cae085d025326570e57749695d6a01454790e95"}, + {file = "lxml-5.2.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9b0ff53900566bc6325ecde9181d89afadc59c5ffa39bddf084aaedfe3b06a11"}, + {file = "lxml-5.2.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd6037392f2d57793ab98d9e26798f44b8b4da2f2464388588f48ac52c489ea1"}, + {file = "lxml-5.2.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b9c07e7a45bb64e21df4b6aa623cb8ba214dfb47d2027d90eac197329bb5e94"}, + {file = "lxml-5.2.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:3249cc2989d9090eeac5467e50e9ec2d40704fea9ab72f36b034ea34ee65ca98"}, + {file = "lxml-5.2.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f42038016852ae51b4088b2862126535cc4fc85802bfe30dea3500fdfaf1864e"}, + {file = "lxml-5.2.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:533658f8fbf056b70e434dff7e7aa611bcacb33e01f75de7f821810e48d1bb66"}, + {file = "lxml-5.2.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:622020d4521e22fb371e15f580d153134bfb68d6a429d1342a25f051ec72df1c"}, + {file = "lxml-5.2.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efa7b51824aa0ee957ccd5a741c73e6851de55f40d807f08069eb4c5a26b2baa"}, + {file = "lxml-5.2.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c6ad0fbf105f6bcc9300c00010a2ffa44ea6f555df1a2ad95c88f5656104817"}, + {file = "lxml-5.2.1-pp37-pypy37_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:e233db59c8f76630c512ab4a4daf5a5986da5c3d5b44b8e9fc742f2a24dbd460"}, + {file = "lxml-5.2.1-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:6a014510830df1475176466b6087fc0c08b47a36714823e58d8b8d7709132a96"}, + {file = "lxml-5.2.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:d38c8f50ecf57f0463399569aa388b232cf1a2ffb8f0a9a5412d0db57e054860"}, + {file = "lxml-5.2.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5aea8212fb823e006b995c4dda533edcf98a893d941f173f6c9506126188860d"}, + {file = "lxml-5.2.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff097ae562e637409b429a7ac958a20aab237a0378c42dabaa1e3abf2f896e5f"}, + {file = "lxml-5.2.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f5d65c39f16717a47c36c756af0fb36144069c4718824b7533f803ecdf91138"}, + {file = "lxml-5.2.1-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:3d0c3dd24bb4605439bf91068598d00c6370684f8de4a67c2992683f6c309d6b"}, + {file = "lxml-5.2.1-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e32be23d538753a8adb6c85bd539f5fd3b15cb987404327c569dfc5fd8366e85"}, + {file = "lxml-5.2.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:cc518cea79fd1e2f6c90baafa28906d4309d24f3a63e801d855e7424c5b34144"}, + {file = "lxml-5.2.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a0af35bd8ebf84888373630f73f24e86bf016642fb8576fba49d3d6b560b7cbc"}, + {file = "lxml-5.2.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8aca2e3a72f37bfc7b14ba96d4056244001ddcc18382bd0daa087fd2e68a354"}, + {file = "lxml-5.2.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ca1e8188b26a819387b29c3895c47a5e618708fe6f787f3b1a471de2c4a94d9"}, + {file = "lxml-5.2.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c8ba129e6d3b0136a0f50345b2cb3db53f6bda5dd8c7f5d83fbccba97fb5dcb5"}, + {file = "lxml-5.2.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e998e304036198b4f6914e6a1e2b6f925208a20e2042563d9734881150c6c246"}, + {file = "lxml-5.2.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d3be9b2076112e51b323bdf6d5a7f8a798de55fb8d95fcb64bd179460cdc0704"}, + {file = "lxml-5.2.1.tar.gz", hash = "sha256:3f7765e69bbce0906a7c74d5fe46d2c7a7596147318dbc08e4a2431f3060e306"}, +] + +[package.extras] +cssselect = ["cssselect (>=0.7)"] +html-clean = ["lxml-html-clean"] +html5 = ["html5lib"] +htmlsoup = ["BeautifulSoup4"] +source = ["Cython (>=3.0.10)"] + +[[package]] +name = "mako" +version = "1.3.2" +description = "A super-fast templating language that borrows the best ideas from the existing templating languages." +optional = false +python-versions = ">=3.8" +files = [ + {file = "Mako-1.3.2-py3-none-any.whl", hash = "sha256:32a99d70754dfce237019d17ffe4a282d2d3351b9c476e90d8a60e63f133b80c"}, + {file = "Mako-1.3.2.tar.gz", hash = "sha256:2a0c8ad7f6274271b3bb7467dd37cf9cc6dab4bc19cb69a4ef10669402de698e"}, +] + +[package.dependencies] +MarkupSafe = ">=0.9.2" + +[package.extras] +babel = ["Babel"] +lingua = ["lingua"] +testing = ["pytest"] + +[[package]] +name = "markdown-it-py" +version = "3.0.0" +description = "Python port of markdown-it. Markdown parsing, done right!" +optional = false +python-versions = ">=3.8" +files = [ + {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, + {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, +] + +[package.dependencies] +mdurl = ">=0.1,<1.0" + +[package.extras] +benchmarking = ["psutil", "pytest", "pytest-benchmark"] +code-style = ["pre-commit (>=3.0,<4.0)"] +compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] +linkify = ["linkify-it-py (>=1,<3)"] +plugins = ["mdit-py-plugins"] +profiling = ["gprof2dot"] +rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] + +[[package]] +name = "markupsafe" +version = "2.1.5" +description = "Safely add untrusted strings to HTML/XML markup." +optional = false +python-versions = ">=3.7" +files = [ + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, + {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, +] + +[[package]] +name = "marshmallow" +version = "3.21.1" +description = "A lightweight library for converting complex datatypes to and from native Python datatypes." +optional = false +python-versions = ">=3.8" +files = [ + {file = "marshmallow-3.21.1-py3-none-any.whl", hash = "sha256:f085493f79efb0644f270a9bf2892843142d80d7174bbbd2f3713f2a589dc633"}, + {file = "marshmallow-3.21.1.tar.gz", hash = "sha256:4e65e9e0d80fc9e609574b9983cf32579f305c718afb30d7233ab818571768c3"}, +] + +[package.dependencies] +packaging = ">=17.0" + +[package.extras] +dev = ["marshmallow[tests]", "pre-commit (>=3.5,<4.0)", "tox"] +docs = ["alabaster (==0.7.16)", "autodocsumm (==0.2.12)", "sphinx (==7.2.6)", "sphinx-issues (==4.0.0)", "sphinx-version-warning (==1.1.2)"] +tests = ["pytest", "pytz", "simplejson"] + +[[package]] +name = "matplotlib-inline" +version = "0.1.6" +description = "Inline Matplotlib backend for Jupyter" +optional = false +python-versions = ">=3.5" +files = [ + {file = "matplotlib-inline-0.1.6.tar.gz", hash = "sha256:f887e5f10ba98e8d2b150ddcf4702c1e5f8b3a20005eb0f74bfdbd360ee6f304"}, + {file = "matplotlib_inline-0.1.6-py3-none-any.whl", hash = "sha256:f1f41aab5328aa5aaea9b16d083b128102f8712542f819fe7e6a420ff581b311"}, +] + +[package.dependencies] +traitlets = "*" + +[[package]] +name = "mdurl" +version = "0.1.2" +description = "Markdown URL utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, + {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, +] + +[[package]] +name = "mmh3" +version = "4.1.0" +description = "Python extension for MurmurHash (MurmurHash3), a set of fast and robust hash functions." +optional = false +python-versions = "*" +files = [ + {file = "mmh3-4.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:be5ac76a8b0cd8095784e51e4c1c9c318c19edcd1709a06eb14979c8d850c31a"}, + {file = "mmh3-4.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:98a49121afdfab67cd80e912b36404139d7deceb6773a83620137aaa0da5714c"}, + {file = "mmh3-4.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5259ac0535874366e7d1a5423ef746e0d36a9e3c14509ce6511614bdc5a7ef5b"}, + {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5950827ca0453a2be357696da509ab39646044e3fa15cad364eb65d78797437"}, + {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1dd0f652ae99585b9dd26de458e5f08571522f0402155809fd1dc8852a613a39"}, + {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99d25548070942fab1e4a6f04d1626d67e66d0b81ed6571ecfca511f3edf07e6"}, + {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53db8d9bad3cb66c8f35cbc894f336273f63489ce4ac416634932e3cbe79eb5b"}, + {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75da0f615eb55295a437264cc0b736753f830b09d102aa4c2a7d719bc445ec05"}, + {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b926b07fd678ea84b3a2afc1fa22ce50aeb627839c44382f3d0291e945621e1a"}, + {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c5b053334f9b0af8559d6da9dc72cef0a65b325ebb3e630c680012323c950bb6"}, + {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:5bf33dc43cd6de2cb86e0aa73a1cc6530f557854bbbe5d59f41ef6de2e353d7b"}, + {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fa7eacd2b830727ba3dd65a365bed8a5c992ecd0c8348cf39a05cc77d22f4970"}, + {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:42dfd6742b9e3eec599f85270617debfa0bbb913c545bb980c8a4fa7b2d047da"}, + {file = "mmh3-4.1.0-cp310-cp310-win32.whl", hash = "sha256:2974ad343f0d39dcc88e93ee6afa96cedc35a9883bc067febd7ff736e207fa47"}, + {file = "mmh3-4.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:74699a8984ded645c1a24d6078351a056f5a5f1fe5838870412a68ac5e28d865"}, + {file = "mmh3-4.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:f0dc874cedc23d46fc488a987faa6ad08ffa79e44fb08e3cd4d4cf2877c00a00"}, + {file = "mmh3-4.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3280a463855b0eae64b681cd5b9ddd9464b73f81151e87bb7c91a811d25619e6"}, + {file = "mmh3-4.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:97ac57c6c3301769e757d444fa7c973ceb002cb66534b39cbab5e38de61cd896"}, + {file = "mmh3-4.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a7b6502cdb4dbd880244818ab363c8770a48cdccecf6d729ade0241b736b5ec0"}, + {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52ba2da04671a9621580ddabf72f06f0e72c1c9c3b7b608849b58b11080d8f14"}, + {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a5fef4c4ecc782e6e43fbeab09cff1bac82c998a1773d3a5ee6a3605cde343e"}, + {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5135358a7e00991f73b88cdc8eda5203bf9de22120d10a834c5761dbeb07dd13"}, + {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cff9ae76a54f7c6fe0167c9c4028c12c1f6de52d68a31d11b6790bb2ae685560"}, + {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6f02576a4d106d7830ca90278868bf0983554dd69183b7bbe09f2fcd51cf54f"}, + {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:073d57425a23721730d3ff5485e2da489dd3c90b04e86243dd7211f889898106"}, + {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:71e32ddec7f573a1a0feb8d2cf2af474c50ec21e7a8263026e8d3b4b629805db"}, + {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7cbb20b29d57e76a58b40fd8b13a9130db495a12d678d651b459bf61c0714cea"}, + {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:a42ad267e131d7847076bb7e31050f6c4378cd38e8f1bf7a0edd32f30224d5c9"}, + {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4a013979fc9390abadc445ea2527426a0e7a4495c19b74589204f9b71bcaafeb"}, + {file = "mmh3-4.1.0-cp311-cp311-win32.whl", hash = "sha256:1d3b1cdad7c71b7b88966301789a478af142bddcb3a2bee563f7a7d40519a00f"}, + {file = "mmh3-4.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:0dc6dc32eb03727467da8e17deffe004fbb65e8b5ee2b502d36250d7a3f4e2ec"}, + {file = "mmh3-4.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:9ae3a5c1b32dda121c7dc26f9597ef7b01b4c56a98319a7fe86c35b8bc459ae6"}, + {file = "mmh3-4.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0033d60c7939168ef65ddc396611077a7268bde024f2c23bdc283a19123f9e9c"}, + {file = "mmh3-4.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d6af3e2287644b2b08b5924ed3a88c97b87b44ad08e79ca9f93d3470a54a41c5"}, + {file = "mmh3-4.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d82eb4defa245e02bb0b0dc4f1e7ee284f8d212633389c91f7fba99ba993f0a2"}, + {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba245e94b8d54765e14c2d7b6214e832557e7856d5183bc522e17884cab2f45d"}, + {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb04e2feeabaad6231e89cd43b3d01a4403579aa792c9ab6fdeef45cc58d4ec0"}, + {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e3b1a27def545ce11e36158ba5d5390cdbc300cfe456a942cc89d649cf7e3b2"}, + {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce0ab79ff736d7044e5e9b3bfe73958a55f79a4ae672e6213e92492ad5e734d5"}, + {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b02268be6e0a8eeb8a924d7db85f28e47344f35c438c1e149878bb1c47b1cd3"}, + {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:deb887f5fcdaf57cf646b1e062d56b06ef2f23421c80885fce18b37143cba828"}, + {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:99dd564e9e2b512eb117bd0cbf0f79a50c45d961c2a02402787d581cec5448d5"}, + {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:08373082dfaa38fe97aa78753d1efd21a1969e51079056ff552e687764eafdfe"}, + {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:54b9c6a2ea571b714e4fe28d3e4e2db37abfd03c787a58074ea21ee9a8fd1740"}, + {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a7b1edf24c69e3513f879722b97ca85e52f9032f24a52284746877f6a7304086"}, + {file = "mmh3-4.1.0-cp312-cp312-win32.whl", hash = "sha256:411da64b951f635e1e2284b71d81a5a83580cea24994b328f8910d40bed67276"}, + {file = "mmh3-4.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:bebc3ecb6ba18292e3d40c8712482b4477abd6981c2ebf0e60869bd90f8ac3a9"}, + {file = "mmh3-4.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:168473dd608ade6a8d2ba069600b35199a9af837d96177d3088ca91f2b3798e3"}, + {file = "mmh3-4.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:372f4b7e1dcde175507640679a2a8790185bb71f3640fc28a4690f73da986a3b"}, + {file = "mmh3-4.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:438584b97f6fe13e944faf590c90fc127682b57ae969f73334040d9fa1c7ffa5"}, + {file = "mmh3-4.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6e27931b232fc676675fac8641c6ec6b596daa64d82170e8597f5a5b8bdcd3b6"}, + {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:571a92bad859d7b0330e47cfd1850b76c39b615a8d8e7aa5853c1f971fd0c4b1"}, + {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a69d6afe3190fa08f9e3a58e5145549f71f1f3fff27bd0800313426929c7068"}, + {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:afb127be0be946b7630220908dbea0cee0d9d3c583fa9114a07156f98566dc28"}, + {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:940d86522f36348ef1a494cbf7248ab3f4a1638b84b59e6c9e90408bd11ad729"}, + {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3dcccc4935686619a8e3d1f7b6e97e3bd89a4a796247930ee97d35ea1a39341"}, + {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:01bb9b90d61854dfc2407c5e5192bfb47222d74f29d140cb2dd2a69f2353f7cc"}, + {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:bcb1b8b951a2c0b0fb8a5426c62a22557e2ffc52539e0a7cc46eb667b5d606a9"}, + {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6477a05d5e5ab3168e82e8b106e316210ac954134f46ec529356607900aea82a"}, + {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:da5892287e5bea6977364b15712a2573c16d134bc5fdcdd4cf460006cf849278"}, + {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:99180d7fd2327a6fffbaff270f760576839dc6ee66d045fa3a450f3490fda7f5"}, + {file = "mmh3-4.1.0-cp38-cp38-win32.whl", hash = "sha256:9b0d4f3949913a9f9a8fb1bb4cc6ecd52879730aab5ff8c5a3d8f5b593594b73"}, + {file = "mmh3-4.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:598c352da1d945108aee0c3c3cfdd0e9b3edef74108f53b49d481d3990402169"}, + {file = "mmh3-4.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:475d6d1445dd080f18f0f766277e1237fa2914e5fe3307a3b2a3044f30892103"}, + {file = "mmh3-4.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5ca07c41e6a2880991431ac717c2a049056fff497651a76e26fc22224e8b5732"}, + {file = "mmh3-4.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ebe052fef4bbe30c0548d12ee46d09f1b69035ca5208a7075e55adfe091be44"}, + {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eaefd42e85afb70f2b855a011f7b4d8a3c7e19c3f2681fa13118e4d8627378c5"}, + {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0ae43caae5a47afe1b63a1ae3f0986dde54b5fb2d6c29786adbfb8edc9edfb"}, + {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6218666f74c8c013c221e7f5f8a693ac9cf68e5ac9a03f2373b32d77c48904de"}, + {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ac59294a536ba447b5037f62d8367d7d93b696f80671c2c45645fa9f1109413c"}, + {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:086844830fcd1e5c84fec7017ea1ee8491487cfc877847d96f86f68881569d2e"}, + {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e42b38fad664f56f77f6fbca22d08450f2464baa68acdbf24841bf900eb98e87"}, + {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d08b790a63a9a1cde3b5d7d733ed97d4eb884bfbc92f075a091652d6bfd7709a"}, + {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:73ea4cc55e8aea28c86799ecacebca09e5f86500414870a8abaedfcbaf74d288"}, + {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:f90938ff137130e47bcec8dc1f4ceb02f10178c766e2ef58a9f657ff1f62d124"}, + {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:aa1f13e94b8631c8cd53259250556edcf1de71738936b60febba95750d9632bd"}, + {file = "mmh3-4.1.0-cp39-cp39-win32.whl", hash = "sha256:a3b680b471c181490cf82da2142029edb4298e1bdfcb67c76922dedef789868d"}, + {file = "mmh3-4.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:fefef92e9c544a8dbc08f77a8d1b6d48006a750c4375bbcd5ff8199d761e263b"}, + {file = "mmh3-4.1.0-cp39-cp39-win_arm64.whl", hash = "sha256:8e2c1f6a2b41723a4f82bd5a762a777836d29d664fc0095f17910bea0adfd4a6"}, + {file = "mmh3-4.1.0.tar.gz", hash = "sha256:a1cf25348b9acd229dda464a094d6170f47d2850a1fcb762a3b6172d2ce6ca4a"}, +] + +[package.extras] +test = ["mypy (>=1.0)", "pytest (>=7.0.0)"] + +[[package]] +name = "monotonic" +version = "1.6" +description = "An implementation of time.monotonic() for Python 2 & < 3.3" +optional = false +python-versions = "*" +files = [ + {file = "monotonic-1.6-py2.py3-none-any.whl", hash = "sha256:68687e19a14f11f26d140dd5c86f3dba4bf5df58003000ed467e0e2a69bca96c"}, + {file = "monotonic-1.6.tar.gz", hash = "sha256:3a55207bcfed53ddd5c5bae174524062935efed17792e9de2ad0205ce9ad63f7"}, +] + +[[package]] +name = "mpmath" +version = "1.3.0" +description = "Python library for arbitrary-precision floating-point arithmetic" +optional = false +python-versions = "*" +files = [ + {file = "mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c"}, + {file = "mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f"}, +] + +[package.extras] +develop = ["codecov", "pycodestyle", "pytest (>=4.6)", "pytest-cov", "wheel"] +docs = ["sphinx"] +gmpy = ["gmpy2 (>=2.1.0a4)"] +tests = ["pytest (>=4.6)"] + +[[package]] +name = "msgpack" +version = "1.0.8" +description = "MessagePack serializer" +optional = false +python-versions = ">=3.8" +files = [ + {file = "msgpack-1.0.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:505fe3d03856ac7d215dbe005414bc28505d26f0c128906037e66d98c4e95868"}, + {file = "msgpack-1.0.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6b7842518a63a9f17107eb176320960ec095a8ee3b4420b5f688e24bf50c53c"}, + {file = "msgpack-1.0.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:376081f471a2ef24828b83a641a02c575d6103a3ad7fd7dade5486cad10ea659"}, + {file = "msgpack-1.0.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e390971d082dba073c05dbd56322427d3280b7cc8b53484c9377adfbae67dc2"}, + {file = "msgpack-1.0.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00e073efcba9ea99db5acef3959efa45b52bc67b61b00823d2a1a6944bf45982"}, + {file = "msgpack-1.0.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82d92c773fbc6942a7a8b520d22c11cfc8fd83bba86116bfcf962c2f5c2ecdaa"}, + {file = "msgpack-1.0.8-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9ee32dcb8e531adae1f1ca568822e9b3a738369b3b686d1477cbc643c4a9c128"}, + {file = "msgpack-1.0.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e3aa7e51d738e0ec0afbed661261513b38b3014754c9459508399baf14ae0c9d"}, + {file = "msgpack-1.0.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:69284049d07fce531c17404fcba2bb1df472bc2dcdac642ae71a2d079d950653"}, + {file = "msgpack-1.0.8-cp310-cp310-win32.whl", hash = "sha256:13577ec9e247f8741c84d06b9ece5f654920d8365a4b636ce0e44f15e07ec693"}, + {file = "msgpack-1.0.8-cp310-cp310-win_amd64.whl", hash = "sha256:e532dbd6ddfe13946de050d7474e3f5fb6ec774fbb1a188aaf469b08cf04189a"}, + {file = "msgpack-1.0.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9517004e21664f2b5a5fd6333b0731b9cf0817403a941b393d89a2f1dc2bd836"}, + {file = "msgpack-1.0.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d16a786905034e7e34098634b184a7d81f91d4c3d246edc6bd7aefb2fd8ea6ad"}, + {file = "msgpack-1.0.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2872993e209f7ed04d963e4b4fbae72d034844ec66bc4ca403329db2074377b"}, + {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c330eace3dd100bdb54b5653b966de7f51c26ec4a7d4e87132d9b4f738220ba"}, + {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83b5c044f3eff2a6534768ccfd50425939e7a8b5cf9a7261c385de1e20dcfc85"}, + {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1876b0b653a808fcd50123b953af170c535027bf1d053b59790eebb0aeb38950"}, + {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:dfe1f0f0ed5785c187144c46a292b8c34c1295c01da12e10ccddfc16def4448a"}, + {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3528807cbbb7f315bb81959d5961855e7ba52aa60a3097151cb21956fbc7502b"}, + {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e2f879ab92ce502a1e65fce390eab619774dda6a6ff719718069ac94084098ce"}, + {file = "msgpack-1.0.8-cp311-cp311-win32.whl", hash = "sha256:26ee97a8261e6e35885c2ecd2fd4a6d38252246f94a2aec23665a4e66d066305"}, + {file = "msgpack-1.0.8-cp311-cp311-win_amd64.whl", hash = "sha256:eadb9f826c138e6cf3c49d6f8de88225a3c0ab181a9b4ba792e006e5292d150e"}, + {file = "msgpack-1.0.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:114be227f5213ef8b215c22dde19532f5da9652e56e8ce969bf0a26d7c419fee"}, + {file = "msgpack-1.0.8-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d661dc4785affa9d0edfdd1e59ec056a58b3dbb9f196fa43587f3ddac654ac7b"}, + {file = "msgpack-1.0.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d56fd9f1f1cdc8227d7b7918f55091349741904d9520c65f0139a9755952c9e8"}, + {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0726c282d188e204281ebd8de31724b7d749adebc086873a59efb8cf7ae27df3"}, + {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8db8e423192303ed77cff4dce3a4b88dbfaf43979d280181558af5e2c3c71afc"}, + {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99881222f4a8c2f641f25703963a5cefb076adffd959e0558dc9f803a52d6a58"}, + {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b5505774ea2a73a86ea176e8a9a4a7c8bf5d521050f0f6f8426afe798689243f"}, + {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ef254a06bcea461e65ff0373d8a0dd1ed3aa004af48839f002a0c994a6f72d04"}, + {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e1dd7839443592d00e96db831eddb4111a2a81a46b028f0facd60a09ebbdd543"}, + {file = "msgpack-1.0.8-cp312-cp312-win32.whl", hash = "sha256:64d0fcd436c5683fdd7c907eeae5e2cbb5eb872fafbc03a43609d7941840995c"}, + {file = "msgpack-1.0.8-cp312-cp312-win_amd64.whl", hash = "sha256:74398a4cf19de42e1498368c36eed45d9528f5fd0155241e82c4082b7e16cffd"}, + {file = "msgpack-1.0.8-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0ceea77719d45c839fd73abcb190b8390412a890df2f83fb8cf49b2a4b5c2f40"}, + {file = "msgpack-1.0.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1ab0bbcd4d1f7b6991ee7c753655b481c50084294218de69365f8f1970d4c151"}, + {file = "msgpack-1.0.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1cce488457370ffd1f953846f82323cb6b2ad2190987cd4d70b2713e17268d24"}, + {file = "msgpack-1.0.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3923a1778f7e5ef31865893fdca12a8d7dc03a44b33e2a5f3295416314c09f5d"}, + {file = "msgpack-1.0.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a22e47578b30a3e199ab067a4d43d790249b3c0587d9a771921f86250c8435db"}, + {file = "msgpack-1.0.8-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd739c9251d01e0279ce729e37b39d49a08c0420d3fee7f2a4968c0576678f77"}, + {file = "msgpack-1.0.8-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d3420522057ebab1728b21ad473aa950026d07cb09da41103f8e597dfbfaeb13"}, + {file = "msgpack-1.0.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5845fdf5e5d5b78a49b826fcdc0eb2e2aa7191980e3d2cfd2a30303a74f212e2"}, + {file = "msgpack-1.0.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a0e76621f6e1f908ae52860bdcb58e1ca85231a9b0545e64509c931dd34275a"}, + {file = "msgpack-1.0.8-cp38-cp38-win32.whl", hash = "sha256:374a8e88ddab84b9ada695d255679fb99c53513c0a51778796fcf0944d6c789c"}, + {file = "msgpack-1.0.8-cp38-cp38-win_amd64.whl", hash = "sha256:f3709997b228685fe53e8c433e2df9f0cdb5f4542bd5114ed17ac3c0129b0480"}, + {file = "msgpack-1.0.8-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f51bab98d52739c50c56658cc303f190785f9a2cd97b823357e7aeae54c8f68a"}, + {file = "msgpack-1.0.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:73ee792784d48aa338bba28063e19a27e8d989344f34aad14ea6e1b9bd83f596"}, + {file = "msgpack-1.0.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f9904e24646570539a8950400602d66d2b2c492b9010ea7e965025cb71d0c86d"}, + {file = "msgpack-1.0.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e75753aeda0ddc4c28dce4c32ba2f6ec30b1b02f6c0b14e547841ba5b24f753f"}, + {file = "msgpack-1.0.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5dbf059fb4b7c240c873c1245ee112505be27497e90f7c6591261c7d3c3a8228"}, + {file = "msgpack-1.0.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4916727e31c28be8beaf11cf117d6f6f188dcc36daae4e851fee88646f5b6b18"}, + {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7938111ed1358f536daf311be244f34df7bf3cdedb3ed883787aca97778b28d8"}, + {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:493c5c5e44b06d6c9268ce21b302c9ca055c1fd3484c25ba41d34476c76ee746"}, + {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fbb160554e319f7b22ecf530a80a3ff496d38e8e07ae763b9e82fadfe96f273"}, + {file = "msgpack-1.0.8-cp39-cp39-win32.whl", hash = "sha256:f9af38a89b6a5c04b7d18c492c8ccf2aee7048aff1ce8437c4683bb5a1df893d"}, + {file = "msgpack-1.0.8-cp39-cp39-win_amd64.whl", hash = "sha256:ed59dd52075f8fc91da6053b12e8c89e37aa043f8986efd89e61fae69dc1b011"}, + {file = "msgpack-1.0.8.tar.gz", hash = "sha256:95c02b0e27e706e48d0e5426d1710ca78e0f0628d6e89d5b5a5b91a5f12274f3"}, +] + +[[package]] +name = "multidict" +version = "6.0.5" +description = "multidict implementation" +optional = false +python-versions = ">=3.7" +files = [ + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc"}, + {file = "multidict-6.0.5-cp310-cp310-win32.whl", hash = "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319"}, + {file = "multidict-6.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e"}, + {file = "multidict-6.0.5-cp311-cp311-win32.whl", hash = "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c"}, + {file = "multidict-6.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"}, + {file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"}, + {file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"}, + {file = "multidict-6.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc"}, + {file = "multidict-6.0.5-cp37-cp37m-win32.whl", hash = "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee"}, + {file = "multidict-6.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44"}, + {file = "multidict-6.0.5-cp38-cp38-win32.whl", hash = "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241"}, + {file = "multidict-6.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c"}, + {file = "multidict-6.0.5-cp39-cp39-win32.whl", hash = "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b"}, + {file = "multidict-6.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755"}, + {file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"}, + {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"}, +] + +[[package]] +name = "multiprocess" +version = "0.70.16" +description = "better multiprocessing and multithreading in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "multiprocess-0.70.16-pp310-pypy310_pp73-macosx_10_13_x86_64.whl", hash = "sha256:476887be10e2f59ff183c006af746cb6f1fd0eadcfd4ef49e605cbe2659920ee"}, + {file = "multiprocess-0.70.16-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d951bed82c8f73929ac82c61f01a7b5ce8f3e5ef40f5b52553b4f547ce2b08ec"}, + {file = "multiprocess-0.70.16-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:37b55f71c07e2d741374998c043b9520b626a8dddc8b3129222ca4f1a06ef67a"}, + {file = "multiprocess-0.70.16-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:ba8c31889abf4511c7308a8c52bb4a30b9d590e7f58523302ba00237702ca054"}, + {file = "multiprocess-0.70.16-pp39-pypy39_pp73-macosx_10_13_x86_64.whl", hash = "sha256:0dfd078c306e08d46d7a8d06fb120313d87aa43af60d66da43ffff40b44d2f41"}, + {file = "multiprocess-0.70.16-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e7b9d0f307cd9bd50851afaac0dba2cb6c44449efff697df7c7645f7d3f2be3a"}, + {file = "multiprocess-0.70.16-py310-none-any.whl", hash = "sha256:c4a9944c67bd49f823687463660a2d6daae94c289adff97e0f9d696ba6371d02"}, + {file = "multiprocess-0.70.16-py311-none-any.whl", hash = "sha256:af4cabb0dac72abfb1e794fa7855c325fd2b55a10a44628a3c1ad3311c04127a"}, + {file = "multiprocess-0.70.16-py312-none-any.whl", hash = "sha256:fc0544c531920dde3b00c29863377f87e1632601092ea2daca74e4beb40faa2e"}, + {file = "multiprocess-0.70.16-py38-none-any.whl", hash = "sha256:a71d82033454891091a226dfc319d0cfa8019a4e888ef9ca910372a446de4435"}, + {file = "multiprocess-0.70.16-py39-none-any.whl", hash = "sha256:a0bafd3ae1b732eac64be2e72038231c1ba97724b60b09400d68f229fcc2fbf3"}, + {file = "multiprocess-0.70.16.tar.gz", hash = "sha256:161af703d4652a0e1410be6abccecde4a7ddffd19341be0a7011b94aeb171ac1"}, +] + +[package.dependencies] +dill = ">=0.3.8" + +[[package]] +name = "mypy" +version = "1.9.0" +description = "Optional static typing for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mypy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f8a67616990062232ee4c3952f41c779afac41405806042a8126fe96e098419f"}, + {file = "mypy-1.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d357423fa57a489e8c47b7c85dfb96698caba13d66e086b412298a1a0ea3b0ed"}, + {file = "mypy-1.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49c87c15aed320de9b438ae7b00c1ac91cd393c1b854c2ce538e2a72d55df150"}, + {file = "mypy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:48533cdd345c3c2e5ef48ba3b0d3880b257b423e7995dada04248725c6f77374"}, + {file = "mypy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:4d3dbd346cfec7cb98e6cbb6e0f3c23618af826316188d587d1c1bc34f0ede03"}, + {file = "mypy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:653265f9a2784db65bfca694d1edd23093ce49740b2244cde583aeb134c008f3"}, + {file = "mypy-1.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a3c007ff3ee90f69cf0a15cbcdf0995749569b86b6d2f327af01fd1b8aee9dc"}, + {file = "mypy-1.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2418488264eb41f69cc64a69a745fad4a8f86649af4b1041a4c64ee61fc61129"}, + {file = "mypy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:68edad3dc7d70f2f17ae4c6c1b9471a56138ca22722487eebacfd1eb5321d612"}, + {file = "mypy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:85ca5fcc24f0b4aeedc1d02f93707bccc04733f21d41c88334c5482219b1ccb3"}, + {file = "mypy-1.9.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aceb1db093b04db5cd390821464504111b8ec3e351eb85afd1433490163d60cd"}, + {file = "mypy-1.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0235391f1c6f6ce487b23b9dbd1327b4ec33bb93934aa986efe8a9563d9349e6"}, + {file = "mypy-1.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4d5ddc13421ba3e2e082a6c2d74c2ddb3979c39b582dacd53dd5d9431237185"}, + {file = "mypy-1.9.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:190da1ee69b427d7efa8aa0d5e5ccd67a4fb04038c380237a0d96829cb157913"}, + {file = "mypy-1.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:fe28657de3bfec596bbeef01cb219833ad9d38dd5393fc649f4b366840baefe6"}, + {file = "mypy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e54396d70be04b34f31d2edf3362c1edd023246c82f1730bbf8768c28db5361b"}, + {file = "mypy-1.9.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5e6061f44f2313b94f920e91b204ec600982961e07a17e0f6cd83371cb23f5c2"}, + {file = "mypy-1.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a10926e5473c5fc3da8abb04119a1f5811a236dc3a38d92015cb1e6ba4cb9e"}, + {file = "mypy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b685154e22e4e9199fc95f298661deea28aaede5ae16ccc8cbb1045e716b3e04"}, + {file = "mypy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:5d741d3fc7c4da608764073089e5f58ef6352bedc223ff58f2f038c2c4698a89"}, + {file = "mypy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:587ce887f75dd9700252a3abbc9c97bbe165a4a630597845c61279cf32dfbf02"}, + {file = "mypy-1.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f88566144752999351725ac623471661c9d1cd8caa0134ff98cceeea181789f4"}, + {file = "mypy-1.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61758fabd58ce4b0720ae1e2fea5cfd4431591d6d590b197775329264f86311d"}, + {file = "mypy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e49499be624dead83927e70c756970a0bc8240e9f769389cdf5714b0784ca6bf"}, + {file = "mypy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:571741dc4194b4f82d344b15e8837e8c5fcc462d66d076748142327626a1b6e9"}, + {file = "mypy-1.9.0-py3-none-any.whl", hash = "sha256:a260627a570559181a9ea5de61ac6297aa5af202f06fd7ab093ce74e7181e43e"}, + {file = "mypy-1.9.0.tar.gz", hash = "sha256:3cc5da0127e6a478cddd906068496a97a7618a21ce9b54bde5bf7e539c7af974"}, +] + +[package.dependencies] +mypy-extensions = ">=1.0.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = ">=4.1.0" + +[package.extras] +dmypy = ["psutil (>=4.0)"] +install-types = ["pip"] +mypyc = ["setuptools (>=50)"] +reports = ["lxml"] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + +[[package]] +name = "nest-asyncio" +version = "1.6.0" +description = "Patch asyncio to allow nested event loops" +optional = false +python-versions = ">=3.5" +files = [ + {file = "nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c"}, + {file = "nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe"}, +] + +[[package]] +name = "numpy" +version = "1.26.4" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"}, + {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"}, + {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4"}, + {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f"}, + {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a"}, + {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2"}, + {file = "numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07"}, + {file = "numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5"}, + {file = "numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71"}, + {file = "numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef"}, + {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e"}, + {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5"}, + {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a"}, + {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a"}, + {file = "numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20"}, + {file = "numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2"}, + {file = "numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218"}, + {file = "numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b"}, + {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b"}, + {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed"}, + {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a"}, + {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0"}, + {file = "numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110"}, + {file = "numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818"}, + {file = "numpy-1.26.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c"}, + {file = "numpy-1.26.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be"}, + {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764"}, + {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3"}, + {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd"}, + {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c"}, + {file = "numpy-1.26.4-cp39-cp39-win32.whl", hash = "sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6"}, + {file = "numpy-1.26.4-cp39-cp39-win_amd64.whl", hash = "sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0"}, + {file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"}, +] + +[[package]] +name = "oauthlib" +version = "3.2.2" +description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" +optional = false +python-versions = ">=3.6" +files = [ + {file = "oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca"}, + {file = "oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918"}, +] + +[package.extras] +rsa = ["cryptography (>=3.0.0)"] +signals = ["blinker (>=1.4.0)"] +signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] + +[[package]] +name = "onnxruntime" +version = "1.17.1" +description = "ONNX Runtime is a runtime accelerator for Machine Learning models" +optional = false +python-versions = "*" +files = [ + {file = "onnxruntime-1.17.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:d43ac17ac4fa3c9096ad3c0e5255bb41fd134560212dc124e7f52c3159af5d21"}, + {file = "onnxruntime-1.17.1-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:55b5e92a4c76a23981c998078b9bf6145e4fb0b016321a8274b1607bd3c6bd35"}, + {file = "onnxruntime-1.17.1-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ebbcd2bc3a066cf54e6f18c75708eb4d309ef42be54606d22e5bdd78afc5b0d7"}, + {file = "onnxruntime-1.17.1-cp310-cp310-win32.whl", hash = "sha256:5e3716b5eec9092e29a8d17aab55e737480487deabfca7eac3cd3ed952b6ada9"}, + {file = "onnxruntime-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:fbb98cced6782ae1bb799cc74ddcbbeeae8819f3ad1d942a74d88e72b6511337"}, + {file = "onnxruntime-1.17.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:36fd6f87a1ecad87e9c652e42407a50fb305374f9a31d71293eb231caae18784"}, + {file = "onnxruntime-1.17.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:99a8bddeb538edabc524d468edb60ad4722cff8a49d66f4e280c39eace70500b"}, + {file = "onnxruntime-1.17.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd7fddb4311deb5a7d3390cd8e9b3912d4d963efbe4dfe075edbaf18d01c024e"}, + {file = "onnxruntime-1.17.1-cp311-cp311-win32.whl", hash = "sha256:606a7cbfb6680202b0e4f1890881041ffc3ac6e41760a25763bd9fe146f0b335"}, + {file = "onnxruntime-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:53e4e06c0a541696ebdf96085fd9390304b7b04b748a19e02cf3b35c869a1e76"}, + {file = "onnxruntime-1.17.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:40f08e378e0f85929712a2b2c9b9a9cc400a90c8a8ca741d1d92c00abec60843"}, + {file = "onnxruntime-1.17.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ac79da6d3e1bb4590f1dad4bb3c2979d7228555f92bb39820889af8b8e6bd472"}, + {file = "onnxruntime-1.17.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ae9ba47dc099004e3781f2d0814ad710a13c868c739ab086fc697524061695ea"}, + {file = "onnxruntime-1.17.1-cp312-cp312-win32.whl", hash = "sha256:2dff1a24354220ac30e4a4ce2fb1df38cb1ea59f7dac2c116238d63fe7f4c5ff"}, + {file = "onnxruntime-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:6226a5201ab8cafb15e12e72ff2a4fc8f50654e8fa5737c6f0bd57c5ff66827e"}, + {file = "onnxruntime-1.17.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:cd0c07c0d1dfb8629e820b05fda5739e4835b3b82faf43753d2998edf2cf00aa"}, + {file = "onnxruntime-1.17.1-cp38-cp38-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:617ebdf49184efa1ba6e4467e602fbfa029ed52c92f13ce3c9f417d303006381"}, + {file = "onnxruntime-1.17.1-cp38-cp38-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9dae9071e3facdf2920769dceee03b71c684b6439021defa45b830d05e148924"}, + {file = "onnxruntime-1.17.1-cp38-cp38-win32.whl", hash = "sha256:835d38fa1064841679433b1aa8138b5e1218ddf0cfa7a3ae0d056d8fd9cec713"}, + {file = "onnxruntime-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:96621e0c555c2453bf607606d08af3f70fbf6f315230c28ddea91754e17ad4e6"}, + {file = "onnxruntime-1.17.1-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:7a9539935fb2d78ebf2cf2693cad02d9930b0fb23cdd5cf37a7df813e977674d"}, + {file = "onnxruntime-1.17.1-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:45c6a384e9d9a29c78afff62032a46a993c477b280247a7e335df09372aedbe9"}, + {file = "onnxruntime-1.17.1-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4e19f966450f16863a1d6182a685ca33ae04d7772a76132303852d05b95411ea"}, + {file = "onnxruntime-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e2ae712d64a42aac29ed7a40a426cb1e624a08cfe9273dcfe681614aa65b07dc"}, + {file = "onnxruntime-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:f7e9f7fb049825cdddf4a923cfc7c649d84d63c0134315f8e0aa9e0c3004672c"}, +] + +[package.dependencies] +coloredlogs = "*" +flatbuffers = "*" +numpy = ">=1.21.6" +packaging = "*" +protobuf = "*" +sympy = "*" + +[[package]] +name = "openai" +version = "1.16.1" +description = "The official Python library for the openai API" +optional = false +python-versions = ">=3.7.1" +files = [ + {file = "openai-1.16.1-py3-none-any.whl", hash = "sha256:77ef3db6110071f7154859e234250fb945a36554207a30a4491092eadb73fcb5"}, + {file = "openai-1.16.1.tar.gz", hash = "sha256:58922c785d167458b46e3c76e7b1bc2306f313ee9b71791e84cbf590abe160f2"}, +] + +[package.dependencies] +anyio = ">=3.5.0,<5" +distro = ">=1.7.0,<2" +httpx = ">=0.23.0,<1" +pydantic = ">=1.9.0,<3" +sniffio = "*" +tqdm = ">4" +typing-extensions = ">=4.7,<5" + +[package.extras] +datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] + +[[package]] +name = "opentelemetry-api" +version = "1.24.0" +description = "OpenTelemetry Python API" +optional = false +python-versions = ">=3.8" +files = [ + {file = "opentelemetry_api-1.24.0-py3-none-any.whl", hash = "sha256:0f2c363d98d10d1ce93330015ca7fd3a65f60be64e05e30f557c61de52c80ca2"}, + {file = "opentelemetry_api-1.24.0.tar.gz", hash = "sha256:42719f10ce7b5a9a73b10a4baf620574fb8ad495a9cbe5c18d76b75d8689c67e"}, +] + +[package.dependencies] +deprecated = ">=1.2.6" +importlib-metadata = ">=6.0,<=7.0" + +[[package]] +name = "opentelemetry-exporter-otlp-proto-common" +version = "1.24.0" +description = "OpenTelemetry Protobuf encoding" +optional = false +python-versions = ">=3.8" +files = [ + {file = "opentelemetry_exporter_otlp_proto_common-1.24.0-py3-none-any.whl", hash = "sha256:e51f2c9735054d598ad2df5d3eca830fecfb5b0bda0a2fa742c9c7718e12f641"}, + {file = "opentelemetry_exporter_otlp_proto_common-1.24.0.tar.gz", hash = "sha256:5d31fa1ff976cacc38be1ec4e3279a3f88435c75b38b1f7a099a1faffc302461"}, +] + +[package.dependencies] +opentelemetry-proto = "1.24.0" + +[[package]] +name = "opentelemetry-exporter-otlp-proto-grpc" +version = "1.24.0" +description = "OpenTelemetry Collector Protobuf over gRPC Exporter" +optional = false +python-versions = ">=3.8" +files = [ + {file = "opentelemetry_exporter_otlp_proto_grpc-1.24.0-py3-none-any.whl", hash = "sha256:f40d62aa30a0a43cc1657428e59fcf82ad5f7ea8fff75de0f9d9cb6f739e0a3b"}, + {file = "opentelemetry_exporter_otlp_proto_grpc-1.24.0.tar.gz", hash = "sha256:217c6e30634f2c9797999ea9da29f7300479a94a610139b9df17433f915e7baa"}, +] + +[package.dependencies] +deprecated = ">=1.2.6" +googleapis-common-protos = ">=1.52,<2.0" +grpcio = ">=1.0.0,<2.0.0" +opentelemetry-api = ">=1.15,<2.0" +opentelemetry-exporter-otlp-proto-common = "1.24.0" +opentelemetry-proto = "1.24.0" +opentelemetry-sdk = ">=1.24.0,<1.25.0" + +[package.extras] +test = ["pytest-grpc"] + +[[package]] +name = "opentelemetry-instrumentation" +version = "0.45b0" +description = "Instrumentation Tools & Auto Instrumentation for OpenTelemetry Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "opentelemetry_instrumentation-0.45b0-py3-none-any.whl", hash = "sha256:06c02e2c952c1b076e8eaedf1b82f715e2937ba7eeacab55913dd434fbcec258"}, + {file = "opentelemetry_instrumentation-0.45b0.tar.gz", hash = "sha256:6c47120a7970bbeb458e6a73686ee9ba84b106329a79e4a4a66761f933709c7e"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.4,<2.0" +setuptools = ">=16.0" +wrapt = ">=1.0.0,<2.0.0" + +[[package]] +name = "opentelemetry-instrumentation-asgi" +version = "0.45b0" +description = "ASGI instrumentation for OpenTelemetry" +optional = false +python-versions = ">=3.8" +files = [ + {file = "opentelemetry_instrumentation_asgi-0.45b0-py3-none-any.whl", hash = "sha256:8be1157ed62f0db24e45fdf7933c530c4338bd025c5d4af7830e903c0756021b"}, + {file = "opentelemetry_instrumentation_asgi-0.45b0.tar.gz", hash = "sha256:97f55620f163fd3d20323e9fd8dc3aacc826c03397213ff36b877e0f4b6b08a6"}, +] + +[package.dependencies] +asgiref = ">=3.0,<4.0" +opentelemetry-api = ">=1.12,<2.0" +opentelemetry-instrumentation = "0.45b0" +opentelemetry-semantic-conventions = "0.45b0" +opentelemetry-util-http = "0.45b0" + +[package.extras] +instruments = ["asgiref (>=3.0,<4.0)"] + +[[package]] +name = "opentelemetry-instrumentation-fastapi" +version = "0.45b0" +description = "OpenTelemetry FastAPI Instrumentation" +optional = false +python-versions = ">=3.8" +files = [ + {file = "opentelemetry_instrumentation_fastapi-0.45b0-py3-none-any.whl", hash = "sha256:77d9c123a363129148f5f66d44094f3d67aaaa2b201396d94782b4a7f9ce4314"}, + {file = "opentelemetry_instrumentation_fastapi-0.45b0.tar.gz", hash = "sha256:5a6b91e1c08a01601845fcfcfdefd0a2aecdb3c356d4a436a3210cb58c21487e"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.12,<2.0" +opentelemetry-instrumentation = "0.45b0" +opentelemetry-instrumentation-asgi = "0.45b0" +opentelemetry-semantic-conventions = "0.45b0" +opentelemetry-util-http = "0.45b0" + +[package.extras] +instruments = ["fastapi (>=0.58,<1.0)"] + +[[package]] +name = "opentelemetry-proto" +version = "1.24.0" +description = "OpenTelemetry Python Proto" +optional = false +python-versions = ">=3.8" +files = [ + {file = "opentelemetry_proto-1.24.0-py3-none-any.whl", hash = "sha256:bcb80e1e78a003040db71ccf83f2ad2019273d1e0828089d183b18a1476527ce"}, + {file = "opentelemetry_proto-1.24.0.tar.gz", hash = "sha256:ff551b8ad63c6cabb1845ce217a6709358dfaba0f75ea1fa21a61ceddc78cab8"}, +] + +[package.dependencies] +protobuf = ">=3.19,<5.0" + +[[package]] +name = "opentelemetry-sdk" +version = "1.24.0" +description = "OpenTelemetry Python SDK" +optional = false +python-versions = ">=3.8" +files = [ + {file = "opentelemetry_sdk-1.24.0-py3-none-any.whl", hash = "sha256:fa731e24efe832e98bcd90902085b359dcfef7d9c9c00eb5b9a18587dae3eb59"}, + {file = "opentelemetry_sdk-1.24.0.tar.gz", hash = "sha256:75bc0563affffa827700e0f4f4a68e1e257db0df13372344aebc6f8a64cde2e5"}, +] + +[package.dependencies] +opentelemetry-api = "1.24.0" +opentelemetry-semantic-conventions = "0.45b0" +typing-extensions = ">=3.7.4" + +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.45b0" +description = "OpenTelemetry Semantic Conventions" +optional = false +python-versions = ">=3.8" +files = [ + {file = "opentelemetry_semantic_conventions-0.45b0-py3-none-any.whl", hash = "sha256:a4a6fb9a7bacd9167c082aa4681009e9acdbfa28ffb2387af50c2fef3d30c864"}, + {file = "opentelemetry_semantic_conventions-0.45b0.tar.gz", hash = "sha256:7c84215a44ac846bc4b8e32d5e78935c5c43482e491812a0bb8aaf87e4d92118"}, +] + +[[package]] +name = "opentelemetry-util-http" +version = "0.45b0" +description = "Web util for OpenTelemetry" +optional = false +python-versions = ">=3.8" +files = [ + {file = "opentelemetry_util_http-0.45b0-py3-none-any.whl", hash = "sha256:6628868b501b3004e1860f976f410eeb3d3499e009719d818000f24ce17b6e33"}, + {file = "opentelemetry_util_http-0.45b0.tar.gz", hash = "sha256:4ce08b6a7d52dd7c96b7705b5b4f06fdb6aa3eac1233b3b0bfef8a0cab9a92cd"}, +] + +[[package]] +name = "orjson" +version = "3.9.15" +description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" +optional = false +python-versions = ">=3.8" +files = [ + {file = "orjson-3.9.15-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:d61f7ce4727a9fa7680cd6f3986b0e2c732639f46a5e0156e550e35258aa313a"}, + {file = "orjson-3.9.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4feeb41882e8aa17634b589533baafdceb387e01e117b1ec65534ec724023d04"}, + {file = "orjson-3.9.15-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fbbeb3c9b2edb5fd044b2a070f127a0ac456ffd079cb82746fc84af01ef021a4"}, + {file = "orjson-3.9.15-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b66bcc5670e8a6b78f0313bcb74774c8291f6f8aeef10fe70e910b8040f3ab75"}, + {file = "orjson-3.9.15-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2973474811db7b35c30248d1129c64fd2bdf40d57d84beed2a9a379a6f57d0ab"}, + {file = "orjson-3.9.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fe41b6f72f52d3da4db524c8653e46243c8c92df826ab5ffaece2dba9cccd58"}, + {file = "orjson-3.9.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4228aace81781cc9d05a3ec3a6d2673a1ad0d8725b4e915f1089803e9efd2b99"}, + {file = "orjson-3.9.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6f7b65bfaf69493c73423ce9db66cfe9138b2f9ef62897486417a8fcb0a92bfe"}, + {file = "orjson-3.9.15-cp310-none-win32.whl", hash = "sha256:2d99e3c4c13a7b0fb3792cc04c2829c9db07838fb6973e578b85c1745e7d0ce7"}, + {file = "orjson-3.9.15-cp310-none-win_amd64.whl", hash = "sha256:b725da33e6e58e4a5d27958568484aa766e825e93aa20c26c91168be58e08cbb"}, + {file = "orjson-3.9.15-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:c8e8fe01e435005d4421f183038fc70ca85d2c1e490f51fb972db92af6e047c2"}, + {file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87f1097acb569dde17f246faa268759a71a2cb8c96dd392cd25c668b104cad2f"}, + {file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ff0f9913d82e1d1fadbd976424c316fbc4d9c525c81d047bbdd16bd27dd98cfc"}, + {file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8055ec598605b0077e29652ccfe9372247474375e0e3f5775c91d9434e12d6b1"}, + {file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d6768a327ea1ba44c9114dba5fdda4a214bdb70129065cd0807eb5f010bfcbb5"}, + {file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12365576039b1a5a47df01aadb353b68223da413e2e7f98c02403061aad34bde"}, + {file = "orjson-3.9.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:71c6b009d431b3839d7c14c3af86788b3cfac41e969e3e1c22f8a6ea13139404"}, + {file = "orjson-3.9.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e18668f1bd39e69b7fed19fa7cd1cd110a121ec25439328b5c89934e6d30d357"}, + {file = "orjson-3.9.15-cp311-none-win32.whl", hash = "sha256:62482873e0289cf7313461009bf62ac8b2e54bc6f00c6fabcde785709231a5d7"}, + {file = "orjson-3.9.15-cp311-none-win_amd64.whl", hash = "sha256:b3d336ed75d17c7b1af233a6561cf421dee41d9204aa3cfcc6c9c65cd5bb69a8"}, + {file = "orjson-3.9.15-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:82425dd5c7bd3adfe4e94c78e27e2fa02971750c2b7ffba648b0f5d5cc016a73"}, + {file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c51378d4a8255b2e7c1e5cc430644f0939539deddfa77f6fac7b56a9784160a"}, + {file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6ae4e06be04dc00618247c4ae3f7c3e561d5bc19ab6941427f6d3722a0875ef7"}, + {file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bcef128f970bb63ecf9a65f7beafd9b55e3aaf0efc271a4154050fc15cdb386e"}, + {file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b72758f3ffc36ca566ba98a8e7f4f373b6c17c646ff8ad9b21ad10c29186f00d"}, + {file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c57bc7b946cf2efa67ac55766e41764b66d40cbd9489041e637c1304400494"}, + {file = "orjson-3.9.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:946c3a1ef25338e78107fba746f299f926db408d34553b4754e90a7de1d44068"}, + {file = "orjson-3.9.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2f256d03957075fcb5923410058982aea85455d035607486ccb847f095442bda"}, + {file = "orjson-3.9.15-cp312-none-win_amd64.whl", hash = "sha256:5bb399e1b49db120653a31463b4a7b27cf2fbfe60469546baf681d1b39f4edf2"}, + {file = "orjson-3.9.15-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:b17f0f14a9c0ba55ff6279a922d1932e24b13fc218a3e968ecdbf791b3682b25"}, + {file = "orjson-3.9.15-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f6cbd8e6e446fb7e4ed5bac4661a29e43f38aeecbf60c4b900b825a353276a1"}, + {file = "orjson-3.9.15-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:76bc6356d07c1d9f4b782813094d0caf1703b729d876ab6a676f3aaa9a47e37c"}, + {file = "orjson-3.9.15-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fdfa97090e2d6f73dced247a2f2d8004ac6449df6568f30e7fa1a045767c69a6"}, + {file = "orjson-3.9.15-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7413070a3e927e4207d00bd65f42d1b780fb0d32d7b1d951f6dc6ade318e1b5a"}, + {file = "orjson-3.9.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9cf1596680ac1f01839dba32d496136bdd5d8ffb858c280fa82bbfeb173bdd40"}, + {file = "orjson-3.9.15-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:809d653c155e2cc4fd39ad69c08fdff7f4016c355ae4b88905219d3579e31eb7"}, + {file = "orjson-3.9.15-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:920fa5a0c5175ab14b9c78f6f820b75804fb4984423ee4c4f1e6d748f8b22bc1"}, + {file = "orjson-3.9.15-cp38-none-win32.whl", hash = "sha256:2b5c0f532905e60cf22a511120e3719b85d9c25d0e1c2a8abb20c4dede3b05a5"}, + {file = "orjson-3.9.15-cp38-none-win_amd64.whl", hash = "sha256:67384f588f7f8daf040114337d34a5188346e3fae6c38b6a19a2fe8c663a2f9b"}, + {file = "orjson-3.9.15-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:6fc2fe4647927070df3d93f561d7e588a38865ea0040027662e3e541d592811e"}, + {file = "orjson-3.9.15-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34cbcd216e7af5270f2ffa63a963346845eb71e174ea530867b7443892d77180"}, + {file = "orjson-3.9.15-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f541587f5c558abd93cb0de491ce99a9ef8d1ae29dd6ab4dbb5a13281ae04cbd"}, + {file = "orjson-3.9.15-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:92255879280ef9c3c0bcb327c5a1b8ed694c290d61a6a532458264f887f052cb"}, + {file = "orjson-3.9.15-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:05a1f57fb601c426635fcae9ddbe90dfc1ed42245eb4c75e4960440cac667262"}, + {file = "orjson-3.9.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ede0bde16cc6e9b96633df1631fbcd66491d1063667f260a4f2386a098393790"}, + {file = "orjson-3.9.15-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e88b97ef13910e5f87bcbc4dd7979a7de9ba8702b54d3204ac587e83639c0c2b"}, + {file = "orjson-3.9.15-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:57d5d8cf9c27f7ef6bc56a5925c7fbc76b61288ab674eb352c26ac780caa5b10"}, + {file = "orjson-3.9.15-cp39-none-win32.whl", hash = "sha256:001f4eb0ecd8e9ebd295722d0cbedf0748680fb9998d3993abaed2f40587257a"}, + {file = "orjson-3.9.15-cp39-none-win_amd64.whl", hash = "sha256:ea0b183a5fe6b2b45f3b854b0d19c4e932d6f5934ae1f723b07cf9560edd4ec7"}, + {file = "orjson-3.9.15.tar.gz", hash = "sha256:95cae920959d772f30ab36d3b25f83bb0f3be671e986c72ce22f8fa700dae061"}, +] + +[[package]] +name = "overrides" +version = "7.7.0" +description = "A decorator to automatically detect mismatch when overriding a method." +optional = false +python-versions = ">=3.6" +files = [ + {file = "overrides-7.7.0-py3-none-any.whl", hash = "sha256:c7ed9d062f78b8e4c1a7b70bd8796b35ead4d9f510227ef9c5dc7626c60d7e49"}, + {file = "overrides-7.7.0.tar.gz", hash = "sha256:55158fa3d93b98cc75299b1e67078ad9003ca27945c76162c1c0766d6f91820a"}, +] + +[[package]] +name = "packaging" +version = "23.2" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, +] + +[[package]] +name = "pandas" +version = "2.2.0" +description = "Powerful data structures for data analysis, time series, and statistics" +optional = false +python-versions = ">=3.9" +files = [ + {file = "pandas-2.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8108ee1712bb4fa2c16981fba7e68b3f6ea330277f5ca34fa8d557e986a11670"}, + {file = "pandas-2.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:736da9ad4033aeab51d067fc3bd69a0ba36f5a60f66a527b3d72e2030e63280a"}, + {file = "pandas-2.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38e0b4fc3ddceb56ec8a287313bc22abe17ab0eb184069f08fc6a9352a769b18"}, + {file = "pandas-2.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20404d2adefe92aed3b38da41d0847a143a09be982a31b85bc7dd565bdba0f4e"}, + {file = "pandas-2.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7ea3ee3f125032bfcade3a4cf85131ed064b4f8dd23e5ce6fa16473e48ebcaf5"}, + {file = "pandas-2.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f9670b3ac00a387620489dfc1bca66db47a787f4e55911f1293063a78b108df1"}, + {file = "pandas-2.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:5a946f210383c7e6d16312d30b238fd508d80d927014f3b33fb5b15c2f895430"}, + {file = "pandas-2.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a1b438fa26b208005c997e78672f1aa8138f67002e833312e6230f3e57fa87d5"}, + {file = "pandas-2.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8ce2fbc8d9bf303ce54a476116165220a1fedf15985b09656b4b4275300e920b"}, + {file = "pandas-2.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2707514a7bec41a4ab81f2ccce8b382961a29fbe9492eab1305bb075b2b1ff4f"}, + {file = "pandas-2.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85793cbdc2d5bc32620dc8ffa715423f0c680dacacf55056ba13454a5be5de88"}, + {file = "pandas-2.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:cfd6c2491dc821b10c716ad6776e7ab311f7df5d16038d0b7458bc0b67dc10f3"}, + {file = "pandas-2.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a146b9dcacc3123aa2b399df1a284de5f46287a4ab4fbfc237eac98a92ebcb71"}, + {file = "pandas-2.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:fbc1b53c0e1fdf16388c33c3cca160f798d38aea2978004dd3f4d3dec56454c9"}, + {file = "pandas-2.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a41d06f308a024981dcaa6c41f2f2be46a6b186b902c94c2674e8cb5c42985bc"}, + {file = "pandas-2.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:159205c99d7a5ce89ecfc37cb08ed179de7783737cea403b295b5eda8e9c56d1"}, + {file = "pandas-2.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb1e1f3861ea9132b32f2133788f3b14911b68102d562715d71bd0013bc45440"}, + {file = "pandas-2.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:761cb99b42a69005dec2b08854fb1d4888fdf7b05db23a8c5a099e4b886a2106"}, + {file = "pandas-2.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a20628faaf444da122b2a64b1e5360cde100ee6283ae8effa0d8745153809a2e"}, + {file = "pandas-2.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f5be5d03ea2073627e7111f61b9f1f0d9625dc3c4d8dda72cc827b0c58a1d042"}, + {file = "pandas-2.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:a626795722d893ed6aacb64d2401d017ddc8a2341b49e0384ab9bf7112bdec30"}, + {file = "pandas-2.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9f66419d4a41132eb7e9a73dcec9486cf5019f52d90dd35547af11bc58f8637d"}, + {file = "pandas-2.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:57abcaeda83fb80d447f28ab0cc7b32b13978f6f733875ebd1ed14f8fbc0f4ab"}, + {file = "pandas-2.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e60f1f7dba3c2d5ca159e18c46a34e7ca7247a73b5dd1a22b6d59707ed6b899a"}, + {file = "pandas-2.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb61dc8567b798b969bcc1fc964788f5a68214d333cade8319c7ab33e2b5d88a"}, + {file = "pandas-2.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:52826b5f4ed658fa2b729264d63f6732b8b29949c7fd234510d57c61dbeadfcd"}, + {file = "pandas-2.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bde2bc699dbd80d7bc7f9cab1e23a95c4375de615860ca089f34e7c64f4a8de7"}, + {file = "pandas-2.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:3de918a754bbf2da2381e8a3dcc45eede8cd7775b047b923f9006d5f876802ae"}, + {file = "pandas-2.2.0.tar.gz", hash = "sha256:30b83f7c3eb217fb4d1b494a57a2fda5444f17834f5df2de6b2ffff68dc3c8e2"}, +] + +[package.dependencies] +numpy = [ + {version = ">=1.22.4,<2", markers = "python_version < \"3.11\""}, + {version = ">=1.23.2,<2", markers = "python_version == \"3.11\""}, +] +python-dateutil = ">=2.8.2" +pytz = ">=2020.1" +tzdata = ">=2022.7" + +[package.extras] +all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] +aws = ["s3fs (>=2022.11.0)"] +clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] +compression = ["zstandard (>=0.19.0)"] +computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] +consortium-standard = ["dataframe-api-compat (>=0.1.7)"] +excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] +feather = ["pyarrow (>=10.0.1)"] +fss = ["fsspec (>=2022.11.0)"] +gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] +hdf5 = ["tables (>=3.8.0)"] +html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] +mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] +output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] +parquet = ["pyarrow (>=10.0.1)"] +performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] +plot = ["matplotlib (>=3.6.3)"] +postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] +spss = ["pyreadstat (>=1.2.0)"] +sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] +test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] +xml = ["lxml (>=4.9.2)"] + +[[package]] +name = "pandas-stubs" +version = "2.2.1.240316" +description = "Type annotations for pandas" +optional = false +python-versions = ">=3.9" +files = [ + {file = "pandas_stubs-2.2.1.240316-py3-none-any.whl", hash = "sha256:0126a26451a37cb893ea62357ca87ba3d181bd999ec8ba2ca5602e20207d6682"}, + {file = "pandas_stubs-2.2.1.240316.tar.gz", hash = "sha256:236a4f812fb6b1922e9607ff09e427f6d8540c421c9e5a40e3e4ddf7adac7f05"}, +] + +[package.dependencies] +numpy = {version = ">=1.26.0", markers = "python_version < \"3.13\""} +types-pytz = ">=2022.1.1" + +[[package]] +name = "parso" +version = "0.8.3" +description = "A Python Parser" +optional = false +python-versions = ">=3.6" +files = [ + {file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"}, + {file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"}, +] + +[package.extras] +qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] +testing = ["docopt", "pytest (<6.0.0)"] + +[[package]] +name = "passlib" +version = "1.7.4" +description = "comprehensive password hashing framework supporting over 30 schemes" +optional = false +python-versions = "*" +files = [ + {file = "passlib-1.7.4-py2.py3-none-any.whl", hash = "sha256:aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1"}, + {file = "passlib-1.7.4.tar.gz", hash = "sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04"}, +] + +[package.extras] +argon2 = ["argon2-cffi (>=18.2.0)"] +bcrypt = ["bcrypt (>=3.1.0)"] +build-docs = ["cloud-sptheme (>=1.10.1)", "sphinx (>=1.6)", "sphinxcontrib-fulltoc (>=1.2.0)"] +totp = ["cryptography"] + +[[package]] +name = "pexpect" +version = "4.9.0" +description = "Pexpect allows easy control of interactive console applications." +optional = false +python-versions = "*" +files = [ + {file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"}, + {file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"}, +] + +[package.dependencies] +ptyprocess = ">=0.5" + +[[package]] +name = "pillow" +version = "10.3.0" +description = "Python Imaging Library (Fork)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pillow-10.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:90b9e29824800e90c84e4022dd5cc16eb2d9605ee13f05d47641eb183cd73d45"}, + {file = "pillow-10.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a2c405445c79c3f5a124573a051062300936b0281fee57637e706453e452746c"}, + {file = "pillow-10.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78618cdbccaa74d3f88d0ad6cb8ac3007f1a6fa5c6f19af64b55ca170bfa1edf"}, + {file = "pillow-10.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:261ddb7ca91fcf71757979534fb4c128448b5b4c55cb6152d280312062f69599"}, + {file = "pillow-10.3.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:ce49c67f4ea0609933d01c0731b34b8695a7a748d6c8d186f95e7d085d2fe475"}, + {file = "pillow-10.3.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:b14f16f94cbc61215115b9b1236f9c18403c15dd3c52cf629072afa9d54c1cbf"}, + {file = "pillow-10.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d33891be6df59d93df4d846640f0e46f1a807339f09e79a8040bc887bdcd7ed3"}, + {file = "pillow-10.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b50811d664d392f02f7761621303eba9d1b056fb1868c8cdf4231279645c25f5"}, + {file = "pillow-10.3.0-cp310-cp310-win32.whl", hash = "sha256:ca2870d5d10d8726a27396d3ca4cf7976cec0f3cb706debe88e3a5bd4610f7d2"}, + {file = "pillow-10.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:f0d0591a0aeaefdaf9a5e545e7485f89910c977087e7de2b6c388aec32011e9f"}, + {file = "pillow-10.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:ccce24b7ad89adb5a1e34a6ba96ac2530046763912806ad4c247356a8f33a67b"}, + {file = "pillow-10.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:5f77cf66e96ae734717d341c145c5949c63180842a545c47a0ce7ae52ca83795"}, + {file = "pillow-10.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e4b878386c4bf293578b48fc570b84ecfe477d3b77ba39a6e87150af77f40c57"}, + {file = "pillow-10.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdcbb4068117dfd9ce0138d068ac512843c52295ed996ae6dd1faf537b6dbc27"}, + {file = "pillow-10.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9797a6c8fe16f25749b371c02e2ade0efb51155e767a971c61734b1bf6293994"}, + {file = "pillow-10.3.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:9e91179a242bbc99be65e139e30690e081fe6cb91a8e77faf4c409653de39451"}, + {file = "pillow-10.3.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:1b87bd9d81d179bd8ab871603bd80d8645729939f90b71e62914e816a76fc6bd"}, + {file = "pillow-10.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:81d09caa7b27ef4e61cb7d8fbf1714f5aec1c6b6c5270ee53504981e6e9121ad"}, + {file = "pillow-10.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:048ad577748b9fa4a99a0548c64f2cb8d672d5bf2e643a739ac8faff1164238c"}, + {file = "pillow-10.3.0-cp311-cp311-win32.whl", hash = "sha256:7161ec49ef0800947dc5570f86568a7bb36fa97dd09e9827dc02b718c5643f09"}, + {file = "pillow-10.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:8eb0908e954d093b02a543dc963984d6e99ad2b5e36503d8a0aaf040505f747d"}, + {file = "pillow-10.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:4e6f7d1c414191c1199f8996d3f2282b9ebea0945693fb67392c75a3a320941f"}, + {file = "pillow-10.3.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:e46f38133e5a060d46bd630faa4d9fa0202377495df1f068a8299fd78c84de84"}, + {file = "pillow-10.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:50b8eae8f7334ec826d6eeffaeeb00e36b5e24aa0b9df322c247539714c6df19"}, + {file = "pillow-10.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d3bea1c75f8c53ee4d505c3e67d8c158ad4df0d83170605b50b64025917f338"}, + {file = "pillow-10.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19aeb96d43902f0a783946a0a87dbdad5c84c936025b8419da0a0cd7724356b1"}, + {file = "pillow-10.3.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:74d28c17412d9caa1066f7a31df8403ec23d5268ba46cd0ad2c50fb82ae40462"}, + {file = "pillow-10.3.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:ff61bfd9253c3915e6d41c651d5f962da23eda633cf02262990094a18a55371a"}, + {file = "pillow-10.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d886f5d353333b4771d21267c7ecc75b710f1a73d72d03ca06df49b09015a9ef"}, + {file = "pillow-10.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b5ec25d8b17217d635f8935dbc1b9aa5907962fae29dff220f2659487891cd3"}, + {file = "pillow-10.3.0-cp312-cp312-win32.whl", hash = "sha256:51243f1ed5161b9945011a7360e997729776f6e5d7005ba0c6879267d4c5139d"}, + {file = "pillow-10.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:412444afb8c4c7a6cc11a47dade32982439925537e483be7c0ae0cf96c4f6a0b"}, + {file = "pillow-10.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:798232c92e7665fe82ac085f9d8e8ca98826f8e27859d9a96b41d519ecd2e49a"}, + {file = "pillow-10.3.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:4eaa22f0d22b1a7e93ff0a596d57fdede2e550aecffb5a1ef1106aaece48e96b"}, + {file = "pillow-10.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cd5e14fbf22a87321b24c88669aad3a51ec052eb145315b3da3b7e3cc105b9a2"}, + {file = "pillow-10.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1530e8f3a4b965eb6a7785cf17a426c779333eb62c9a7d1bbcf3ffd5bf77a4aa"}, + {file = "pillow-10.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d512aafa1d32efa014fa041d38868fda85028e3f930a96f85d49c7d8ddc0383"}, + {file = "pillow-10.3.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:339894035d0ede518b16073bdc2feef4c991ee991a29774b33e515f1d308e08d"}, + {file = "pillow-10.3.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:aa7e402ce11f0885305bfb6afb3434b3cd8f53b563ac065452d9d5654c7b86fd"}, + {file = "pillow-10.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0ea2a783a2bdf2a561808fe4a7a12e9aa3799b701ba305de596bc48b8bdfce9d"}, + {file = "pillow-10.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c78e1b00a87ce43bb37642c0812315b411e856a905d58d597750eb79802aaaa3"}, + {file = "pillow-10.3.0-cp38-cp38-win32.whl", hash = "sha256:72d622d262e463dfb7595202d229f5f3ab4b852289a1cd09650362db23b9eb0b"}, + {file = "pillow-10.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:2034f6759a722da3a3dbd91a81148cf884e91d1b747992ca288ab88c1de15999"}, + {file = "pillow-10.3.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:2ed854e716a89b1afcedea551cd85f2eb2a807613752ab997b9974aaa0d56936"}, + {file = "pillow-10.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:dc1a390a82755a8c26c9964d457d4c9cbec5405896cba94cf51f36ea0d855002"}, + {file = "pillow-10.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4203efca580f0dd6f882ca211f923168548f7ba334c189e9eab1178ab840bf60"}, + {file = "pillow-10.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3102045a10945173d38336f6e71a8dc71bcaeed55c3123ad4af82c52807b9375"}, + {file = "pillow-10.3.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:6fb1b30043271ec92dc65f6d9f0b7a830c210b8a96423074b15c7bc999975f57"}, + {file = "pillow-10.3.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:1dfc94946bc60ea375cc39cff0b8da6c7e5f8fcdc1d946beb8da5c216156ddd8"}, + {file = "pillow-10.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b09b86b27a064c9624d0a6c54da01c1beaf5b6cadfa609cf63789b1d08a797b9"}, + {file = "pillow-10.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d3b2348a78bc939b4fed6552abfd2e7988e0f81443ef3911a4b8498ca084f6eb"}, + {file = "pillow-10.3.0-cp39-cp39-win32.whl", hash = "sha256:45ebc7b45406febf07fef35d856f0293a92e7417ae7933207e90bf9090b70572"}, + {file = "pillow-10.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:0ba26351b137ca4e0db0342d5d00d2e355eb29372c05afd544ebf47c0956ffeb"}, + {file = "pillow-10.3.0-cp39-cp39-win_arm64.whl", hash = "sha256:50fd3f6b26e3441ae07b7c979309638b72abc1a25da31a81a7fbd9495713ef4f"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:6b02471b72526ab8a18c39cb7967b72d194ec53c1fd0a70b050565a0f366d355"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8ab74c06ffdab957d7670c2a5a6e1a70181cd10b727cd788c4dd9005b6a8acd9"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:048eeade4c33fdf7e08da40ef402e748df113fd0b4584e32c4af74fe78baaeb2"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e2ec1e921fd07c7cda7962bad283acc2f2a9ccc1b971ee4b216b75fad6f0463"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:4c8e73e99da7db1b4cad7f8d682cf6abad7844da39834c288fbfa394a47bbced"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:16563993329b79513f59142a6b02055e10514c1a8e86dca8b48a893e33cf91e3"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:dd78700f5788ae180b5ee8902c6aea5a5726bac7c364b202b4b3e3ba2d293170"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:aff76a55a8aa8364d25400a210a65ff59d0168e0b4285ba6bf2bd83cf675ba32"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:b7bc2176354defba3edc2b9a777744462da2f8e921fbaf61e52acb95bafa9828"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:793b4e24db2e8742ca6423d3fde8396db336698c55cd34b660663ee9e45ed37f"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d93480005693d247f8346bc8ee28c72a2191bdf1f6b5db469c096c0c867ac015"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c83341b89884e2b2e55886e8fbbf37c3fa5efd6c8907124aeb72f285ae5696e5"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1a1d1915db1a4fdb2754b9de292642a39a7fb28f1736699527bb649484fb966a"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a0eaa93d054751ee9964afa21c06247779b90440ca41d184aeb5d410f20ff591"}, + {file = "pillow-10.3.0.tar.gz", hash = "sha256:9d2455fbf44c914840c793e89aa82d0e1763a14253a000743719ae5946814b2d"}, +] + +[package.extras] +docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"] +fpx = ["olefile"] +mic = ["olefile"] +tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] +typing = ["typing-extensions"] +xmp = ["defusedxml"] + +[[package]] +name = "platformdirs" +version = "4.2.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +optional = false +python-versions = ">=3.8" +files = [ + {file = "platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068"}, + {file = "platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768"}, +] + +[package.extras] +docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] + +[[package]] +name = "pluggy" +version = "1.4.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, + {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "posthog" +version = "3.5.0" +description = "Integrate PostHog into any python application." +optional = false +python-versions = "*" +files = [ + {file = "posthog-3.5.0-py2.py3-none-any.whl", hash = "sha256:3c672be7ba6f95d555ea207d4486c171d06657eb34b3ce25eb043bfe7b6b5b76"}, + {file = "posthog-3.5.0.tar.gz", hash = "sha256:8f7e3b2c6e8714d0c0c542a2109b83a7549f63b7113a133ab2763a89245ef2ef"}, +] + +[package.dependencies] +backoff = ">=1.10.0" +monotonic = ">=1.5" +python-dateutil = ">2.1" +requests = ">=2.7,<3.0" +six = ">=1.5" + +[package.extras] +dev = ["black", "flake8", "flake8-print", "isort", "pre-commit"] +sentry = ["django", "sentry-sdk"] +test = ["coverage", "flake8", "freezegun (==0.3.15)", "mock (>=2.0.0)", "pylint", "pytest", "pytest-timeout"] + +[[package]] +name = "prompt-toolkit" +version = "3.0.43" +description = "Library for building powerful interactive command lines in Python" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "prompt_toolkit-3.0.43-py3-none-any.whl", hash = "sha256:a11a29cb3bf0a28a387fe5122cdb649816a957cd9261dcedf8c9f1fef33eacf6"}, + {file = "prompt_toolkit-3.0.43.tar.gz", hash = "sha256:3527b7af26106cbc65a040bcc84839a3566ec1b051bb0bfe953631e704b0ff7d"}, +] + +[package.dependencies] +wcwidth = "*" + +[[package]] +name = "protobuf" +version = "4.25.3" +description = "" +optional = false +python-versions = ">=3.8" +files = [ + {file = "protobuf-4.25.3-cp310-abi3-win32.whl", hash = "sha256:d4198877797a83cbfe9bffa3803602bbe1625dc30d8a097365dbc762e5790faa"}, + {file = "protobuf-4.25.3-cp310-abi3-win_amd64.whl", hash = "sha256:209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8"}, + {file = "protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c"}, + {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019"}, + {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d"}, + {file = "protobuf-4.25.3-cp38-cp38-win32.whl", hash = "sha256:f4f118245c4a087776e0a8408be33cf09f6c547442c00395fbfb116fac2f8ac2"}, + {file = "protobuf-4.25.3-cp38-cp38-win_amd64.whl", hash = "sha256:c053062984e61144385022e53678fbded7aea14ebb3e0305ae3592fb219ccfa4"}, + {file = "protobuf-4.25.3-cp39-cp39-win32.whl", hash = "sha256:19b270aeaa0099f16d3ca02628546b8baefe2955bbe23224aaf856134eccf1e4"}, + {file = "protobuf-4.25.3-cp39-cp39-win_amd64.whl", hash = "sha256:e3c97a1555fd6388f857770ff8b9703083de6bf1f9274a002a332d65fbb56c8c"}, + {file = "protobuf-4.25.3-py3-none-any.whl", hash = "sha256:f0700d54bcf45424477e46a9f0944155b46fb0639d69728739c0e47bab83f2b9"}, + {file = "protobuf-4.25.3.tar.gz", hash = "sha256:25b5d0b42fd000320bd7830b349e3b696435f3b329810427a6bcce6a5492cc5c"}, +] + +[[package]] +name = "psutil" +version = "5.9.8" +description = "Cross-platform lib for process and system monitoring in Python." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +files = [ + {file = "psutil-5.9.8-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:26bd09967ae00920df88e0352a91cff1a78f8d69b3ecabbfe733610c0af486c8"}, + {file = "psutil-5.9.8-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:05806de88103b25903dff19bb6692bd2e714ccf9e668d050d144012055cbca73"}, + {file = "psutil-5.9.8-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:611052c4bc70432ec770d5d54f64206aa7203a101ec273a0cd82418c86503bb7"}, + {file = "psutil-5.9.8-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:50187900d73c1381ba1454cf40308c2bf6f34268518b3f36a9b663ca87e65e36"}, + {file = "psutil-5.9.8-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:02615ed8c5ea222323408ceba16c60e99c3f91639b07da6373fb7e6539abc56d"}, + {file = "psutil-5.9.8-cp27-none-win32.whl", hash = "sha256:36f435891adb138ed3c9e58c6af3e2e6ca9ac2f365efe1f9cfef2794e6c93b4e"}, + {file = "psutil-5.9.8-cp27-none-win_amd64.whl", hash = "sha256:bd1184ceb3f87651a67b2708d4c3338e9b10c5df903f2e3776b62303b26cb631"}, + {file = "psutil-5.9.8-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:aee678c8720623dc456fa20659af736241f575d79429a0e5e9cf88ae0605cc81"}, + {file = "psutil-5.9.8-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cb6403ce6d8e047495a701dc7c5bd788add903f8986d523e3e20b98b733e421"}, + {file = "psutil-5.9.8-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d06016f7f8625a1825ba3732081d77c94589dca78b7a3fc072194851e88461a4"}, + {file = "psutil-5.9.8-cp36-cp36m-win32.whl", hash = "sha256:7d79560ad97af658a0f6adfef8b834b53f64746d45b403f225b85c5c2c140eee"}, + {file = "psutil-5.9.8-cp36-cp36m-win_amd64.whl", hash = "sha256:27cc40c3493bb10de1be4b3f07cae4c010ce715290a5be22b98493509c6299e2"}, + {file = "psutil-5.9.8-cp37-abi3-win32.whl", hash = "sha256:bc56c2a1b0d15aa3eaa5a60c9f3f8e3e565303b465dbf57a1b730e7a2b9844e0"}, + {file = "psutil-5.9.8-cp37-abi3-win_amd64.whl", hash = "sha256:8db4c1b57507eef143a15a6884ca10f7c73876cdf5d51e713151c1236a0e68cf"}, + {file = "psutil-5.9.8-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:d16bbddf0693323b8c6123dd804100241da461e41d6e332fb0ba6058f630f8c8"}, + {file = "psutil-5.9.8.tar.gz", hash = "sha256:6be126e3225486dff286a8fb9a06246a5253f4c7c53b475ea5f5ac934e64194c"}, +] + +[package.extras] +test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] + +[[package]] +name = "ptyprocess" +version = "0.7.0" +description = "Run a subprocess in a pseudo terminal" +optional = false +python-versions = "*" +files = [ + {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, + {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, +] + +[[package]] +name = "pulsar-client" +version = "3.4.0" +description = "Apache Pulsar Python client library" +optional = false +python-versions = "*" +files = [ + {file = "pulsar_client-3.4.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:ebf99db5244ff69479283b25621b070492acc4bb643d162d86b90387cb6fdb2a"}, + {file = "pulsar_client-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6cb5d8e1482a8aea758633be23717e0c4bb7dc53784e37915c0048c0382f134"}, + {file = "pulsar_client-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b30a7592e42c76034e9a8d64d42dd5bab361425f869de562e9ccad698e19cd88"}, + {file = "pulsar_client-3.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5963090a78a5644ba25f41da3a6d49ea3f00c972b095baff365916dc246426a"}, + {file = "pulsar_client-3.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:419cdcf577f755e3f31bf264300d9ba158325edb2ee9cee555d81ba1909c094e"}, + {file = "pulsar_client-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:4c93c35ee97307dae153e748b33dcd3d4f06da34bca373321aa2df73f1535705"}, + {file = "pulsar_client-3.4.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:11952fb022ee72debf53b169f4482f9dc5c890be0149ae98779864b3a21f1bd3"}, + {file = "pulsar_client-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8743c320aa96798d20cafa98ea97a68c4295fc4872c23acd5e012fd36cb06ba"}, + {file = "pulsar_client-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33571de99cd898349f17978ba62e2b839ea0275fb7067f31bf5f6ebfeae0987d"}, + {file = "pulsar_client-3.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a60c03c3e70f018538e7cd3fa84d95e283b610272b744166dbc48960a809fa07"}, + {file = "pulsar_client-3.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4c47041267b5843ffec54352d842156c279945f3e976d7025ffa89875ff76390"}, + {file = "pulsar_client-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:49fe4ab04004b476c87ab3ad22fe87346fca564a3e3ca9c0ac58fee45a895d81"}, + {file = "pulsar_client-3.4.0-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:1e077a4839be3ead3de3f05b4c244269dca2df07f47cea0b90544c7e9dc1642f"}, + {file = "pulsar_client-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f202b84e1f683d64672dd1971114600ae2e5c3735587286ff9bfb431385f08e8"}, + {file = "pulsar_client-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c606c04f357341042fa6c75477de7d2204f7ae50aa29c2f74b24e54c85f47f96"}, + {file = "pulsar_client-3.4.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c67b25ede3a578f5a7dc30230e52609ef38191f74b47e5cbdbc98c42df556927"}, + {file = "pulsar_client-3.4.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b7f8211cc9460cdf4d06e4e1cb878689d2aa4a7e4027bd2a2f1419a79ade16a6"}, + {file = "pulsar_client-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:c5399e9780d6951c69808c0b6175311a966af82fb08addf6e741ae37b1bee7ef"}, + {file = "pulsar_client-3.4.0-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:a2d6c850b60106dc915d3476a490fba547c6748a5f742b68abd30d1a35355b82"}, + {file = "pulsar_client-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a52ea8294a9f30eb6f0a2db5dc16e3aad7ff2284f818c48ad3a6b601723be02b"}, + {file = "pulsar_client-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1eeeede40108be12222e009285c971e5b8f6433d9f0f8ef934d6a131585921c4"}, + {file = "pulsar_client-3.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9409066c600f2b6f220552c5dfe08aeeabcf07fe0e76367aa5816b2e87a5cf72"}, + {file = "pulsar_client-3.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:58e2f886e6dab43e66c3ce990fe96209e55ab46350506829a637b77b74125fb9"}, + {file = "pulsar_client-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:b57dfa5063b0d9dc7664896c55605eac90753e35e80db5a959d3be2be0ab0d48"}, + {file = "pulsar_client-3.4.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:7704c664aa2c801af4c2d3a58e9d8ffaeef12ce8a0f71712e9187f9a96da856f"}, + {file = "pulsar_client-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0364db563e27442053bdbb8655e7ffb420f491690bc2c78da5a58bd35c658ad"}, + {file = "pulsar_client-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3e34de19e0744d8aa3538cb2172076bccd0761b3e94ebadb7bd59765ae3d1ed"}, + {file = "pulsar_client-3.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:dc8be41dec8cb052fb1837550f495e9b73a8b3cf85e07157904ec84832758a65"}, + {file = "pulsar_client-3.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b49d669bed15b7edb9c936704310d57808f1d01c511b94d866f54fe8ffe1752d"}, + {file = "pulsar_client-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:88c93e5fbfc349f3967e931f7a908d15fd4fd725ebdd842423ac9cd961fe293f"}, +] + +[package.dependencies] +certifi = "*" + +[package.extras] +all = ["apache-bookkeeper-client (>=4.16.1)", "fastavro (>=1.9.2)", "grpcio (>=1.60.0)", "prometheus-client", "protobuf (>=3.6.1,<=3.20.3)", "ratelimit"] +avro = ["fastavro (>=1.9.2)"] +functions = ["apache-bookkeeper-client (>=4.16.1)", "grpcio (>=1.60.0)", "prometheus-client", "protobuf (>=3.6.1,<=3.20.3)", "ratelimit"] + +[[package]] +name = "pure-eval" +version = "0.2.2" +description = "Safely evaluate AST nodes without side effects" +optional = false +python-versions = "*" +files = [ + {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"}, + {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"}, +] + +[package.extras] +tests = ["pytest"] + +[[package]] +name = "pyasn1" +version = "0.6.0" +description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyasn1-0.6.0-py2.py3-none-any.whl", hash = "sha256:cca4bb0f2df5504f02f6f8a775b6e416ff9b0b3b16f7ee80b5a3153d9b804473"}, + {file = "pyasn1-0.6.0.tar.gz", hash = "sha256:3a35ab2c4b5ef98e17dfdec8ab074046fbda76e281c5a706ccd82328cfc8f64c"}, +] + +[[package]] +name = "pyasn1-modules" +version = "0.4.0" +description = "A collection of ASN.1-based protocols modules" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyasn1_modules-0.4.0-py3-none-any.whl", hash = "sha256:be04f15b66c206eed667e0bb5ab27e2b1855ea54a842e5037738099e8ca4ae0b"}, + {file = "pyasn1_modules-0.4.0.tar.gz", hash = "sha256:831dbcea1b177b28c9baddf4c6d1013c24c3accd14a1873fffaa6a2e905f17b6"}, +] + +[package.dependencies] +pyasn1 = ">=0.4.6,<0.7.0" + +[[package]] +name = "pycparser" +version = "2.22" +description = "C parser in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, + {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, +] + +[[package]] +name = "pydantic" +version = "2.6.4" +description = "Data validation using Python type hints" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic-2.6.4-py3-none-any.whl", hash = "sha256:cc46fce86607580867bdc3361ad462bab9c222ef042d3da86f2fb333e1d916c5"}, + {file = "pydantic-2.6.4.tar.gz", hash = "sha256:b1704e0847db01817624a6b86766967f552dd9dbf3afba4004409f908dcc84e6"}, +] + +[package.dependencies] +annotated-types = ">=0.4.0" +pydantic-core = "2.16.3" +typing-extensions = ">=4.6.1" + +[package.extras] +email = ["email-validator (>=2.0.0)"] + +[[package]] +name = "pydantic-core" +version = "2.16.3" +description = "" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic_core-2.16.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:75b81e678d1c1ede0785c7f46690621e4c6e63ccd9192af1f0bd9d504bbb6bf4"}, + {file = "pydantic_core-2.16.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9c865a7ee6f93783bd5d781af5a4c43dadc37053a5b42f7d18dc019f8c9d2bd1"}, + {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:162e498303d2b1c036b957a1278fa0899d02b2842f1ff901b6395104c5554a45"}, + {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f583bd01bbfbff4eaee0868e6fc607efdfcc2b03c1c766b06a707abbc856187"}, + {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b926dd38db1519ed3043a4de50214e0d600d404099c3392f098a7f9d75029ff8"}, + {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:716b542728d4c742353448765aa7cdaa519a7b82f9564130e2b3f6766018c9ec"}, + {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc4ad7f7ee1a13d9cb49d8198cd7d7e3aa93e425f371a68235f784e99741561f"}, + {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd87f48924f360e5d1c5f770d6155ce0e7d83f7b4e10c2f9ec001c73cf475c99"}, + {file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0df446663464884297c793874573549229f9eca73b59360878f382a0fc085979"}, + {file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4df8a199d9f6afc5ae9a65f8f95ee52cae389a8c6b20163762bde0426275b7db"}, + {file = "pydantic_core-2.16.3-cp310-none-win32.whl", hash = "sha256:456855f57b413f077dff513a5a28ed838dbbb15082ba00f80750377eed23d132"}, + {file = "pydantic_core-2.16.3-cp310-none-win_amd64.whl", hash = "sha256:732da3243e1b8d3eab8c6ae23ae6a58548849d2e4a4e03a1924c8ddf71a387cb"}, + {file = "pydantic_core-2.16.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:519ae0312616026bf4cedc0fe459e982734f3ca82ee8c7246c19b650b60a5ee4"}, + {file = "pydantic_core-2.16.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b3992a322a5617ded0a9f23fd06dbc1e4bd7cf39bc4ccf344b10f80af58beacd"}, + {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d62da299c6ecb04df729e4b5c52dc0d53f4f8430b4492b93aa8de1f541c4aac"}, + {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2acca2be4bb2f2147ada8cac612f8a98fc09f41c89f87add7256ad27332c2fda"}, + {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b662180108c55dfbf1280d865b2d116633d436cfc0bba82323554873967b340"}, + {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e7c6ed0dc9d8e65f24f5824291550139fe6f37fac03788d4580da0d33bc00c97"}, + {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1bb0827f56654b4437955555dc3aeeebeddc47c2d7ed575477f082622c49e"}, + {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e56f8186d6210ac7ece503193ec84104da7ceb98f68ce18c07282fcc2452e76f"}, + {file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:936e5db01dd49476fa8f4383c259b8b1303d5dd5fb34c97de194560698cc2c5e"}, + {file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:33809aebac276089b78db106ee692bdc9044710e26f24a9a2eaa35a0f9fa70ba"}, + {file = "pydantic_core-2.16.3-cp311-none-win32.whl", hash = "sha256:ded1c35f15c9dea16ead9bffcde9bb5c7c031bff076355dc58dcb1cb436c4721"}, + {file = "pydantic_core-2.16.3-cp311-none-win_amd64.whl", hash = "sha256:d89ca19cdd0dd5f31606a9329e309d4fcbb3df860960acec32630297d61820df"}, + {file = "pydantic_core-2.16.3-cp311-none-win_arm64.whl", hash = "sha256:6162f8d2dc27ba21027f261e4fa26f8bcb3cf9784b7f9499466a311ac284b5b9"}, + {file = "pydantic_core-2.16.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0f56ae86b60ea987ae8bcd6654a887238fd53d1384f9b222ac457070b7ac4cff"}, + {file = "pydantic_core-2.16.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9bd22a2a639e26171068f8ebb5400ce2c1bc7d17959f60a3b753ae13c632975"}, + {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4204e773b4b408062960e65468d5346bdfe139247ee5f1ca2a378983e11388a2"}, + {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f651dd19363c632f4abe3480a7c87a9773be27cfe1341aef06e8759599454120"}, + {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aaf09e615a0bf98d406657e0008e4a8701b11481840be7d31755dc9f97c44053"}, + {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8e47755d8152c1ab5b55928ab422a76e2e7b22b5ed8e90a7d584268dd49e9c6b"}, + {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:500960cb3a0543a724a81ba859da816e8cf01b0e6aaeedf2c3775d12ee49cade"}, + {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cf6204fe865da605285c34cf1172879d0314ff267b1c35ff59de7154f35fdc2e"}, + {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d33dd21f572545649f90c38c227cc8631268ba25c460b5569abebdd0ec5974ca"}, + {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:49d5d58abd4b83fb8ce763be7794d09b2f50f10aa65c0f0c1696c677edeb7cbf"}, + {file = "pydantic_core-2.16.3-cp312-none-win32.whl", hash = "sha256:f53aace168a2a10582e570b7736cc5bef12cae9cf21775e3eafac597e8551fbe"}, + {file = "pydantic_core-2.16.3-cp312-none-win_amd64.whl", hash = "sha256:0d32576b1de5a30d9a97f300cc6a3f4694c428d956adbc7e6e2f9cad279e45ed"}, + {file = "pydantic_core-2.16.3-cp312-none-win_arm64.whl", hash = "sha256:ec08be75bb268473677edb83ba71e7e74b43c008e4a7b1907c6d57e940bf34b6"}, + {file = "pydantic_core-2.16.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b1f6f5938d63c6139860f044e2538baeee6f0b251a1816e7adb6cbce106a1f01"}, + {file = "pydantic_core-2.16.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2a1ef6a36fdbf71538142ed604ad19b82f67b05749512e47f247a6ddd06afdc7"}, + {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:704d35ecc7e9c31d48926150afada60401c55efa3b46cd1ded5a01bdffaf1d48"}, + {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d937653a696465677ed583124b94a4b2d79f5e30b2c46115a68e482c6a591c8a"}, + {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9803edf8e29bd825f43481f19c37f50d2b01899448273b3a7758441b512acf8"}, + {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:72282ad4892a9fb2da25defeac8c2e84352c108705c972db82ab121d15f14e6d"}, + {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f752826b5b8361193df55afcdf8ca6a57d0232653494ba473630a83ba50d8c9"}, + {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4384a8f68ddb31a0b0c3deae88765f5868a1b9148939c3f4121233314ad5532c"}, + {file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a4b2bf78342c40b3dc830880106f54328928ff03e357935ad26c7128bbd66ce8"}, + {file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:13dcc4802961b5f843a9385fc821a0b0135e8c07fc3d9949fd49627c1a5e6ae5"}, + {file = "pydantic_core-2.16.3-cp38-none-win32.whl", hash = "sha256:e3e70c94a0c3841e6aa831edab1619ad5c511199be94d0c11ba75fe06efe107a"}, + {file = "pydantic_core-2.16.3-cp38-none-win_amd64.whl", hash = "sha256:ecdf6bf5f578615f2e985a5e1f6572e23aa632c4bd1dc67f8f406d445ac115ed"}, + {file = "pydantic_core-2.16.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:bda1ee3e08252b8d41fa5537413ffdddd58fa73107171a126d3b9ff001b9b820"}, + {file = "pydantic_core-2.16.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:21b888c973e4f26b7a96491c0965a8a312e13be108022ee510248fe379a5fa23"}, + {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be0ec334369316fa73448cc8c982c01e5d2a81c95969d58b8f6e272884df0074"}, + {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5b6079cc452a7c53dd378c6f881ac528246b3ac9aae0f8eef98498a75657805"}, + {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ee8d5f878dccb6d499ba4d30d757111847b6849ae07acdd1205fffa1fc1253c"}, + {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7233d65d9d651242a68801159763d09e9ec96e8a158dbf118dc090cd77a104c9"}, + {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6119dc90483a5cb50a1306adb8d52c66e447da88ea44f323e0ae1a5fcb14256"}, + {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:578114bc803a4c1ff9946d977c221e4376620a46cf78da267d946397dc9514a8"}, + {file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d8f99b147ff3fcf6b3cc60cb0c39ea443884d5559a30b1481e92495f2310ff2b"}, + {file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4ac6b4ce1e7283d715c4b729d8f9dab9627586dafce81d9eaa009dd7f25dd972"}, + {file = "pydantic_core-2.16.3-cp39-none-win32.whl", hash = "sha256:e7774b570e61cb998490c5235740d475413a1f6de823169b4cf94e2fe9e9f6b2"}, + {file = "pydantic_core-2.16.3-cp39-none-win_amd64.whl", hash = "sha256:9091632a25b8b87b9a605ec0e61f241c456e9248bfdcf7abdf344fdb169c81cf"}, + {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:36fa178aacbc277bc6b62a2c3da95226520da4f4e9e206fdf076484363895d2c"}, + {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:dcca5d2bf65c6fb591fff92da03f94cd4f315972f97c21975398bd4bd046854a"}, + {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a72fb9963cba4cd5793854fd12f4cfee731e86df140f59ff52a49b3552db241"}, + {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b60cc1a081f80a2105a59385b92d82278b15d80ebb3adb200542ae165cd7d183"}, + {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cbcc558401de90a746d02ef330c528f2e668c83350f045833543cd57ecead1ad"}, + {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:fee427241c2d9fb7192b658190f9f5fd6dfe41e02f3c1489d2ec1e6a5ab1e04a"}, + {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f4cb85f693044e0f71f394ff76c98ddc1bc0953e48c061725e540396d5c8a2e1"}, + {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b29eeb887aa931c2fcef5aa515d9d176d25006794610c264ddc114c053bf96fe"}, + {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a425479ee40ff021f8216c9d07a6a3b54b31c8267c6e17aa88b70d7ebd0e5e5b"}, + {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5c5cbc703168d1b7a838668998308018a2718c2130595e8e190220238addc96f"}, + {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99b6add4c0b39a513d323d3b93bc173dac663c27b99860dd5bf491b240d26137"}, + {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f76ee558751746d6a38f89d60b6228fa174e5172d143886af0f85aa306fd89"}, + {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:00ee1c97b5364b84cb0bd82e9bbf645d5e2871fb8c58059d158412fee2d33d8a"}, + {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:287073c66748f624be4cef893ef9174e3eb88fe0b8a78dc22e88eca4bc357ca6"}, + {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ed25e1835c00a332cb10c683cd39da96a719ab1dfc08427d476bce41b92531fc"}, + {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:86b3d0033580bd6bbe07590152007275bd7af95f98eaa5bd36f3da219dcd93da"}, + {file = "pydantic_core-2.16.3.tar.gz", hash = "sha256:1cac689f80a3abab2d3c0048b29eea5751114054f032a941a32de4c852c59cad"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" + +[[package]] +name = "pydantic-settings" +version = "2.2.1" +description = "Settings management using Pydantic" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic_settings-2.2.1-py3-none-any.whl", hash = "sha256:0235391d26db4d2190cb9b31051c4b46882d28a51533f97440867f012d4da091"}, + {file = "pydantic_settings-2.2.1.tar.gz", hash = "sha256:00b9f6a5e95553590434c0fa01ead0b216c3e10bc54ae02e37f359948643c5ed"}, +] + +[package.dependencies] +pydantic = ">=2.3.0" +python-dotenv = ">=0.21.0" + +[package.extras] +toml = ["tomli (>=2.0.1)"] +yaml = ["pyyaml (>=6.0.1)"] + +[[package]] +name = "pygments" +version = "2.17.2" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"}, + {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"}, +] + +[package.extras] +plugins = ["importlib-metadata"] +windows-terminal = ["colorama (>=0.4.6)"] + +[[package]] +name = "pypdf" +version = "4.1.0" +description = "A pure-python PDF library capable of splitting, merging, cropping, and transforming PDF files" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pypdf-4.1.0-py3-none-any.whl", hash = "sha256:16cac912a05200099cef3f347c4c7e0aaf0a6d027603b8f9a973c0ea500dff89"}, + {file = "pypdf-4.1.0.tar.gz", hash = "sha256:01c3257ec908676efd60a4537e525b89d48e0852bc92b4e0aa4cc646feda17cc"}, +] + +[package.extras] +crypto = ["PyCryptodome", "cryptography"] +dev = ["black", "flit", "pip-tools", "pre-commit (<2.18.0)", "pytest-cov", "pytest-socket", "pytest-timeout", "pytest-xdist", "wheel"] +docs = ["myst_parser", "sphinx", "sphinx_rtd_theme"] +full = ["Pillow (>=8.0.0)", "PyCryptodome", "cryptography"] +image = ["Pillow (>=8.0.0)"] + +[[package]] +name = "pypika" +version = "0.48.9" +description = "A SQL query builder API for Python" +optional = false +python-versions = "*" +files = [ + {file = "PyPika-0.48.9.tar.gz", hash = "sha256:838836a61747e7c8380cd1b7ff638694b7a7335345d0f559b04b2cd832ad5378"}, +] + +[[package]] +name = "pyproject-hooks" +version = "1.0.0" +description = "Wrappers to call pyproject.toml-based build backend hooks." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pyproject_hooks-1.0.0-py3-none-any.whl", hash = "sha256:283c11acd6b928d2f6a7c73fa0d01cb2bdc5f07c57a2eeb6e83d5e56b97976f8"}, + {file = "pyproject_hooks-1.0.0.tar.gz", hash = "sha256:f271b298b97f5955d53fb12b72c1fb1948c22c1a6b70b315c54cedaca0264ef5"}, +] + +[package.dependencies] +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} + +[[package]] +name = "pyreadline3" +version = "3.4.1" +description = "A python implementation of GNU readline." +optional = false +python-versions = "*" +files = [ + {file = "pyreadline3-3.4.1-py3-none-any.whl", hash = "sha256:b0efb6516fd4fb07b45949053826a62fa4cb353db5be2bbb4a7aa1fdd1e345fb"}, + {file = "pyreadline3-3.4.1.tar.gz", hash = "sha256:6f3d1f7b8a31ba32b73917cefc1f28cc660562f39aea8646d30bd6eff21f7bae"}, +] + +[[package]] +name = "pytest" +version = "7.4.4" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, + {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} + +[package.extras] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "pytest-asyncio" +version = "0.21.1" +description = "Pytest support for asyncio" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-asyncio-0.21.1.tar.gz", hash = "sha256:40a7eae6dded22c7b604986855ea48400ab15b069ae38116e8c01238e9eeb64d"}, + {file = "pytest_asyncio-0.21.1-py3-none-any.whl", hash = "sha256:8666c1c8ac02631d7c51ba282e0c69a8a452b211ffedf2599099845da5c5c37b"}, +] + +[package.dependencies] +pytest = ">=7.0.0" + +[package.extras] +docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] +testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"] + +[[package]] +name = "pytest-cov" +version = "4.1.0" +description = "Pytest plugin for measuring coverage." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, + {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, +] + +[package.dependencies] +coverage = {version = ">=5.2.1", extras = ["toml"]} +pytest = ">=4.6" + +[package.extras] +testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] + +[[package]] +name = "pytest-mock" +version = "3.14.0" +description = "Thin-wrapper around the mock package for easier use with pytest" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0"}, + {file = "pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f"}, +] + +[package.dependencies] +pytest = ">=6.2.5" + +[package.extras] +dev = ["pre-commit", "pytest-asyncio", "tox"] + +[[package]] +name = "pytest-sugar" +version = "0.9.7" +description = "pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly)." +optional = false +python-versions = "*" +files = [ + {file = "pytest-sugar-0.9.7.tar.gz", hash = "sha256:f1e74c1abfa55f7241cf7088032b6e378566f16b938f3f08905e2cf4494edd46"}, + {file = "pytest_sugar-0.9.7-py2.py3-none-any.whl", hash = "sha256:8cb5a4e5f8bbcd834622b0235db9e50432f4cbd71fef55b467fe44e43701e062"}, +] + +[package.dependencies] +packaging = ">=21.3" +pytest = ">=6.2.0" +termcolor = ">=2.1.0" + +[package.extras] +dev = ["black", "flake8", "pre-commit"] + +[[package]] +name = "pytest-xdist" +version = "3.5.0" +description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-xdist-3.5.0.tar.gz", hash = "sha256:cbb36f3d67e0c478baa57fa4edc8843887e0f6cfc42d677530a36d7472b32d8a"}, + {file = "pytest_xdist-3.5.0-py3-none-any.whl", hash = "sha256:d075629c7e00b611df89f490a5063944bee7a4362a5ff11c7cc7824a03dfce24"}, +] + +[package.dependencies] +execnet = ">=1.1" +pytest = ">=6.2.0" + +[package.extras] +psutil = ["psutil (>=3.0)"] +setproctitle = ["setproctitle"] +testing = ["filelock"] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "python-docx" +version = "1.1.0" +description = "Create, read, and update Microsoft Word .docx files." +optional = false +python-versions = ">=3.7" +files = [ + {file = "python-docx-1.1.0.tar.gz", hash = "sha256:5829b722141cf1ab79aedf0c34d9fe9924b29764584c0f2164eb2b02dcdf17c9"}, + {file = "python_docx-1.1.0-py3-none-any.whl", hash = "sha256:bac9773278098a1ddc43a52d84e22f5909c4a3080a624530b3ecb3771b07c6cd"}, +] + +[package.dependencies] +lxml = ">=3.1.0" +typing-extensions = "*" + +[[package]] +name = "python-dotenv" +version = "1.0.1" +description = "Read key-value pairs from a .env file and set them as environment variables" +optional = false +python-versions = ">=3.8" +files = [ + {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, + {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, +] + +[package.extras] +cli = ["click (>=5.0)"] + +[[package]] +name = "python-engineio" +version = "4.9.0" +description = "Engine.IO server and client for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "python-engineio-4.9.0.tar.gz", hash = "sha256:e87459c15638e567711fd156e6f9c4a402668871bed79523f0ecfec744729ec7"}, + {file = "python_engineio-4.9.0-py3-none-any.whl", hash = "sha256:979859bff770725b75e60353d7ae53b397e8b517d05ba76733b404a3dcca3e4c"}, +] + +[package.dependencies] +simple-websocket = ">=0.10.0" + +[package.extras] +asyncio-client = ["aiohttp (>=3.4)"] +client = ["requests (>=2.21.0)", "websocket-client (>=0.54.0)"] +docs = ["sphinx"] + +[[package]] +name = "python-jose" +version = "3.3.0" +description = "JOSE implementation in Python" +optional = false +python-versions = "*" +files = [ + {file = "python-jose-3.3.0.tar.gz", hash = "sha256:55779b5e6ad599c6336191246e95eb2293a9ddebd555f796a65f838f07e5d78a"}, + {file = "python_jose-3.3.0-py2.py3-none-any.whl", hash = "sha256:9b1376b023f8b298536eedd47ae1089bcdb848f1535ab30555cd92002d78923a"}, +] + +[package.dependencies] +ecdsa = "!=0.15" +pyasn1 = "*" +rsa = "*" + +[package.extras] +cryptography = ["cryptography (>=3.4.0)"] +pycrypto = ["pyasn1", "pycrypto (>=2.6.0,<2.7.0)"] +pycryptodome = ["pyasn1", "pycryptodome (>=3.3.1,<4.0.0)"] + +[[package]] +name = "python-multipart" +version = "0.0.7" +description = "A streaming multipart parser for Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "python_multipart-0.0.7-py3-none-any.whl", hash = "sha256:b1fef9a53b74c795e2347daac8c54b252d9e0df9c619712691c1cc8021bd3c49"}, + {file = "python_multipart-0.0.7.tar.gz", hash = "sha256:288a6c39b06596c1b988bb6794c6fbc80e6c369e35e5062637df256bee0c9af9"}, +] + +[package.extras] +dev = ["atomicwrites (==1.2.1)", "attrs (==19.2.0)", "coverage (==6.5.0)", "hatch", "invoke (==2.2.0)", "more-itertools (==4.3.0)", "pbr (==4.3.0)", "pluggy (==1.0.0)", "py (==1.11.0)", "pytest (==7.2.0)", "pytest-cov (==4.0.0)", "pytest-timeout (==2.1.0)", "pyyaml (==5.1)"] + +[[package]] +name = "python-socketio" +version = "5.11.2" +description = "Socket.IO server and client for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "python-socketio-5.11.2.tar.gz", hash = "sha256:ae6a1de5c5209ca859dc574dccc8931c4be17ee003e74ce3b8d1306162bb4a37"}, + {file = "python_socketio-5.11.2-py3-none-any.whl", hash = "sha256:b9f22a8ff762d7a6e123d16a43ddb1a27d50f07c3c88ea999334f2f89b0ad52b"}, +] + +[package.dependencies] +bidict = ">=0.21.0" +python-engineio = ">=4.8.0" + +[package.extras] +asyncio-client = ["aiohttp (>=3.4)"] +client = ["requests (>=2.21.0)", "websocket-client (>=0.54.0)"] +docs = ["sphinx"] + +[[package]] +name = "pytz" +version = "2024.1" +description = "World timezone definitions, modern and historical" +optional = false +python-versions = "*" +files = [ + {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, + {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, +] + +[[package]] +name = "pywin32" +version = "306" +description = "Python for Window Extensions" +optional = false +python-versions = "*" +files = [ + {file = "pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d"}, + {file = "pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8"}, + {file = "pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407"}, + {file = "pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e"}, + {file = "pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a"}, + {file = "pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b"}, + {file = "pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e"}, + {file = "pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040"}, + {file = "pywin32-306-cp37-cp37m-win32.whl", hash = "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65"}, + {file = "pywin32-306-cp37-cp37m-win_amd64.whl", hash = "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36"}, + {file = "pywin32-306-cp38-cp38-win32.whl", hash = "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a"}, + {file = "pywin32-306-cp38-cp38-win_amd64.whl", hash = "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0"}, + {file = "pywin32-306-cp39-cp39-win32.whl", hash = "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802"}, + {file = "pywin32-306-cp39-cp39-win_amd64.whl", hash = "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4"}, +] + +[[package]] +name = "pyyaml" +version = "6.0.1" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, +] + +[[package]] +name = "pyzmq" +version = "25.1.2" +description = "Python bindings for 0MQ" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pyzmq-25.1.2-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:e624c789359f1a16f83f35e2c705d07663ff2b4d4479bad35621178d8f0f6ea4"}, + {file = "pyzmq-25.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:49151b0efece79f6a79d41a461d78535356136ee70084a1c22532fc6383f4ad0"}, + {file = "pyzmq-25.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9a5f194cf730f2b24d6af1f833c14c10f41023da46a7f736f48b6d35061e76e"}, + {file = "pyzmq-25.1.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:faf79a302f834d9e8304fafdc11d0d042266667ac45209afa57e5efc998e3872"}, + {file = "pyzmq-25.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f51a7b4ead28d3fca8dda53216314a553b0f7a91ee8fc46a72b402a78c3e43d"}, + {file = "pyzmq-25.1.2-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:0ddd6d71d4ef17ba5a87becf7ddf01b371eaba553c603477679ae817a8d84d75"}, + {file = "pyzmq-25.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:246747b88917e4867e2367b005fc8eefbb4a54b7db363d6c92f89d69abfff4b6"}, + {file = "pyzmq-25.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:00c48ae2fd81e2a50c3485de1b9d5c7c57cd85dc8ec55683eac16846e57ac979"}, + {file = "pyzmq-25.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5a68d491fc20762b630e5db2191dd07ff89834086740f70e978bb2ef2668be08"}, + {file = "pyzmq-25.1.2-cp310-cp310-win32.whl", hash = "sha256:09dfe949e83087da88c4a76767df04b22304a682d6154de2c572625c62ad6886"}, + {file = "pyzmq-25.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:fa99973d2ed20417744fca0073390ad65ce225b546febb0580358e36aa90dba6"}, + {file = "pyzmq-25.1.2-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:82544e0e2d0c1811482d37eef297020a040c32e0687c1f6fc23a75b75db8062c"}, + {file = "pyzmq-25.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:01171fc48542348cd1a360a4b6c3e7d8f46cdcf53a8d40f84db6707a6768acc1"}, + {file = "pyzmq-25.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc69c96735ab501419c432110016329bf0dea8898ce16fab97c6d9106dc0b348"}, + {file = "pyzmq-25.1.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3e124e6b1dd3dfbeb695435dff0e383256655bb18082e094a8dd1f6293114642"}, + {file = "pyzmq-25.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7598d2ba821caa37a0f9d54c25164a4fa351ce019d64d0b44b45540950458840"}, + {file = "pyzmq-25.1.2-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:d1299d7e964c13607efd148ca1f07dcbf27c3ab9e125d1d0ae1d580a1682399d"}, + {file = "pyzmq-25.1.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4e6f689880d5ad87918430957297c975203a082d9a036cc426648fcbedae769b"}, + {file = "pyzmq-25.1.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cc69949484171cc961e6ecd4a8911b9ce7a0d1f738fcae717177c231bf77437b"}, + {file = "pyzmq-25.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9880078f683466b7f567b8624bfc16cad65077be046b6e8abb53bed4eeb82dd3"}, + {file = "pyzmq-25.1.2-cp311-cp311-win32.whl", hash = "sha256:4e5837af3e5aaa99a091302df5ee001149baff06ad22b722d34e30df5f0d9097"}, + {file = "pyzmq-25.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:25c2dbb97d38b5ac9fd15586e048ec5eb1e38f3d47fe7d92167b0c77bb3584e9"}, + {file = "pyzmq-25.1.2-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:11e70516688190e9c2db14fcf93c04192b02d457b582a1f6190b154691b4c93a"}, + {file = "pyzmq-25.1.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:313c3794d650d1fccaaab2df942af9f2c01d6217c846177cfcbc693c7410839e"}, + {file = "pyzmq-25.1.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b3cbba2f47062b85fe0ef9de5b987612140a9ba3a9c6d2543c6dec9f7c2ab27"}, + {file = "pyzmq-25.1.2-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fc31baa0c32a2ca660784d5af3b9487e13b61b3032cb01a115fce6588e1bed30"}, + {file = "pyzmq-25.1.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02c9087b109070c5ab0b383079fa1b5f797f8d43e9a66c07a4b8b8bdecfd88ee"}, + {file = "pyzmq-25.1.2-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:f8429b17cbb746c3e043cb986328da023657e79d5ed258b711c06a70c2ea7537"}, + {file = "pyzmq-25.1.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5074adeacede5f810b7ef39607ee59d94e948b4fd954495bdb072f8c54558181"}, + {file = "pyzmq-25.1.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:7ae8f354b895cbd85212da245f1a5ad8159e7840e37d78b476bb4f4c3f32a9fe"}, + {file = "pyzmq-25.1.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b264bf2cc96b5bc43ce0e852be995e400376bd87ceb363822e2cb1964fcdc737"}, + {file = "pyzmq-25.1.2-cp312-cp312-win32.whl", hash = "sha256:02bbc1a87b76e04fd780b45e7f695471ae6de747769e540da909173d50ff8e2d"}, + {file = "pyzmq-25.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:ced111c2e81506abd1dc142e6cd7b68dd53747b3b7ae5edbea4578c5eeff96b7"}, + {file = "pyzmq-25.1.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:7b6d09a8962a91151f0976008eb7b29b433a560fde056ec7a3db9ec8f1075438"}, + {file = "pyzmq-25.1.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:967668420f36878a3c9ecb5ab33c9d0ff8d054f9c0233d995a6d25b0e95e1b6b"}, + {file = "pyzmq-25.1.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5edac3f57c7ddaacdb4d40f6ef2f9e299471fc38d112f4bc6d60ab9365445fb0"}, + {file = "pyzmq-25.1.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:0dabfb10ef897f3b7e101cacba1437bd3a5032ee667b7ead32bbcdd1a8422fe7"}, + {file = "pyzmq-25.1.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:2c6441e0398c2baacfe5ba30c937d274cfc2dc5b55e82e3749e333aabffde561"}, + {file = "pyzmq-25.1.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:16b726c1f6c2e7625706549f9dbe9b06004dfbec30dbed4bf50cbdfc73e5b32a"}, + {file = "pyzmq-25.1.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:a86c2dd76ef71a773e70551a07318b8e52379f58dafa7ae1e0a4be78efd1ff16"}, + {file = "pyzmq-25.1.2-cp36-cp36m-win32.whl", hash = "sha256:359f7f74b5d3c65dae137f33eb2bcfa7ad9ebefd1cab85c935f063f1dbb245cc"}, + {file = "pyzmq-25.1.2-cp36-cp36m-win_amd64.whl", hash = "sha256:55875492f820d0eb3417b51d96fea549cde77893ae3790fd25491c5754ea2f68"}, + {file = "pyzmq-25.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b8c8a419dfb02e91b453615c69568442e897aaf77561ee0064d789705ff37a92"}, + {file = "pyzmq-25.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8807c87fa893527ae8a524c15fc505d9950d5e856f03dae5921b5e9aa3b8783b"}, + {file = "pyzmq-25.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5e319ed7d6b8f5fad9b76daa0a68497bc6f129858ad956331a5835785761e003"}, + {file = "pyzmq-25.1.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:3c53687dde4d9d473c587ae80cc328e5b102b517447456184b485587ebd18b62"}, + {file = "pyzmq-25.1.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:9add2e5b33d2cd765ad96d5eb734a5e795a0755f7fc49aa04f76d7ddda73fd70"}, + {file = "pyzmq-25.1.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:e690145a8c0c273c28d3b89d6fb32c45e0d9605b2293c10e650265bf5c11cfec"}, + {file = "pyzmq-25.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:00a06faa7165634f0cac1abb27e54d7a0b3b44eb9994530b8ec73cf52e15353b"}, + {file = "pyzmq-25.1.2-cp37-cp37m-win32.whl", hash = "sha256:0f97bc2f1f13cb16905a5f3e1fbdf100e712d841482b2237484360f8bc4cb3d7"}, + {file = "pyzmq-25.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6cc0020b74b2e410287e5942e1e10886ff81ac77789eb20bec13f7ae681f0fdd"}, + {file = "pyzmq-25.1.2-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:bef02cfcbded83473bdd86dd8d3729cd82b2e569b75844fb4ea08fee3c26ae41"}, + {file = "pyzmq-25.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e10a4b5a4b1192d74853cc71a5e9fd022594573926c2a3a4802020360aa719d8"}, + {file = "pyzmq-25.1.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8c5f80e578427d4695adac6fdf4370c14a2feafdc8cb35549c219b90652536ae"}, + {file = "pyzmq-25.1.2-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5dde6751e857910c1339890f3524de74007958557593b9e7e8c5f01cd919f8a7"}, + {file = "pyzmq-25.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea1608dd169da230a0ad602d5b1ebd39807ac96cae1845c3ceed39af08a5c6df"}, + {file = "pyzmq-25.1.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0f513130c4c361201da9bc69df25a086487250e16b5571ead521b31ff6b02220"}, + {file = "pyzmq-25.1.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:019744b99da30330798bb37df33549d59d380c78e516e3bab9c9b84f87a9592f"}, + {file = "pyzmq-25.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2e2713ef44be5d52dd8b8e2023d706bf66cb22072e97fc71b168e01d25192755"}, + {file = "pyzmq-25.1.2-cp38-cp38-win32.whl", hash = "sha256:07cd61a20a535524906595e09344505a9bd46f1da7a07e504b315d41cd42eb07"}, + {file = "pyzmq-25.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb7e49a17fb8c77d3119d41a4523e432eb0c6932187c37deb6fbb00cc3028088"}, + {file = "pyzmq-25.1.2-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:94504ff66f278ab4b7e03e4cba7e7e400cb73bfa9d3d71f58d8972a8dc67e7a6"}, + {file = "pyzmq-25.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6dd0d50bbf9dca1d0bdea219ae6b40f713a3fb477c06ca3714f208fd69e16fd8"}, + {file = "pyzmq-25.1.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:004ff469d21e86f0ef0369717351073e0e577428e514c47c8480770d5e24a565"}, + {file = "pyzmq-25.1.2-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c0b5ca88a8928147b7b1e2dfa09f3b6c256bc1135a1338536cbc9ea13d3b7add"}, + {file = "pyzmq-25.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c9a79f1d2495b167119d02be7448bfba57fad2a4207c4f68abc0bab4b92925b"}, + {file = "pyzmq-25.1.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:518efd91c3d8ac9f9b4f7dd0e2b7b8bf1a4fe82a308009016b07eaa48681af82"}, + {file = "pyzmq-25.1.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:1ec23bd7b3a893ae676d0e54ad47d18064e6c5ae1fadc2f195143fb27373f7f6"}, + {file = "pyzmq-25.1.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db36c27baed588a5a8346b971477b718fdc66cf5b80cbfbd914b4d6d355e44e2"}, + {file = "pyzmq-25.1.2-cp39-cp39-win32.whl", hash = "sha256:39b1067f13aba39d794a24761e385e2eddc26295826530a8c7b6c6c341584289"}, + {file = "pyzmq-25.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:8e9f3fabc445d0ce320ea2c59a75fe3ea591fdbdeebec5db6de530dd4b09412e"}, + {file = "pyzmq-25.1.2-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a8c1d566344aee826b74e472e16edae0a02e2a044f14f7c24e123002dcff1c05"}, + {file = "pyzmq-25.1.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:759cfd391a0996345ba94b6a5110fca9c557ad4166d86a6e81ea526c376a01e8"}, + {file = "pyzmq-25.1.2-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c61e346ac34b74028ede1c6b4bcecf649d69b707b3ff9dc0fab453821b04d1e"}, + {file = "pyzmq-25.1.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cb8fc1f8d69b411b8ec0b5f1ffbcaf14c1db95b6bccea21d83610987435f1a4"}, + {file = "pyzmq-25.1.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:3c00c9b7d1ca8165c610437ca0c92e7b5607b2f9076f4eb4b095c85d6e680a1d"}, + {file = "pyzmq-25.1.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:df0c7a16ebb94452d2909b9a7b3337940e9a87a824c4fc1c7c36bb4404cb0cde"}, + {file = "pyzmq-25.1.2-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:45999e7f7ed5c390f2e87ece7f6c56bf979fb213550229e711e45ecc7d42ccb8"}, + {file = "pyzmq-25.1.2-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ac170e9e048b40c605358667aca3d94e98f604a18c44bdb4c102e67070f3ac9b"}, + {file = "pyzmq-25.1.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1b604734bec94f05f81b360a272fc824334267426ae9905ff32dc2be433ab96"}, + {file = "pyzmq-25.1.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:a793ac733e3d895d96f865f1806f160696422554e46d30105807fdc9841b9f7d"}, + {file = "pyzmq-25.1.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0806175f2ae5ad4b835ecd87f5f85583316b69f17e97786f7443baaf54b9bb98"}, + {file = "pyzmq-25.1.2-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ef12e259e7bc317c7597d4f6ef59b97b913e162d83b421dd0db3d6410f17a244"}, + {file = "pyzmq-25.1.2-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea253b368eb41116011add00f8d5726762320b1bda892f744c91997b65754d73"}, + {file = "pyzmq-25.1.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b9b1f2ad6498445a941d9a4fee096d387fee436e45cc660e72e768d3d8ee611"}, + {file = "pyzmq-25.1.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:8b14c75979ce932c53b79976a395cb2a8cd3aaf14aef75e8c2cb55a330b9b49d"}, + {file = "pyzmq-25.1.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:889370d5174a741a62566c003ee8ddba4b04c3f09a97b8000092b7ca83ec9c49"}, + {file = "pyzmq-25.1.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9a18fff090441a40ffda8a7f4f18f03dc56ae73f148f1832e109f9bffa85df15"}, + {file = "pyzmq-25.1.2-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99a6b36f95c98839ad98f8c553d8507644c880cf1e0a57fe5e3a3f3969040882"}, + {file = "pyzmq-25.1.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4345c9a27f4310afbb9c01750e9461ff33d6fb74cd2456b107525bbeebcb5be3"}, + {file = "pyzmq-25.1.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3516e0b6224cf6e43e341d56da15fd33bdc37fa0c06af4f029f7d7dfceceabbc"}, + {file = "pyzmq-25.1.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:146b9b1f29ead41255387fb07be56dc29639262c0f7344f570eecdcd8d683314"}, + {file = "pyzmq-25.1.2.tar.gz", hash = "sha256:93f1aa311e8bb912e34f004cf186407a4e90eec4f0ecc0efd26056bf7eda0226"}, +] + +[package.dependencies] +cffi = {version = "*", markers = "implementation_name == \"pypy\""} + +[[package]] +name = "regex" +version = "2023.12.25" +description = "Alternative regular expression module, to replace re." +optional = false +python-versions = ">=3.7" +files = [ + {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0694219a1d54336fd0445ea382d49d36882415c0134ee1e8332afd1529f0baa5"}, + {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b014333bd0217ad3d54c143de9d4b9a3ca1c5a29a6d0d554952ea071cff0f1f8"}, + {file = "regex-2023.12.25-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d865984b3f71f6d0af64d0d88f5733521698f6c16f445bb09ce746c92c97c586"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e0eabac536b4cc7f57a5f3d095bfa557860ab912f25965e08fe1545e2ed8b4c"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c25a8ad70e716f96e13a637802813f65d8a6760ef48672aa3502f4c24ea8b400"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9b6d73353f777630626f403b0652055ebfe8ff142a44ec2cf18ae470395766e"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9cc99d6946d750eb75827cb53c4371b8b0fe89c733a94b1573c9dd16ea6c9e4"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88d1f7bef20c721359d8675f7d9f8e414ec5003d8f642fdfd8087777ff7f94b5"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cb3fe77aec8f1995611f966d0c656fdce398317f850d0e6e7aebdfe61f40e1cd"}, + {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7aa47c2e9ea33a4a2a05f40fcd3ea36d73853a2aae7b4feab6fc85f8bf2c9704"}, + {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:df26481f0c7a3f8739fecb3e81bc9da3fcfae34d6c094563b9d4670b047312e1"}, + {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c40281f7d70baf6e0db0c2f7472b31609f5bc2748fe7275ea65a0b4601d9b392"}, + {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:d94a1db462d5690ebf6ae86d11c5e420042b9898af5dcf278bd97d6bda065423"}, + {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ba1b30765a55acf15dce3f364e4928b80858fa8f979ad41f862358939bdd1f2f"}, + {file = "regex-2023.12.25-cp310-cp310-win32.whl", hash = "sha256:150c39f5b964e4d7dba46a7962a088fbc91f06e606f023ce57bb347a3b2d4630"}, + {file = "regex-2023.12.25-cp310-cp310-win_amd64.whl", hash = "sha256:09da66917262d9481c719599116c7dc0c321ffcec4b1f510c4f8a066f8768105"}, + {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1b9d811f72210fa9306aeb88385b8f8bcef0dfbf3873410413c00aa94c56c2b6"}, + {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97"}, + {file = "regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887"}, + {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb"}, + {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:636ba0a77de609d6510235b7f0e77ec494d2657108f777e8765efc060094c98c"}, + {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fda75704357805eb953a3ee15a2b240694a9a514548cd49b3c5124b4e2ad01b"}, + {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa"}, + {file = "regex-2023.12.25-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db2a0b1857f18b11e3b0e54ddfefc96af46b0896fb678c85f63fb8c37518b3e7"}, + {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7502534e55c7c36c0978c91ba6f61703faf7ce733715ca48f499d3dbbd7657e0"}, + {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e8c7e08bb566de4faaf11984af13f6bcf6a08f327b13631d41d62592681d24fe"}, + {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:283fc8eed679758de38fe493b7d7d84a198b558942b03f017b1f94dda8efae80"}, + {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f44dd4d68697559d007462b0a3a1d9acd61d97072b71f6d1968daef26bc744bd"}, + {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:67d3ccfc590e5e7197750fcb3a2915b416a53e2de847a728cfa60141054123d4"}, + {file = "regex-2023.12.25-cp311-cp311-win32.whl", hash = "sha256:68191f80a9bad283432385961d9efe09d783bcd36ed35a60fb1ff3f1ec2efe87"}, + {file = "regex-2023.12.25-cp311-cp311-win_amd64.whl", hash = "sha256:7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f"}, + {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8a0ccf52bb37d1a700375a6b395bff5dd15c50acb745f7db30415bae3c2b0715"}, + {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c3c4a78615b7762740531c27cf46e2f388d8d727d0c0c739e72048beb26c8a9d"}, + {file = "regex-2023.12.25-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ad83e7545b4ab69216cef4cc47e344d19622e28aabec61574b20257c65466d6a"}, + {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7a635871143661feccce3979e1727c4e094f2bdfd3ec4b90dfd4f16f571a87a"}, + {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d498eea3f581fbe1b34b59c697512a8baef88212f92e4c7830fcc1499f5b45a5"}, + {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:43f7cd5754d02a56ae4ebb91b33461dc67be8e3e0153f593c509e21d219c5060"}, + {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51f4b32f793812714fd5307222a7f77e739b9bc566dc94a18126aba3b92b98a3"}, + {file = "regex-2023.12.25-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba99d8077424501b9616b43a2d208095746fb1284fc5ba490139651f971d39d9"}, + {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4bfc2b16e3ba8850e0e262467275dd4d62f0d045e0e9eda2bc65078c0110a11f"}, + {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8c2c19dae8a3eb0ea45a8448356ed561be843b13cbc34b840922ddf565498c1c"}, + {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:60080bb3d8617d96f0fb7e19796384cc2467447ef1c491694850ebd3670bc457"}, + {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b77e27b79448e34c2c51c09836033056a0547aa360c45eeeb67803da7b0eedaf"}, + {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:518440c991f514331f4850a63560321f833979d145d7d81186dbe2f19e27ae3d"}, + {file = "regex-2023.12.25-cp312-cp312-win32.whl", hash = "sha256:e2610e9406d3b0073636a3a2e80db05a02f0c3169b5632022b4e81c0364bcda5"}, + {file = "regex-2023.12.25-cp312-cp312-win_amd64.whl", hash = "sha256:cc37b9aeebab425f11f27e5e9e6cf580be7206c6582a64467a14dda211abc232"}, + {file = "regex-2023.12.25-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:da695d75ac97cb1cd725adac136d25ca687da4536154cdc2815f576e4da11c69"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d126361607b33c4eb7b36debc173bf25d7805847346dd4d99b5499e1fef52bc7"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4719bb05094d7d8563a450cf8738d2e1061420f79cfcc1fa7f0a44744c4d8f73"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5dd58946bce44b53b06d94aa95560d0b243eb2fe64227cba50017a8d8b3cd3e2"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22a86d9fff2009302c440b9d799ef2fe322416d2d58fc124b926aa89365ec482"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2aae8101919e8aa05ecfe6322b278f41ce2994c4a430303c4cd163fef746e04f"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e692296c4cc2873967771345a876bcfc1c547e8dd695c6b89342488b0ea55cd8"}, + {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:263ef5cc10979837f243950637fffb06e8daed7f1ac1e39d5910fd29929e489a"}, + {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:d6f7e255e5fa94642a0724e35406e6cb7001c09d476ab5fce002f652b36d0c39"}, + {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:88ad44e220e22b63b0f8f81f007e8abbb92874d8ced66f32571ef8beb0643b2b"}, + {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:3a17d3ede18f9cedcbe23d2daa8a2cd6f59fe2bf082c567e43083bba3fb00347"}, + {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d15b274f9e15b1a0b7a45d2ac86d1f634d983ca40d6b886721626c47a400bf39"}, + {file = "regex-2023.12.25-cp37-cp37m-win32.whl", hash = "sha256:ed19b3a05ae0c97dd8f75a5d8f21f7723a8c33bbc555da6bbe1f96c470139d3c"}, + {file = "regex-2023.12.25-cp37-cp37m-win_amd64.whl", hash = "sha256:a6d1047952c0b8104a1d371f88f4ab62e6275567d4458c1e26e9627ad489b445"}, + {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b43523d7bc2abd757119dbfb38af91b5735eea45537ec6ec3a5ec3f9562a1c53"}, + {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:efb2d82f33b2212898f1659fb1c2e9ac30493ac41e4d53123da374c3b5541e64"}, + {file = "regex-2023.12.25-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b7fca9205b59c1a3d5031f7e64ed627a1074730a51c2a80e97653e3e9fa0d415"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086dd15e9435b393ae06f96ab69ab2d333f5d65cbe65ca5a3ef0ec9564dfe770"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e81469f7d01efed9b53740aedd26085f20d49da65f9c1f41e822a33992cb1590"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:34e4af5b27232f68042aa40a91c3b9bb4da0eeb31b7632e0091afc4310afe6cb"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9852b76ab558e45b20bf1893b59af64a28bd3820b0c2efc80e0a70a4a3ea51c1"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff100b203092af77d1a5a7abe085b3506b7eaaf9abf65b73b7d6905b6cb76988"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cc038b2d8b1470364b1888a98fd22d616fba2b6309c5b5f181ad4483e0017861"}, + {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:094ba386bb5c01e54e14434d4caabf6583334090865b23ef58e0424a6286d3dc"}, + {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5cd05d0f57846d8ba4b71d9c00f6f37d6b97d5e5ef8b3c3840426a475c8f70f4"}, + {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:9aa1a67bbf0f957bbe096375887b2505f5d8ae16bf04488e8b0f334c36e31360"}, + {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:98a2636994f943b871786c9e82bfe7883ecdaba2ef5df54e1450fa9869d1f756"}, + {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:37f8e93a81fc5e5bd8db7e10e62dc64261bcd88f8d7e6640aaebe9bc180d9ce2"}, + {file = "regex-2023.12.25-cp38-cp38-win32.whl", hash = "sha256:d78bd484930c1da2b9679290a41cdb25cc127d783768a0369d6b449e72f88beb"}, + {file = "regex-2023.12.25-cp38-cp38-win_amd64.whl", hash = "sha256:b521dcecebc5b978b447f0f69b5b7f3840eac454862270406a39837ffae4e697"}, + {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f7bc09bc9c29ebead055bcba136a67378f03d66bf359e87d0f7c759d6d4ffa31"}, + {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e14b73607d6231f3cc4622809c196b540a6a44e903bcfad940779c80dffa7be7"}, + {file = "regex-2023.12.25-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9eda5f7a50141291beda3edd00abc2d4a5b16c29c92daf8d5bd76934150f3edc"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc6bb9aa69aacf0f6032c307da718f61a40cf970849e471254e0e91c56ffca95"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:298dc6354d414bc921581be85695d18912bea163a8b23cac9a2562bbcd5088b1"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f4e475a80ecbd15896a976aa0b386c5525d0ed34d5c600b6d3ebac0a67c7ddf"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:531ac6cf22b53e0696f8e1d56ce2396311254eb806111ddd3922c9d937151dae"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22f3470f7524b6da61e2020672df2f3063676aff444db1daa283c2ea4ed259d6"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:89723d2112697feaa320c9d351e5f5e7b841e83f8b143dba8e2d2b5f04e10923"}, + {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0ecf44ddf9171cd7566ef1768047f6e66975788258b1c6c6ca78098b95cf9a3d"}, + {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:905466ad1702ed4acfd67a902af50b8db1feeb9781436372261808df7a2a7bca"}, + {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:4558410b7a5607a645e9804a3e9dd509af12fb72b9825b13791a37cd417d73a5"}, + {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7e316026cc1095f2a3e8cc012822c99f413b702eaa2ca5408a513609488cb62f"}, + {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3b1de218d5375cd6ac4b5493e0b9f3df2be331e86520f23382f216c137913d20"}, + {file = "regex-2023.12.25-cp39-cp39-win32.whl", hash = "sha256:11a963f8e25ab5c61348d090bf1b07f1953929c13bd2309a0662e9ff680763c9"}, + {file = "regex-2023.12.25-cp39-cp39-win_amd64.whl", hash = "sha256:e693e233ac92ba83a87024e1d32b5f9ab15ca55ddd916d878146f4e3406b5c91"}, + {file = "regex-2023.12.25.tar.gz", hash = "sha256:29171aa128da69afdf4bde412d5bedc335f2ca8fcfe4489038577d05f16181e5"}, +] + +[[package]] +name = "requests" +version = "2.31.0" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.7" +files = [ + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "requests-oauthlib" +version = "2.0.0" +description = "OAuthlib authentication support for Requests." +optional = false +python-versions = ">=3.4" +files = [ + {file = "requests-oauthlib-2.0.0.tar.gz", hash = "sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9"}, + {file = "requests_oauthlib-2.0.0-py2.py3-none-any.whl", hash = "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36"}, +] + +[package.dependencies] +oauthlib = ">=3.0.0" +requests = ">=2.0.0" + +[package.extras] +rsa = ["oauthlib[signedtoken] (>=3.0.0)"] + +[[package]] +name = "rich" +version = "13.7.1" +description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "rich-13.7.1-py3-none-any.whl", hash = "sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222"}, + {file = "rich-13.7.1.tar.gz", hash = "sha256:9be308cb1fe2f1f57d67ce99e95af38a1e2bc71ad9813b0e247cf7ffbcc3a432"}, +] + +[package.dependencies] +markdown-it-py = ">=2.2.0" +pygments = ">=2.13.0,<3.0.0" + +[package.extras] +jupyter = ["ipywidgets (>=7.5.1,<9)"] + +[[package]] +name = "roundrobin" +version = "0.0.4" +description = "Collection of roundrobin utilities" +optional = false +python-versions = "*" +files = [ + {file = "roundrobin-0.0.4.tar.gz", hash = "sha256:7e9d19a5bd6123d99993fb935fa86d25c88bb2096e493885f61737ed0f5e9abd"}, +] + +[[package]] +name = "rsa" +version = "4.9" +description = "Pure-Python RSA implementation" +optional = false +python-versions = ">=3.6,<4" +files = [ + {file = "rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7"}, + {file = "rsa-4.9.tar.gz", hash = "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21"}, +] + +[package.dependencies] +pyasn1 = ">=0.1.3" + +[[package]] +name = "ruff" +version = "0.1.15" +description = "An extremely fast Python linter and code formatter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.1.15-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:5fe8d54df166ecc24106db7dd6a68d44852d14eb0729ea4672bb4d96c320b7df"}, + {file = "ruff-0.1.15-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6f0bfbb53c4b4de117ac4d6ddfd33aa5fc31beeaa21d23c45c6dd249faf9126f"}, + {file = "ruff-0.1.15-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0d432aec35bfc0d800d4f70eba26e23a352386be3a6cf157083d18f6f5881c8"}, + {file = "ruff-0.1.15-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9405fa9ac0e97f35aaddf185a1be194a589424b8713e3b97b762336ec79ff807"}, + {file = "ruff-0.1.15-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c66ec24fe36841636e814b8f90f572a8c0cb0e54d8b5c2d0e300d28a0d7bffec"}, + {file = "ruff-0.1.15-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:6f8ad828f01e8dd32cc58bc28375150171d198491fc901f6f98d2a39ba8e3ff5"}, + {file = "ruff-0.1.15-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86811954eec63e9ea162af0ffa9f8d09088bab51b7438e8b6488b9401863c25e"}, + {file = "ruff-0.1.15-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fd4025ac5e87d9b80e1f300207eb2fd099ff8200fa2320d7dc066a3f4622dc6b"}, + {file = "ruff-0.1.15-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b17b93c02cdb6aeb696effecea1095ac93f3884a49a554a9afa76bb125c114c1"}, + {file = "ruff-0.1.15-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:ddb87643be40f034e97e97f5bc2ef7ce39de20e34608f3f829db727a93fb82c5"}, + {file = "ruff-0.1.15-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:abf4822129ed3a5ce54383d5f0e964e7fef74a41e48eb1dfad404151efc130a2"}, + {file = "ruff-0.1.15-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6c629cf64bacfd136c07c78ac10a54578ec9d1bd2a9d395efbee0935868bf852"}, + {file = "ruff-0.1.15-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1bab866aafb53da39c2cadfb8e1c4550ac5340bb40300083eb8967ba25481447"}, + {file = "ruff-0.1.15-py3-none-win32.whl", hash = "sha256:2417e1cb6e2068389b07e6fa74c306b2810fe3ee3476d5b8a96616633f40d14f"}, + {file = "ruff-0.1.15-py3-none-win_amd64.whl", hash = "sha256:3837ac73d869efc4182d9036b1405ef4c73d9b1f88da2413875e34e0d6919587"}, + {file = "ruff-0.1.15-py3-none-win_arm64.whl", hash = "sha256:9a933dfb1c14ec7a33cceb1e49ec4a16b51ce3c20fd42663198746efc0427360"}, + {file = "ruff-0.1.15.tar.gz", hash = "sha256:f6dfa8c1b21c913c326919056c390966648b680966febcb796cc9d1aaab8564e"}, +] + +[[package]] +name = "setuptools" +version = "69.2.0" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "setuptools-69.2.0-py3-none-any.whl", hash = "sha256:c21c49fb1042386df081cb5d86759792ab89efca84cf114889191cd09aacc80c"}, + {file = "setuptools-69.2.0.tar.gz", hash = "sha256:0ff4183f8f42cd8fa3acea16c45205521a4ef28f73c6391d8a25e92893134f2e"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mypy (==1.9)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] + +[[package]] +name = "simple-websocket" +version = "1.0.0" +description = "Simple WebSocket server and client for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "simple-websocket-1.0.0.tar.gz", hash = "sha256:17d2c72f4a2bd85174a97e3e4c88b01c40c3f81b7b648b0cc3ce1305968928c8"}, + {file = "simple_websocket-1.0.0-py3-none-any.whl", hash = "sha256:1d5bf585e415eaa2083e2bcf02a3ecf91f9712e7b3e6b9fa0b461ad04e0837bc"}, +] + +[package.dependencies] +wsproto = "*" + +[package.extras] +docs = ["sphinx"] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +description = "Sniff out which async library your code is running under" +optional = false +python-versions = ">=3.7" +files = [ + {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, + {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, +] + +[[package]] +name = "sqlalchemy" +version = "2.0.29" +description = "Database Abstraction Library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "SQLAlchemy-2.0.29-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4c142852ae192e9fe5aad5c350ea6befe9db14370b34047e1f0f7cf99e63c63b"}, + {file = "SQLAlchemy-2.0.29-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:99a1e69d4e26f71e750e9ad6fdc8614fbddb67cfe2173a3628a2566034e223c7"}, + {file = "SQLAlchemy-2.0.29-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ef3fbccb4058355053c51b82fd3501a6e13dd808c8d8cd2561e610c5456013c"}, + {file = "SQLAlchemy-2.0.29-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d6753305936eddc8ed190e006b7bb33a8f50b9854823485eed3a886857ab8d1"}, + {file = "SQLAlchemy-2.0.29-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0f3ca96af060a5250a8ad5a63699180bc780c2edf8abf96c58af175921df847a"}, + {file = "SQLAlchemy-2.0.29-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c4520047006b1d3f0d89e0532978c0688219857eb2fee7c48052560ae76aca1e"}, + {file = "SQLAlchemy-2.0.29-cp310-cp310-win32.whl", hash = "sha256:b2a0e3cf0caac2085ff172c3faacd1e00c376e6884b5bc4dd5b6b84623e29e4f"}, + {file = "SQLAlchemy-2.0.29-cp310-cp310-win_amd64.whl", hash = "sha256:01d10638a37460616708062a40c7b55f73e4d35eaa146781c683e0fa7f6c43fb"}, + {file = "SQLAlchemy-2.0.29-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:308ef9cb41d099099fffc9d35781638986870b29f744382904bf9c7dadd08513"}, + {file = "SQLAlchemy-2.0.29-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:296195df68326a48385e7a96e877bc19aa210e485fa381c5246bc0234c36c78e"}, + {file = "SQLAlchemy-2.0.29-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a13b917b4ffe5a0a31b83d051d60477819ddf18276852ea68037a144a506efb9"}, + {file = "SQLAlchemy-2.0.29-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f6d971255d9ddbd3189e2e79d743ff4845c07f0633adfd1de3f63d930dbe673"}, + {file = "SQLAlchemy-2.0.29-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:61405ea2d563407d316c63a7b5271ae5d274a2a9fbcd01b0aa5503635699fa1e"}, + {file = "SQLAlchemy-2.0.29-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:de7202ffe4d4a8c1e3cde1c03e01c1a3772c92858837e8f3879b497158e4cb44"}, + {file = "SQLAlchemy-2.0.29-cp311-cp311-win32.whl", hash = "sha256:b5d7ed79df55a731749ce65ec20d666d82b185fa4898430b17cb90c892741520"}, + {file = "SQLAlchemy-2.0.29-cp311-cp311-win_amd64.whl", hash = "sha256:205f5a2b39d7c380cbc3b5dcc8f2762fb5bcb716838e2d26ccbc54330775b003"}, + {file = "SQLAlchemy-2.0.29-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d96710d834a6fb31e21381c6d7b76ec729bd08c75a25a5184b1089141356171f"}, + {file = "SQLAlchemy-2.0.29-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:52de4736404e53c5c6a91ef2698c01e52333988ebdc218f14c833237a0804f1b"}, + {file = "SQLAlchemy-2.0.29-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c7b02525ede2a164c5fa5014915ba3591730f2cc831f5be9ff3b7fd3e30958e"}, + {file = "SQLAlchemy-2.0.29-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dfefdb3e54cd15f5d56fd5ae32f1da2d95d78319c1f6dfb9bcd0eb15d603d5d"}, + {file = "SQLAlchemy-2.0.29-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a88913000da9205b13f6f195f0813b6ffd8a0c0c2bd58d499e00a30eb508870c"}, + {file = "SQLAlchemy-2.0.29-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fecd5089c4be1bcc37c35e9aa678938d2888845a134dd016de457b942cf5a758"}, + {file = "SQLAlchemy-2.0.29-cp312-cp312-win32.whl", hash = "sha256:8197d6f7a3d2b468861ebb4c9f998b9df9e358d6e1cf9c2a01061cb9b6cf4e41"}, + {file = "SQLAlchemy-2.0.29-cp312-cp312-win_amd64.whl", hash = "sha256:9b19836ccca0d321e237560e475fd99c3d8655d03da80c845c4da20dda31b6e1"}, + {file = "SQLAlchemy-2.0.29-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:87a1d53a5382cdbbf4b7619f107cc862c1b0a4feb29000922db72e5a66a5ffc0"}, + {file = "SQLAlchemy-2.0.29-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a0732dffe32333211801b28339d2a0babc1971bc90a983e3035e7b0d6f06b93"}, + {file = "SQLAlchemy-2.0.29-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90453597a753322d6aa770c5935887ab1fc49cc4c4fdd436901308383d698b4b"}, + {file = "SQLAlchemy-2.0.29-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ea311d4ee9a8fa67f139c088ae9f905fcf0277d6cd75c310a21a88bf85e130f5"}, + {file = "SQLAlchemy-2.0.29-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:5f20cb0a63a3e0ec4e169aa8890e32b949c8145983afa13a708bc4b0a1f30e03"}, + {file = "SQLAlchemy-2.0.29-cp37-cp37m-win32.whl", hash = "sha256:e5bbe55e8552019c6463709b39634a5fc55e080d0827e2a3a11e18eb73f5cdbd"}, + {file = "SQLAlchemy-2.0.29-cp37-cp37m-win_amd64.whl", hash = "sha256:c2f9c762a2735600654c654bf48dad388b888f8ce387b095806480e6e4ff6907"}, + {file = "SQLAlchemy-2.0.29-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7e614d7a25a43a9f54fcce4675c12761b248547f3d41b195e8010ca7297c369c"}, + {file = "SQLAlchemy-2.0.29-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:471fcb39c6adf37f820350c28aac4a7df9d3940c6548b624a642852e727ea586"}, + {file = "SQLAlchemy-2.0.29-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:988569c8732f54ad3234cf9c561364221a9e943b78dc7a4aaf35ccc2265f1930"}, + {file = "SQLAlchemy-2.0.29-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dddaae9b81c88083e6437de95c41e86823d150f4ee94bf24e158a4526cbead01"}, + {file = "SQLAlchemy-2.0.29-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:334184d1ab8f4c87f9652b048af3f7abea1c809dfe526fb0435348a6fef3d380"}, + {file = "SQLAlchemy-2.0.29-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:38b624e5cf02a69b113c8047cf7f66b5dfe4a2ca07ff8b8716da4f1b3ae81567"}, + {file = "SQLAlchemy-2.0.29-cp38-cp38-win32.whl", hash = "sha256:bab41acf151cd68bc2b466deae5deeb9e8ae9c50ad113444151ad965d5bf685b"}, + {file = "SQLAlchemy-2.0.29-cp38-cp38-win_amd64.whl", hash = "sha256:52c8011088305476691b8750c60e03b87910a123cfd9ad48576d6414b6ec2a1d"}, + {file = "SQLAlchemy-2.0.29-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3071ad498896907a5ef756206b9dc750f8e57352113c19272bdfdc429c7bd7de"}, + {file = "SQLAlchemy-2.0.29-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:dba622396a3170974f81bad49aacebd243455ec3cc70615aeaef9e9613b5bca5"}, + {file = "SQLAlchemy-2.0.29-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b184e3de58009cc0bf32e20f137f1ec75a32470f5fede06c58f6c355ed42a72"}, + {file = "SQLAlchemy-2.0.29-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c37f1050feb91f3d6c32f864d8e114ff5545a4a7afe56778d76a9aec62638ba"}, + {file = "SQLAlchemy-2.0.29-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bda7ce59b06d0f09afe22c56714c65c957b1068dee3d5e74d743edec7daba552"}, + {file = "SQLAlchemy-2.0.29-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:25664e18bef6dc45015b08f99c63952a53a0a61f61f2e48a9e70cec27e55f699"}, + {file = "SQLAlchemy-2.0.29-cp39-cp39-win32.whl", hash = "sha256:77d29cb6c34b14af8a484e831ab530c0f7188f8efed1c6a833a2c674bf3c26ec"}, + {file = "SQLAlchemy-2.0.29-cp39-cp39-win_amd64.whl", hash = "sha256:04c487305ab035a9548f573763915189fc0fe0824d9ba28433196f8436f1449c"}, + {file = "SQLAlchemy-2.0.29-py3-none-any.whl", hash = "sha256:dc4ee2d4ee43251905f88637d5281a8d52e916a021384ec10758826f5cbae305"}, + {file = "SQLAlchemy-2.0.29.tar.gz", hash = "sha256:bd9566b8e58cabd700bc367b60e90d9349cd16f0984973f98a9a09f9c64e86f0"}, +] + +[package.dependencies] +greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""} +typing-extensions = ">=4.6.0" + +[package.extras] +aiomysql = ["aiomysql (>=0.2.0)", "greenlet (!=0.4.17)"] +aioodbc = ["aioodbc", "greenlet (!=0.4.17)"] +aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing_extensions (!=3.10.0.1)"] +asyncio = ["greenlet (!=0.4.17)"] +asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (!=0.4.17)"] +mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5)"] +mssql = ["pyodbc"] +mssql-pymssql = ["pymssql"] +mssql-pyodbc = ["pyodbc"] +mypy = ["mypy (>=0.910)"] +mysql = ["mysqlclient (>=1.4.0)"] +mysql-connector = ["mysql-connector-python"] +oracle = ["cx_oracle (>=8)"] +oracle-oracledb = ["oracledb (>=1.0.1)"] +postgresql = ["psycopg2 (>=2.7)"] +postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"] +postgresql-pg8000 = ["pg8000 (>=1.29.1)"] +postgresql-psycopg = ["psycopg (>=3.0.7)"] +postgresql-psycopg2binary = ["psycopg2-binary"] +postgresql-psycopg2cffi = ["psycopg2cffi"] +postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"] +pymysql = ["pymysql"] +sqlcipher = ["sqlcipher3_binary"] + +[[package]] +name = "sqlmodel" +version = "0.0.14" +description = "SQLModel, SQL databases in Python, designed for simplicity, compatibility, and robustness." +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "sqlmodel-0.0.14-py3-none-any.whl", hash = "sha256:accea3ff5d878e41ac439b11e78613ed61ce300cfcb860e87a2d73d4884cbee4"}, + {file = "sqlmodel-0.0.14.tar.gz", hash = "sha256:0bff8fc94af86b44925aa813f56cf6aabdd7f156b73259f2f60692c6a64ac90e"}, +] + +[package.dependencies] +pydantic = ">=1.10.13,<3.0.0" +SQLAlchemy = ">=2.0.0,<2.1.0" + +[[package]] +name = "stack-data" +version = "0.6.3" +description = "Extract data from python stack frames and tracebacks for informative displays" +optional = false +python-versions = "*" +files = [ + {file = "stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695"}, + {file = "stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9"}, +] + +[package.dependencies] +asttokens = ">=2.1.0" +executing = ">=1.2.0" +pure-eval = "*" + +[package.extras] +tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] + +[[package]] +name = "starlette" +version = "0.36.3" +description = "The little ASGI library that shines." +optional = false +python-versions = ">=3.8" +files = [ + {file = "starlette-0.36.3-py3-none-any.whl", hash = "sha256:13d429aa93a61dc40bf503e8c801db1f1bca3dc706b10ef2434a36123568f044"}, + {file = "starlette-0.36.3.tar.gz", hash = "sha256:90a671733cfb35771d8cc605e0b679d23b992f8dcfad48cc60b38cb29aeb7080"}, +] + +[package.dependencies] +anyio = ">=3.4.0,<5" + +[package.extras] +full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7)", "pyyaml"] + +[[package]] +name = "sympy" +version = "1.12" +description = "Computer algebra system (CAS) in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "sympy-1.12-py3-none-any.whl", hash = "sha256:c3588cd4295d0c0f603d0f2ae780587e64e2efeedb3521e46b9bb1d08d184fa5"}, + {file = "sympy-1.12.tar.gz", hash = "sha256:ebf595c8dac3e0fdc4152c51878b498396ec7f30e7a914d6071e674d49420fb8"}, +] + +[package.dependencies] +mpmath = ">=0.19" + +[[package]] +name = "tenacity" +version = "8.2.3" +description = "Retry code until it succeeds" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tenacity-8.2.3-py3-none-any.whl", hash = "sha256:ce510e327a630c9e1beaf17d42e6ffacc88185044ad85cf74c0a8887c6a0f88c"}, + {file = "tenacity-8.2.3.tar.gz", hash = "sha256:5398ef0d78e63f40007c1fb4c0bff96e1911394d2fa8d194f77619c05ff6cc8a"}, +] + +[package.extras] +doc = ["reno", "sphinx", "tornado (>=4.5)"] + +[[package]] +name = "termcolor" +version = "2.4.0" +description = "ANSI color formatting for output in terminal" +optional = false +python-versions = ">=3.8" +files = [ + {file = "termcolor-2.4.0-py3-none-any.whl", hash = "sha256:9297c0df9c99445c2412e832e882a7884038a25617c60cea2ad69488d4040d63"}, + {file = "termcolor-2.4.0.tar.gz", hash = "sha256:aab9e56047c8ac41ed798fa36d892a37aca6b3e9159f3e0c24bc64a9b3ac7b7a"}, +] + +[package.extras] +tests = ["pytest", "pytest-cov"] + +[[package]] +name = "tiktoken" +version = "0.6.0" +description = "tiktoken is a fast BPE tokeniser for use with OpenAI's models" +optional = false +python-versions = ">=3.8" +files = [ + {file = "tiktoken-0.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:277de84ccd8fa12730a6b4067456e5cf72fef6300bea61d506c09e45658d41ac"}, + {file = "tiktoken-0.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9c44433f658064463650d61387623735641dcc4b6c999ca30bc0f8ba3fccaf5c"}, + {file = "tiktoken-0.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afb9a2a866ae6eef1995ab656744287a5ac95acc7e0491c33fad54d053288ad3"}, + {file = "tiktoken-0.6.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c62c05b3109fefca26fedb2820452a050074ad8e5ad9803f4652977778177d9f"}, + {file = "tiktoken-0.6.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0ef917fad0bccda07bfbad835525bbed5f3ab97a8a3e66526e48cdc3e7beacf7"}, + {file = "tiktoken-0.6.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e095131ab6092d0769a2fda85aa260c7c383072daec599ba9d8b149d2a3f4d8b"}, + {file = "tiktoken-0.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:05b344c61779f815038292a19a0c6eb7098b63c8f865ff205abb9ea1b656030e"}, + {file = "tiktoken-0.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cefb9870fb55dca9e450e54dbf61f904aab9180ff6fe568b61f4db9564e78871"}, + {file = "tiktoken-0.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:702950d33d8cabc039845674107d2e6dcabbbb0990ef350f640661368df481bb"}, + {file = "tiktoken-0.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8d49d076058f23254f2aff9af603863c5c5f9ab095bc896bceed04f8f0b013a"}, + {file = "tiktoken-0.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:430bc4e650a2d23a789dc2cdca3b9e5e7eb3cd3935168d97d43518cbb1f9a911"}, + {file = "tiktoken-0.6.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:293cb8669757301a3019a12d6770bd55bec38a4d3ee9978ddbe599d68976aca7"}, + {file = "tiktoken-0.6.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7bd1a288b7903aadc054b0e16ea78e3171f70b670e7372432298c686ebf9dd47"}, + {file = "tiktoken-0.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:ac76e000183e3b749634968a45c7169b351e99936ef46f0d2353cd0d46c3118d"}, + {file = "tiktoken-0.6.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:17cc8a4a3245ab7d935c83a2db6bb71619099d7284b884f4b2aea4c74f2f83e3"}, + {file = "tiktoken-0.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:284aebcccffe1bba0d6571651317df6a5b376ff6cfed5aeb800c55df44c78177"}, + {file = "tiktoken-0.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c1a3a5d33846f8cd9dd3b7897c1d45722f48625a587f8e6f3d3e85080559be8"}, + {file = "tiktoken-0.6.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6318b2bb2337f38ee954fd5efa82632c6e5ced1d52a671370fa4b2eff1355e91"}, + {file = "tiktoken-0.6.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1f5f0f2ed67ba16373f9a6013b68da298096b27cd4e1cf276d2d3868b5c7efd1"}, + {file = "tiktoken-0.6.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:75af4c0b16609c2ad02581f3cdcd1fb698c7565091370bf6c0cf8624ffaba6dc"}, + {file = "tiktoken-0.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:45577faf9a9d383b8fd683e313cf6df88b6076c034f0a16da243bb1c139340c3"}, + {file = "tiktoken-0.6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7c1492ab90c21ca4d11cef3a236ee31a3e279bb21b3fc5b0e2210588c4209e68"}, + {file = "tiktoken-0.6.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e2b380c5b7751272015400b26144a2bab4066ebb8daae9c3cd2a92c3b508fe5a"}, + {file = "tiktoken-0.6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9f497598b9f58c99cbc0eb764b4a92272c14d5203fc713dd650b896a03a50ad"}, + {file = "tiktoken-0.6.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e65e8bd6f3f279d80f1e1fbd5f588f036b9a5fa27690b7f0cc07021f1dfa0839"}, + {file = "tiktoken-0.6.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5f1495450a54e564d236769d25bfefbf77727e232d7a8a378f97acddee08c1ae"}, + {file = "tiktoken-0.6.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6c4e4857d99f6fb4670e928250835b21b68c59250520a1941618b5b4194e20c3"}, + {file = "tiktoken-0.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:168d718f07a39b013032741867e789971346df8e89983fe3c0ef3fbd5a0b1cb9"}, + {file = "tiktoken-0.6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:47fdcfe11bd55376785a6aea8ad1db967db7f66ea81aed5c43fad497521819a4"}, + {file = "tiktoken-0.6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fb7d2ccbf1a7784810aff6b80b4012fb42c6fc37eaa68cb3b553801a5cc2d1fc"}, + {file = "tiktoken-0.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ccb7a111ee76af5d876a729a347f8747d5ad548e1487eeea90eaf58894b3138"}, + {file = "tiktoken-0.6.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2048e1086b48e3c8c6e2ceeac866561374cd57a84622fa49a6b245ffecb7744"}, + {file = "tiktoken-0.6.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:07f229a5eb250b6403a61200199cecf0aac4aa23c3ecc1c11c1ca002cbb8f159"}, + {file = "tiktoken-0.6.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:432aa3be8436177b0db5a2b3e7cc28fd6c693f783b2f8722539ba16a867d0c6a"}, + {file = "tiktoken-0.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:8bfe8a19c8b5c40d121ee7938cd9c6a278e5b97dc035fd61714b4f0399d2f7a1"}, + {file = "tiktoken-0.6.0.tar.gz", hash = "sha256:ace62a4ede83c75b0374a2ddfa4b76903cf483e9cb06247f566be3bf14e6beed"}, +] + +[package.dependencies] +regex = ">=2022.1.18" +requests = ">=2.26.0" + +[package.extras] +blobfile = ["blobfile (>=2)"] + +[[package]] +name = "tokenizers" +version = "0.15.2" +description = "" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tokenizers-0.15.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:52f6130c9cbf70544287575a985bf44ae1bda2da7e8c24e97716080593638012"}, + {file = "tokenizers-0.15.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:054c1cc9c6d68f7ffa4e810b3d5131e0ba511b6e4be34157aa08ee54c2f8d9ee"}, + {file = "tokenizers-0.15.2-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a9b9b070fdad06e347563b88c278995735292ded1132f8657084989a4c84a6d5"}, + {file = "tokenizers-0.15.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea621a7eef4b70e1f7a4e84dd989ae3f0eeb50fc8690254eacc08acb623e82f1"}, + {file = "tokenizers-0.15.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cf7fd9a5141634fa3aa8d6b7be362e6ae1b4cda60da81388fa533e0b552c98fd"}, + {file = "tokenizers-0.15.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44f2a832cd0825295f7179eaf173381dc45230f9227ec4b44378322d900447c9"}, + {file = "tokenizers-0.15.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8b9ec69247a23747669ec4b0ca10f8e3dfb3545d550258129bd62291aabe8605"}, + {file = "tokenizers-0.15.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40b6a4c78da863ff26dbd5ad9a8ecc33d8a8d97b535172601cf00aee9d7ce9ce"}, + {file = "tokenizers-0.15.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5ab2a4d21dcf76af60e05af8063138849eb1d6553a0d059f6534357bce8ba364"}, + {file = "tokenizers-0.15.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a47acfac7e511f6bbfcf2d3fb8c26979c780a91e06fb5b9a43831b2c0153d024"}, + {file = "tokenizers-0.15.2-cp310-none-win32.whl", hash = "sha256:064ff87bb6acdbd693666de9a4b692add41308a2c0ec0770d6385737117215f2"}, + {file = "tokenizers-0.15.2-cp310-none-win_amd64.whl", hash = "sha256:3b919afe4df7eb6ac7cafd2bd14fb507d3f408db7a68c43117f579c984a73843"}, + {file = "tokenizers-0.15.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:89cd1cb93e4b12ff39bb2d626ad77e35209de9309a71e4d3d4672667b4b256e7"}, + {file = "tokenizers-0.15.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cfed5c64e5be23d7ee0f0e98081a25c2a46b0b77ce99a4f0605b1ec43dd481fa"}, + {file = "tokenizers-0.15.2-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a907d76dcfda37023ba203ab4ceeb21bc5683436ebefbd895a0841fd52f6f6f2"}, + {file = "tokenizers-0.15.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20ea60479de6fc7b8ae756b4b097572372d7e4032e2521c1bbf3d90c90a99ff0"}, + {file = "tokenizers-0.15.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:48e2b9335be2bc0171df9281385c2ed06a15f5cf121c44094338306ab7b33f2c"}, + {file = "tokenizers-0.15.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:112a1dd436d2cc06e6ffdc0b06d55ac019a35a63afd26475205cb4b1bf0bfbff"}, + {file = "tokenizers-0.15.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4620cca5c2817177ee8706f860364cc3a8845bc1e291aaf661fb899e5d1c45b0"}, + {file = "tokenizers-0.15.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ccd73a82751c523b3fc31ff8194702e4af4db21dc20e55b30ecc2079c5d43cb7"}, + {file = "tokenizers-0.15.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:107089f135b4ae7817affe6264f8c7a5c5b4fd9a90f9439ed495f54fcea56fb4"}, + {file = "tokenizers-0.15.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0ff110ecc57b7aa4a594396525a3451ad70988e517237fe91c540997c4e50e29"}, + {file = "tokenizers-0.15.2-cp311-none-win32.whl", hash = "sha256:6d76f00f5c32da36c61f41c58346a4fa7f0a61be02f4301fd30ad59834977cc3"}, + {file = "tokenizers-0.15.2-cp311-none-win_amd64.whl", hash = "sha256:cc90102ed17271cf0a1262babe5939e0134b3890345d11a19c3145184b706055"}, + {file = "tokenizers-0.15.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f86593c18d2e6248e72fb91c77d413a815153b8ea4e31f7cd443bdf28e467670"}, + {file = "tokenizers-0.15.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0774bccc6608eca23eb9d620196687c8b2360624619623cf4ba9dc9bd53e8b51"}, + {file = "tokenizers-0.15.2-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:d0222c5b7c9b26c0b4822a82f6a7011de0a9d3060e1da176f66274b70f846b98"}, + {file = "tokenizers-0.15.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3835738be1de66624fff2f4f6f6684775da4e9c00bde053be7564cbf3545cc66"}, + {file = "tokenizers-0.15.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0143e7d9dcd811855c1ce1ab9bf5d96d29bf5e528fd6c7824d0465741e8c10fd"}, + {file = "tokenizers-0.15.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db35825f6d54215f6b6009a7ff3eedee0848c99a6271c870d2826fbbedf31a38"}, + {file = "tokenizers-0.15.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3f5e64b0389a2be47091d8cc53c87859783b837ea1a06edd9d8e04004df55a5c"}, + {file = "tokenizers-0.15.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e0480c452217edd35eca56fafe2029fb4d368b7c0475f8dfa3c5c9c400a7456"}, + {file = "tokenizers-0.15.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a33ab881c8fe70474980577e033d0bc9a27b7ab8272896e500708b212995d834"}, + {file = "tokenizers-0.15.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a308a607ca9de2c64c1b9ba79ec9a403969715a1b8ba5f998a676826f1a7039d"}, + {file = "tokenizers-0.15.2-cp312-none-win32.whl", hash = "sha256:b8fcfa81bcb9447df582c5bc96a031e6df4da2a774b8080d4f02c0c16b42be0b"}, + {file = "tokenizers-0.15.2-cp312-none-win_amd64.whl", hash = "sha256:38d7ab43c6825abfc0b661d95f39c7f8af2449364f01d331f3b51c94dcff7221"}, + {file = "tokenizers-0.15.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:38bfb0204ff3246ca4d5e726e8cc8403bfc931090151e6eede54d0e0cf162ef0"}, + {file = "tokenizers-0.15.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9c861d35e8286a53e06e9e28d030b5a05bcbf5ac9d7229e561e53c352a85b1fc"}, + {file = "tokenizers-0.15.2-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:936bf3842db5b2048eaa53dade907b1160f318e7c90c74bfab86f1e47720bdd6"}, + {file = "tokenizers-0.15.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:620beacc3373277700d0e27718aa8b25f7b383eb8001fba94ee00aeea1459d89"}, + {file = "tokenizers-0.15.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2735ecbbf37e52db4ea970e539fd2d450d213517b77745114f92867f3fc246eb"}, + {file = "tokenizers-0.15.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:473c83c5e2359bb81b0b6fde870b41b2764fcdd36d997485e07e72cc3a62264a"}, + {file = "tokenizers-0.15.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:968fa1fb3c27398b28a4eca1cbd1e19355c4d3a6007f7398d48826bbe3a0f728"}, + {file = "tokenizers-0.15.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:865c60ae6eaebdde7da66191ee9b7db52e542ed8ee9d2c653b6d190a9351b980"}, + {file = "tokenizers-0.15.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7c0d8b52664ab2d4a8d6686eb5effc68b78608a9008f086a122a7b2996befbab"}, + {file = "tokenizers-0.15.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:f33dfbdec3784093a9aebb3680d1f91336c56d86cc70ddf88708251da1fe9064"}, + {file = "tokenizers-0.15.2-cp37-cp37m-macosx_10_12_x86_64.whl", hash = "sha256:d44ba80988ff9424e33e0a49445072ac7029d8c0e1601ad25a0ca5f41ed0c1d6"}, + {file = "tokenizers-0.15.2-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:dce74266919b892f82b1b86025a613956ea0ea62a4843d4c4237be2c5498ed3a"}, + {file = "tokenizers-0.15.2-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0ef06b9707baeb98b316577acb04f4852239d856b93e9ec3a299622f6084e4be"}, + {file = "tokenizers-0.15.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c73e2e74bbb07910da0d37c326869f34113137b23eadad3fc00856e6b3d9930c"}, + {file = "tokenizers-0.15.2-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4eeb12daf02a59e29f578a865f55d87cd103ce62bd8a3a5874f8fdeaa82e336b"}, + {file = "tokenizers-0.15.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9ba9f6895af58487ca4f54e8a664a322f16c26bbb442effd01087eba391a719e"}, + {file = "tokenizers-0.15.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ccec77aa7150e38eec6878a493bf8c263ff1fa8a62404e16c6203c64c1f16a26"}, + {file = "tokenizers-0.15.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3f40604f5042ff210ba82743dda2b6aa3e55aa12df4e9f2378ee01a17e2855e"}, + {file = "tokenizers-0.15.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:5645938a42d78c4885086767c70923abad047163d809c16da75d6b290cb30bbe"}, + {file = "tokenizers-0.15.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:05a77cbfebe28a61ab5c3891f9939cc24798b63fa236d84e5f29f3a85a200c00"}, + {file = "tokenizers-0.15.2-cp37-none-win32.whl", hash = "sha256:361abdc068e8afe9c5b818769a48624687fb6aaed49636ee39bec4e95e1a215b"}, + {file = "tokenizers-0.15.2-cp37-none-win_amd64.whl", hash = "sha256:7ef789f83eb0f9baeb4d09a86cd639c0a5518528f9992f38b28e819df397eb06"}, + {file = "tokenizers-0.15.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:4fe1f74a902bee74a3b25aff180fbfbf4f8b444ab37c4d496af7afd13a784ed2"}, + {file = "tokenizers-0.15.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4c4b89038a684f40a6b15d6b09f49650ac64d951ad0f2a3ea9169687bbf2a8ba"}, + {file = "tokenizers-0.15.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:d05a1b06f986d41aed5f2de464c003004b2df8aaf66f2b7628254bcbfb72a438"}, + {file = "tokenizers-0.15.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:508711a108684111ec8af89d3a9e9e08755247eda27d0ba5e3c50e9da1600f6d"}, + {file = "tokenizers-0.15.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:daa348f02d15160cb35439098ac96e3a53bacf35885072611cd9e5be7d333daa"}, + {file = "tokenizers-0.15.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:494fdbe5932d3416de2a85fc2470b797e6f3226c12845cadf054dd906afd0442"}, + {file = "tokenizers-0.15.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2d60f5246f4da9373f75ff18d64c69cbf60c3bca597290cea01059c336d2470"}, + {file = "tokenizers-0.15.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93268e788825f52de4c7bdcb6ebc1fcd4a5442c02e730faa9b6b08f23ead0e24"}, + {file = "tokenizers-0.15.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6fc7083ab404019fc9acafe78662c192673c1e696bd598d16dc005bd663a5cf9"}, + {file = "tokenizers-0.15.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:41e39b41e5531d6b2122a77532dbea60e171ef87a3820b5a3888daa847df4153"}, + {file = "tokenizers-0.15.2-cp38-none-win32.whl", hash = "sha256:06cd0487b1cbfabefb2cc52fbd6b1f8d4c37799bd6c6e1641281adaa6b2504a7"}, + {file = "tokenizers-0.15.2-cp38-none-win_amd64.whl", hash = "sha256:5179c271aa5de9c71712e31cb5a79e436ecd0d7532a408fa42a8dbfa4bc23fd9"}, + {file = "tokenizers-0.15.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:82f8652a74cc107052328b87ea8b34291c0f55b96d8fb261b3880216a9f9e48e"}, + {file = "tokenizers-0.15.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:02458bee6f5f3139f1ebbb6d042b283af712c0981f5bc50edf771d6b762d5e4f"}, + {file = "tokenizers-0.15.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c9a09cd26cca2e1c349f91aa665309ddb48d71636370749414fbf67bc83c5343"}, + {file = "tokenizers-0.15.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:158be8ea8554e5ed69acc1ce3fbb23a06060bd4bbb09029431ad6b9a466a7121"}, + {file = "tokenizers-0.15.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1ddba9a2b0c8c81633eca0bb2e1aa5b3a15362b1277f1ae64176d0f6eba78ab1"}, + {file = "tokenizers-0.15.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3ef5dd1d39797044642dbe53eb2bc56435308432e9c7907728da74c69ee2adca"}, + {file = "tokenizers-0.15.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:454c203164e07a860dbeb3b1f4a733be52b0edbb4dd2e5bd75023ffa8b49403a"}, + {file = "tokenizers-0.15.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0cf6b7f1d4dc59af960e6ffdc4faffe6460bbfa8dce27a58bf75755ffdb2526d"}, + {file = "tokenizers-0.15.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2ef09bbc16519f6c25d0c7fc0c6a33a6f62923e263c9d7cca4e58b8c61572afb"}, + {file = "tokenizers-0.15.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c9a2ebdd2ad4ec7a68e7615086e633857c85e2f18025bd05d2a4399e6c5f7169"}, + {file = "tokenizers-0.15.2-cp39-none-win32.whl", hash = "sha256:918fbb0eab96fe08e72a8c2b5461e9cce95585d82a58688e7f01c2bd546c79d0"}, + {file = "tokenizers-0.15.2-cp39-none-win_amd64.whl", hash = "sha256:524e60da0135e106b254bd71f0659be9f89d83f006ea9093ce4d1fab498c6d0d"}, + {file = "tokenizers-0.15.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6a9b648a58281c4672212fab04e60648fde574877d0139cd4b4f93fe28ca8944"}, + {file = "tokenizers-0.15.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:7c7d18b733be6bbca8a55084027f7be428c947ddf871c500ee603e375013ffba"}, + {file = "tokenizers-0.15.2-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:13ca3611de8d9ddfbc4dc39ef54ab1d2d4aaa114ac8727dfdc6a6ec4be017378"}, + {file = "tokenizers-0.15.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:237d1bf3361cf2e6463e6c140628e6406766e8b27274f5fcc62c747ae3c6f094"}, + {file = "tokenizers-0.15.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67a0fe1e49e60c664915e9fb6b0cb19bac082ab1f309188230e4b2920230edb3"}, + {file = "tokenizers-0.15.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4e022fe65e99230b8fd89ebdfea138c24421f91c1a4f4781a8f5016fd5cdfb4d"}, + {file = "tokenizers-0.15.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:d857be2df69763362ac699f8b251a8cd3fac9d21893de129bc788f8baaef2693"}, + {file = "tokenizers-0.15.2-pp37-pypy37_pp73-macosx_10_12_x86_64.whl", hash = "sha256:708bb3e4283177236309e698da5fcd0879ce8fd37457d7c266d16b550bcbbd18"}, + {file = "tokenizers-0.15.2-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:64c35e09e9899b72a76e762f9854e8750213f67567787d45f37ce06daf57ca78"}, + {file = "tokenizers-0.15.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1257f4394be0d3b00de8c9e840ca5601d0a4a8438361ce9c2b05c7d25f6057b"}, + {file = "tokenizers-0.15.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02272fe48280e0293a04245ca5d919b2c94a48b408b55e858feae9618138aeda"}, + {file = "tokenizers-0.15.2-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:dc3ad9ebc76eabe8b1d7c04d38be884b8f9d60c0cdc09b0aa4e3bcf746de0388"}, + {file = "tokenizers-0.15.2-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:32e16bdeffa7c4f46bf2152172ca511808b952701d13e7c18833c0b73cb5c23f"}, + {file = "tokenizers-0.15.2-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:fb16ba563d59003028b678d2361a27f7e4ae0ab29c7a80690efa20d829c81fdb"}, + {file = "tokenizers-0.15.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:2277c36d2d6cdb7876c274547921a42425b6810d38354327dd65a8009acf870c"}, + {file = "tokenizers-0.15.2-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1cf75d32e8d250781940d07f7eece253f2fe9ecdb1dc7ba6e3833fa17b82fcbc"}, + {file = "tokenizers-0.15.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1b3b31884dc8e9b21508bb76da80ebf7308fdb947a17affce815665d5c4d028"}, + {file = "tokenizers-0.15.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b10122d8d8e30afb43bb1fe21a3619f62c3e2574bff2699cf8af8b0b6c5dc4a3"}, + {file = "tokenizers-0.15.2-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d88b96ff0fe8e91f6ef01ba50b0d71db5017fa4e3b1d99681cec89a85faf7bf7"}, + {file = "tokenizers-0.15.2-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:37aaec5a52e959892870a7c47cef80c53797c0db9149d458460f4f31e2fb250e"}, + {file = "tokenizers-0.15.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e2ea752f2b0fe96eb6e2f3adbbf4d72aaa1272079b0dfa1145507bd6a5d537e6"}, + {file = "tokenizers-0.15.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:4b19a808d8799fda23504a5cd31d2f58e6f52f140380082b352f877017d6342b"}, + {file = "tokenizers-0.15.2-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:64c86e5e068ac8b19204419ed8ca90f9d25db20578f5881e337d203b314f4104"}, + {file = "tokenizers-0.15.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de19c4dc503c612847edf833c82e9f73cd79926a384af9d801dcf93f110cea4e"}, + {file = "tokenizers-0.15.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea09acd2fe3324174063d61ad620dec3bcf042b495515f27f638270a7d466e8b"}, + {file = "tokenizers-0.15.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:cf27fd43472e07b57cf420eee1e814549203d56de00b5af8659cb99885472f1f"}, + {file = "tokenizers-0.15.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:7ca22bd897537a0080521445d91a58886c8c04084a6a19e6c78c586e0cfa92a5"}, + {file = "tokenizers-0.15.2.tar.gz", hash = "sha256:e6e9c6e019dd5484be5beafc775ae6c925f4c69a3487040ed09b45e13df2cb91"}, +] + +[package.dependencies] +huggingface_hub = ">=0.16.4,<1.0" + +[package.extras] +dev = ["tokenizers[testing]"] +docs = ["setuptools_rust", "sphinx", "sphinx_rtd_theme"] +testing = ["black (==22.3)", "datasets", "numpy", "pytest", "requests"] + +[[package]] +name = "toml" +version = "0.10.2" +description = "Python Library for Tom's Obvious, Minimal Language" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[[package]] +name = "tornado" +version = "6.4" +description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." +optional = false +python-versions = ">= 3.8" +files = [ + {file = "tornado-6.4-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:02ccefc7d8211e5a7f9e8bc3f9e5b0ad6262ba2fbb683a6443ecc804e5224ce0"}, + {file = "tornado-6.4-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:27787de946a9cffd63ce5814c33f734c627a87072ec7eed71f7fc4417bb16263"}, + {file = "tornado-6.4-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7894c581ecdcf91666a0912f18ce5e757213999e183ebfc2c3fdbf4d5bd764e"}, + {file = "tornado-6.4-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e43bc2e5370a6a8e413e1e1cd0c91bedc5bd62a74a532371042a18ef19e10579"}, + {file = "tornado-6.4-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0251554cdd50b4b44362f73ad5ba7126fc5b2c2895cc62b14a1c2d7ea32f212"}, + {file = "tornado-6.4-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fd03192e287fbd0899dd8f81c6fb9cbbc69194d2074b38f384cb6fa72b80e9c2"}, + {file = "tornado-6.4-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:88b84956273fbd73420e6d4b8d5ccbe913c65d31351b4c004ae362eba06e1f78"}, + {file = "tornado-6.4-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:71ddfc23a0e03ef2df1c1397d859868d158c8276a0603b96cf86892bff58149f"}, + {file = "tornado-6.4-cp38-abi3-win32.whl", hash = "sha256:6f8a6c77900f5ae93d8b4ae1196472d0ccc2775cc1dfdc9e7727889145c45052"}, + {file = "tornado-6.4-cp38-abi3-win_amd64.whl", hash = "sha256:10aeaa8006333433da48dec9fe417877f8bcc21f48dda8d661ae79da357b2a63"}, + {file = "tornado-6.4.tar.gz", hash = "sha256:72291fa6e6bc84e626589f1c29d90a5a6d593ef5ae68052ee2ef000dfd273dee"}, +] + +[[package]] +name = "tqdm" +version = "4.66.2" +description = "Fast, Extensible Progress Meter" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tqdm-4.66.2-py3-none-any.whl", hash = "sha256:1ee4f8a893eb9bef51c6e35730cebf234d5d0b6bd112b0271e10ed7c24a02bd9"}, + {file = "tqdm-4.66.2.tar.gz", hash = "sha256:6cd52cdf0fef0e0f543299cfc96fec90d7b8a7e88745f411ec33eb44d5ed3531"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[package.extras] +dev = ["pytest (>=6)", "pytest-cov", "pytest-timeout", "pytest-xdist"] +notebook = ["ipywidgets (>=6)"] +slack = ["slack-sdk"] +telegram = ["requests"] + +[[package]] +name = "traitlets" +version = "5.14.2" +description = "Traitlets Python configuration system" +optional = false +python-versions = ">=3.8" +files = [ + {file = "traitlets-5.14.2-py3-none-any.whl", hash = "sha256:fcdf85684a772ddeba87db2f398ce00b40ff550d1528c03c14dbf6a02003cd80"}, + {file = "traitlets-5.14.2.tar.gz", hash = "sha256:8cdd83c040dab7d1dee822678e5f5d100b514f7b72b01615b26fc5718916fdf9"}, +] + +[package.extras] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] +test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<8.1)", "pytest-mock", "pytest-mypy-testing"] + +[[package]] +name = "typer" +version = "0.9.4" +description = "Typer, build great CLIs. Easy to code. Based on Python type hints." +optional = false +python-versions = ">=3.6" +files = [ + {file = "typer-0.9.4-py3-none-any.whl", hash = "sha256:aa6c4a4e2329d868b80ecbaf16f807f2b54e192209d7ac9dd42691d63f7a54eb"}, + {file = "typer-0.9.4.tar.gz", hash = "sha256:f714c2d90afae3a7929fcd72a3abb08df305e1ff61719381384211c4070af57f"}, +] + +[package.dependencies] +click = ">=7.1.1,<9.0.0" +typing-extensions = ">=3.7.4.3" + +[package.extras] +all = ["colorama (>=0.4.3,<0.5.0)", "rich (>=10.11.0,<14.0.0)", "shellingham (>=1.3.0,<2.0.0)"] +dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "pre-commit (>=2.17.0,<3.0.0)"] +doc = ["cairosvg (>=2.5.2,<3.0.0)", "mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "pillow (>=9.3.0,<10.0.0)"] +test = ["black (>=22.3.0,<23.0.0)", "coverage (>=6.2,<7.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.971)", "pytest (>=4.4.0,<8.0.0)", "pytest-cov (>=2.10.0,<5.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "pytest-xdist (>=1.32.0,<4.0.0)", "rich (>=10.11.0,<14.0.0)", "shellingham (>=1.3.0,<2.0.0)"] + +[[package]] +name = "types-google-cloud-ndb" +version = "2.3.0.20240311" +description = "Typing stubs for google-cloud-ndb" +optional = false +python-versions = ">=3.8" +files = [ + {file = "types-google-cloud-ndb-2.3.0.20240311.tar.gz", hash = "sha256:c37a149f313827d9443a0f7b8dfd572292f9d9dabb8a9c4d68cdba81689a380f"}, + {file = "types_google_cloud_ndb-2.3.0.20240311-py3-none-any.whl", hash = "sha256:8209962a420d2c60615ee26bc21ad74d77a3e337045b70ed86843a974f2d2ecd"}, +] + +[[package]] +name = "types-passlib" +version = "1.7.7.20240327" +description = "Typing stubs for passlib" +optional = false +python-versions = ">=3.8" +files = [ + {file = "types-passlib-1.7.7.20240327.tar.gz", hash = "sha256:4cce6a1a3a6afee9fc4728b4d9784300764ac2be747f5bcc01646d904b85f4bb"}, + {file = "types_passlib-1.7.7.20240327-py3-none-any.whl", hash = "sha256:3a3b7f4258b71034d2e2f4f307d6810f9904f906cdf375514c8bdbdb28a4ad23"}, +] + +[[package]] +name = "types-pillow" +version = "9.5.0.6" +description = "Typing stubs for Pillow" +optional = false +python-versions = "*" +files = [ + {file = "types-Pillow-9.5.0.6.tar.gz", hash = "sha256:6a0cad40686e5c35fe7ada70f52bd3970395d31ece33486609e5420e820a9e4e"}, + {file = "types_Pillow-9.5.0.6-py3-none-any.whl", hash = "sha256:1d238abaa9d529b04941d805b7f4d3f7df30702bb14521ec507617f117406fb4"}, +] + +[[package]] +name = "types-pyasn1" +version = "0.6.0.20240402" +description = "Typing stubs for pyasn1" +optional = false +python-versions = ">=3.8" +files = [ + {file = "types-pyasn1-0.6.0.20240402.tar.gz", hash = "sha256:5d54dcb33f69dd269071ca098e923ac20c5f03c814631fa7f3ed9ee035a5da3a"}, + {file = "types_pyasn1-0.6.0.20240402-py3-none-any.whl", hash = "sha256:848d01e7313c200acc035a8b3d377fe7b2aecbe77f2be49eb160a7f82835aaaf"}, +] + +[[package]] +name = "types-pyopenssl" +version = "24.0.0.20240311" +description = "Typing stubs for pyOpenSSL" +optional = false +python-versions = ">=3.8" +files = [ + {file = "types-pyOpenSSL-24.0.0.20240311.tar.gz", hash = "sha256:7bca00cfc4e7ef9c5d2663c6a1c068c35798e59670595439f6296e7ba3d58083"}, + {file = "types_pyOpenSSL-24.0.0.20240311-py3-none-any.whl", hash = "sha256:6e8e8bfad34924067333232c93f7fc4b369856d8bea0d5c9d1808cb290ab1972"}, +] + +[package.dependencies] +cryptography = ">=35.0.0" + +[[package]] +name = "types-python-jose" +version = "3.3.4.20240106" +description = "Typing stubs for python-jose" +optional = false +python-versions = ">=3.8" +files = [ + {file = "types-python-jose-3.3.4.20240106.tar.gz", hash = "sha256:b18cf8c5080bbfe1ef7c3b707986435d9efca3e90889acb6a06f65e06bc3405a"}, + {file = "types_python_jose-3.3.4.20240106-py3-none-any.whl", hash = "sha256:b515a6c0c61f5e2a53bc93e3a2b024cbd42563e2e19cbde9fd1c2cc2cfe77ccc"}, +] + +[package.dependencies] +types-pyasn1 = "*" + +[[package]] +name = "types-pytz" +version = "2024.1.0.20240203" +description = "Typing stubs for pytz" +optional = false +python-versions = ">=3.8" +files = [ + {file = "types-pytz-2024.1.0.20240203.tar.gz", hash = "sha256:c93751ee20dfc6e054a0148f8f5227b9a00b79c90a4d3c9f464711a73179c89e"}, + {file = "types_pytz-2024.1.0.20240203-py3-none-any.whl", hash = "sha256:9679eef0365db3af91ef7722c199dbb75ee5c1b67e3c4dd7bfbeb1b8a71c21a3"}, +] + +[[package]] +name = "types-pywin32" +version = "306.0.0.20240331" +description = "Typing stubs for pywin32" +optional = false +python-versions = ">=3.8" +files = [ + {file = "types-pywin32-306.0.0.20240331.tar.gz", hash = "sha256:3427e60ffbbc47b31e6bc416c3e4c37d579e6774e5152dab953589c9b64c4d58"}, + {file = "types_pywin32-306.0.0.20240331-py3-none-any.whl", hash = "sha256:844b90253f3da38e254c9ce199ba41f63da52c511003daedcda414e88f1cf319"}, +] + +[[package]] +name = "types-pyyaml" +version = "6.0.12.20240311" +description = "Typing stubs for PyYAML" +optional = false +python-versions = ">=3.8" +files = [ + {file = "types-PyYAML-6.0.12.20240311.tar.gz", hash = "sha256:a9e0f0f88dc835739b0c1ca51ee90d04ca2a897a71af79de9aec5f38cb0a5342"}, + {file = "types_PyYAML-6.0.12.20240311-py3-none-any.whl", hash = "sha256:b845b06a1c7e54b8e5b4c683043de0d9caf205e7434b3edc678ff2411979b8f6"}, +] + +[[package]] +name = "types-redis" +version = "4.6.0.20240311" +description = "Typing stubs for redis" +optional = false +python-versions = ">=3.8" +files = [ + {file = "types-redis-4.6.0.20240311.tar.gz", hash = "sha256:e049bbdff0e0a1f8e701b64636811291d21bff79bf1e7850850a44055224a85f"}, + {file = "types_redis-4.6.0.20240311-py3-none-any.whl", hash = "sha256:6b9d68a29aba1ee400c823d8e5fe88675282eb69d7211e72fe65dbe54b33daca"}, +] + +[package.dependencies] +cryptography = ">=35.0.0" +types-pyOpenSSL = "*" + +[[package]] +name = "types-requests" +version = "2.31.0.20240403" +description = "Typing stubs for requests" +optional = false +python-versions = ">=3.8" +files = [ + {file = "types-requests-2.31.0.20240403.tar.gz", hash = "sha256:e1e0cd0b655334f39d9f872b68a1310f0e343647688bf2cee932ec4c2b04de59"}, + {file = "types_requests-2.31.0.20240403-py3-none-any.whl", hash = "sha256:06abf6a68f5c4f2a62f6bb006672dfb26ed50ccbfddb281e1ee6f09a65707d5d"}, +] + +[package.dependencies] +urllib3 = ">=2" + +[[package]] +name = "typing-extensions" +version = "4.10.0" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"}, + {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"}, +] + +[[package]] +name = "typing-inspect" +version = "0.9.0" +description = "Runtime inspection utilities for typing module." +optional = false +python-versions = "*" +files = [ + {file = "typing_inspect-0.9.0-py3-none-any.whl", hash = "sha256:9ee6fc59062311ef8547596ab6b955e1b8aa46242d854bfc78f4f6b0eff35f9f"}, + {file = "typing_inspect-0.9.0.tar.gz", hash = "sha256:b23fc42ff6f6ef6954e4852c1fb512cdd18dbea03134f91f856a95ccc9461f78"}, +] + +[package.dependencies] +mypy-extensions = ">=0.3.0" +typing-extensions = ">=3.7.4" + +[[package]] +name = "tzdata" +version = "2024.1" +description = "Provider of IANA time zone data" +optional = false +python-versions = ">=2" +files = [ + {file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"}, + {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, +] + +[[package]] +name = "urllib3" +version = "2.2.1" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.8" +files = [ + {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, + {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "uvicorn" +version = "0.27.1" +description = "The lightning-fast ASGI server." +optional = false +python-versions = ">=3.8" +files = [ + {file = "uvicorn-0.27.1-py3-none-any.whl", hash = "sha256:5c89da2f3895767472a35556e539fd59f7edbe9b1e9c0e1c99eebeadc61838e4"}, + {file = "uvicorn-0.27.1.tar.gz", hash = "sha256:3d9a267296243532db80c83a959a3400502165ade2c1338dea4e67915fd4745a"}, +] + +[package.dependencies] +click = ">=7.0" +colorama = {version = ">=0.4", optional = true, markers = "sys_platform == \"win32\" and extra == \"standard\""} +h11 = ">=0.8" +httptools = {version = ">=0.5.0", optional = true, markers = "extra == \"standard\""} +python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} +pyyaml = {version = ">=5.1", optional = true, markers = "extra == \"standard\""} +typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""} +uvloop = {version = ">=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1", optional = true, markers = "(sys_platform != \"win32\" and sys_platform != \"cygwin\") and platform_python_implementation != \"PyPy\" and extra == \"standard\""} +watchfiles = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} +websockets = {version = ">=10.4", optional = true, markers = "extra == \"standard\""} + +[package.extras] +standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] + +[[package]] +name = "uvloop" +version = "0.19.0" +description = "Fast implementation of asyncio event loop on top of libuv" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:de4313d7f575474c8f5a12e163f6d89c0a878bc49219641d49e6f1444369a90e"}, + {file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5588bd21cf1fcf06bded085f37e43ce0e00424197e7c10e77afd4bbefffef428"}, + {file = "uvloop-0.19.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b1fd71c3843327f3bbc3237bedcdb6504fd50368ab3e04d0410e52ec293f5b8"}, + {file = "uvloop-0.19.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a05128d315e2912791de6088c34136bfcdd0c7cbc1cf85fd6fd1bb321b7c849"}, + {file = "uvloop-0.19.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:cd81bdc2b8219cb4b2556eea39d2e36bfa375a2dd021404f90a62e44efaaf957"}, + {file = "uvloop-0.19.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5f17766fb6da94135526273080f3455a112f82570b2ee5daa64d682387fe0dcd"}, + {file = "uvloop-0.19.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4ce6b0af8f2729a02a5d1575feacb2a94fc7b2e983868b009d51c9a9d2149bef"}, + {file = "uvloop-0.19.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:31e672bb38b45abc4f26e273be83b72a0d28d074d5b370fc4dcf4c4eb15417d2"}, + {file = "uvloop-0.19.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:570fc0ed613883d8d30ee40397b79207eedd2624891692471808a95069a007c1"}, + {file = "uvloop-0.19.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5138821e40b0c3e6c9478643b4660bd44372ae1e16a322b8fc07478f92684e24"}, + {file = "uvloop-0.19.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:91ab01c6cd00e39cde50173ba4ec68a1e578fee9279ba64f5221810a9e786533"}, + {file = "uvloop-0.19.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:47bf3e9312f63684efe283f7342afb414eea4d3011542155c7e625cd799c3b12"}, + {file = "uvloop-0.19.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:da8435a3bd498419ee8c13c34b89b5005130a476bda1d6ca8cfdde3de35cd650"}, + {file = "uvloop-0.19.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:02506dc23a5d90e04d4f65c7791e65cf44bd91b37f24cfc3ef6cf2aff05dc7ec"}, + {file = "uvloop-0.19.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2693049be9d36fef81741fddb3f441673ba12a34a704e7b4361efb75cf30befc"}, + {file = "uvloop-0.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7010271303961c6f0fe37731004335401eb9075a12680738731e9c92ddd96ad6"}, + {file = "uvloop-0.19.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5daa304d2161d2918fa9a17d5635099a2f78ae5b5960e742b2fcfbb7aefaa593"}, + {file = "uvloop-0.19.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7207272c9520203fea9b93843bb775d03e1cf88a80a936ce760f60bb5add92f3"}, + {file = "uvloop-0.19.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:78ab247f0b5671cc887c31d33f9b3abfb88d2614b84e4303f1a63b46c046c8bd"}, + {file = "uvloop-0.19.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:472d61143059c84947aa8bb74eabbace30d577a03a1805b77933d6bd13ddebbd"}, + {file = "uvloop-0.19.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45bf4c24c19fb8a50902ae37c5de50da81de4922af65baf760f7c0c42e1088be"}, + {file = "uvloop-0.19.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:271718e26b3e17906b28b67314c45d19106112067205119dddbd834c2b7ce797"}, + {file = "uvloop-0.19.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:34175c9fd2a4bc3adc1380e1261f60306344e3407c20a4d684fd5f3be010fa3d"}, + {file = "uvloop-0.19.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e27f100e1ff17f6feeb1f33968bc185bf8ce41ca557deee9d9bbbffeb72030b7"}, + {file = "uvloop-0.19.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13dfdf492af0aa0a0edf66807d2b465607d11c4fa48f4a1fd41cbea5b18e8e8b"}, + {file = "uvloop-0.19.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6e3d4e85ac060e2342ff85e90d0c04157acb210b9ce508e784a944f852a40e67"}, + {file = "uvloop-0.19.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8ca4956c9ab567d87d59d49fa3704cf29e37109ad348f2d5223c9bf761a332e7"}, + {file = "uvloop-0.19.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f467a5fd23b4fc43ed86342641f3936a68ded707f4627622fa3f82a120e18256"}, + {file = "uvloop-0.19.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:492e2c32c2af3f971473bc22f086513cedfc66a130756145a931a90c3958cb17"}, + {file = "uvloop-0.19.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2df95fca285a9f5bfe730e51945ffe2fa71ccbfdde3b0da5772b4ee4f2e770d5"}, + {file = "uvloop-0.19.0.tar.gz", hash = "sha256:0246f4fd1bf2bf702e06b0d45ee91677ee5c31242f39aab4ea6fe0c51aedd0fd"}, +] + +[package.extras] +docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] +test = ["Cython (>=0.29.36,<0.30.0)", "aiohttp (==3.9.0b0)", "aiohttp (>=3.8.1)", "flake8 (>=5.0,<6.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=23.0.0,<23.1.0)", "pycodestyle (>=2.9.0,<2.10.0)"] + +[[package]] +name = "watchfiles" +version = "0.21.0" +description = "Simple, modern and high performance file watching and code reload in python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "watchfiles-0.21.0-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:27b4035013f1ea49c6c0b42d983133b136637a527e48c132d368eb19bf1ac6aa"}, + {file = "watchfiles-0.21.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c81818595eff6e92535ff32825f31c116f867f64ff8cdf6562cd1d6b2e1e8f3e"}, + {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6c107ea3cf2bd07199d66f156e3ea756d1b84dfd43b542b2d870b77868c98c03"}, + {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d9ac347653ebd95839a7c607608703b20bc07e577e870d824fa4801bc1cb124"}, + {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5eb86c6acb498208e7663ca22dbe68ca2cf42ab5bf1c776670a50919a56e64ab"}, + {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f564bf68404144ea6b87a78a3f910cc8de216c6b12a4cf0b27718bf4ec38d303"}, + {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d0f32ebfaa9c6011f8454994f86108c2eb9c79b8b7de00b36d558cadcedaa3d"}, + {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6d45d9b699ecbac6c7bd8e0a2609767491540403610962968d258fd6405c17c"}, + {file = "watchfiles-0.21.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:aff06b2cac3ef4616e26ba17a9c250c1fe9dd8a5d907d0193f84c499b1b6e6a9"}, + {file = "watchfiles-0.21.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d9792dff410f266051025ecfaa927078b94cc7478954b06796a9756ccc7e14a9"}, + {file = "watchfiles-0.21.0-cp310-none-win32.whl", hash = "sha256:214cee7f9e09150d4fb42e24919a1e74d8c9b8a9306ed1474ecaddcd5479c293"}, + {file = "watchfiles-0.21.0-cp310-none-win_amd64.whl", hash = "sha256:1ad7247d79f9f55bb25ab1778fd47f32d70cf36053941f07de0b7c4e96b5d235"}, + {file = "watchfiles-0.21.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:668c265d90de8ae914f860d3eeb164534ba2e836811f91fecc7050416ee70aa7"}, + {file = "watchfiles-0.21.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a23092a992e61c3a6a70f350a56db7197242f3490da9c87b500f389b2d01eef"}, + {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e7941bbcfdded9c26b0bf720cb7e6fd803d95a55d2c14b4bd1f6a2772230c586"}, + {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:11cd0c3100e2233e9c53106265da31d574355c288e15259c0d40a4405cbae317"}, + {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d78f30cbe8b2ce770160d3c08cff01b2ae9306fe66ce899b73f0409dc1846c1b"}, + {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6674b00b9756b0af620aa2a3346b01f8e2a3dc729d25617e1b89cf6af4a54eb1"}, + {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fd7ac678b92b29ba630d8c842d8ad6c555abda1b9ef044d6cc092dacbfc9719d"}, + {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c873345680c1b87f1e09e0eaf8cf6c891b9851d8b4d3645e7efe2ec20a20cc7"}, + {file = "watchfiles-0.21.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:49f56e6ecc2503e7dbe233fa328b2be1a7797d31548e7a193237dcdf1ad0eee0"}, + {file = "watchfiles-0.21.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:02d91cbac553a3ad141db016e3350b03184deaafeba09b9d6439826ee594b365"}, + {file = "watchfiles-0.21.0-cp311-none-win32.whl", hash = "sha256:ebe684d7d26239e23d102a2bad2a358dedf18e462e8808778703427d1f584400"}, + {file = "watchfiles-0.21.0-cp311-none-win_amd64.whl", hash = "sha256:4566006aa44cb0d21b8ab53baf4b9c667a0ed23efe4aaad8c227bfba0bf15cbe"}, + {file = "watchfiles-0.21.0-cp311-none-win_arm64.whl", hash = "sha256:c550a56bf209a3d987d5a975cdf2063b3389a5d16caf29db4bdddeae49f22078"}, + {file = "watchfiles-0.21.0-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:51ddac60b96a42c15d24fbdc7a4bfcd02b5a29c047b7f8bf63d3f6f5a860949a"}, + {file = "watchfiles-0.21.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:511f0b034120cd1989932bf1e9081aa9fb00f1f949fbd2d9cab6264916ae89b1"}, + {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cfb92d49dbb95ec7a07511bc9efb0faff8fe24ef3805662b8d6808ba8409a71a"}, + {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f92944efc564867bbf841c823c8b71bb0be75e06b8ce45c084b46411475a915"}, + {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:642d66b75eda909fd1112d35c53816d59789a4b38c141a96d62f50a3ef9b3360"}, + {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d23bcd6c8eaa6324fe109d8cac01b41fe9a54b8c498af9ce464c1aeeb99903d6"}, + {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18d5b4da8cf3e41895b34e8c37d13c9ed294954907929aacd95153508d5d89d7"}, + {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b8d1eae0f65441963d805f766c7e9cd092f91e0c600c820c764a4ff71a0764c"}, + {file = "watchfiles-0.21.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1fd9a5205139f3c6bb60d11f6072e0552f0a20b712c85f43d42342d162be1235"}, + {file = "watchfiles-0.21.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a1e3014a625bcf107fbf38eece0e47fa0190e52e45dc6eee5a8265ddc6dc5ea7"}, + {file = "watchfiles-0.21.0-cp312-none-win32.whl", hash = "sha256:9d09869f2c5a6f2d9df50ce3064b3391d3ecb6dced708ad64467b9e4f2c9bef3"}, + {file = "watchfiles-0.21.0-cp312-none-win_amd64.whl", hash = "sha256:18722b50783b5e30a18a8a5db3006bab146d2b705c92eb9a94f78c72beb94094"}, + {file = "watchfiles-0.21.0-cp312-none-win_arm64.whl", hash = "sha256:a3b9bec9579a15fb3ca2d9878deae789df72f2b0fdaf90ad49ee389cad5edab6"}, + {file = "watchfiles-0.21.0-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:4ea10a29aa5de67de02256a28d1bf53d21322295cb00bd2d57fcd19b850ebd99"}, + {file = "watchfiles-0.21.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:40bca549fdc929b470dd1dbfcb47b3295cb46a6d2c90e50588b0a1b3bd98f429"}, + {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9b37a7ba223b2f26122c148bb8d09a9ff312afca998c48c725ff5a0a632145f7"}, + {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec8c8900dc5c83650a63dd48c4d1d245343f904c4b64b48798c67a3767d7e165"}, + {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8ad3fe0a3567c2f0f629d800409cd528cb6251da12e81a1f765e5c5345fd0137"}, + {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d353c4cfda586db2a176ce42c88f2fc31ec25e50212650c89fdd0f560ee507b"}, + {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:83a696da8922314ff2aec02987eefb03784f473281d740bf9170181829133765"}, + {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a03651352fc20975ee2a707cd2d74a386cd303cc688f407296064ad1e6d1562"}, + {file = "watchfiles-0.21.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3ad692bc7792be8c32918c699638b660c0de078a6cbe464c46e1340dadb94c19"}, + {file = "watchfiles-0.21.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06247538e8253975bdb328e7683f8515ff5ff041f43be6c40bff62d989b7d0b0"}, + {file = "watchfiles-0.21.0-cp38-none-win32.whl", hash = "sha256:9a0aa47f94ea9a0b39dd30850b0adf2e1cd32a8b4f9c7aa443d852aacf9ca214"}, + {file = "watchfiles-0.21.0-cp38-none-win_amd64.whl", hash = "sha256:8d5f400326840934e3507701f9f7269247f7c026d1b6cfd49477d2be0933cfca"}, + {file = "watchfiles-0.21.0-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:7f762a1a85a12cc3484f77eee7be87b10f8c50b0b787bb02f4e357403cad0c0e"}, + {file = "watchfiles-0.21.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6e9be3ef84e2bb9710f3f777accce25556f4a71e15d2b73223788d528fcc2052"}, + {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4c48a10d17571d1275701e14a601e36959ffada3add8cdbc9e5061a6e3579a5d"}, + {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c889025f59884423428c261f212e04d438de865beda0b1e1babab85ef4c0f01"}, + {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:66fac0c238ab9a2e72d026b5fb91cb902c146202bbd29a9a1a44e8db7b710b6f"}, + {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b4a21f71885aa2744719459951819e7bf5a906a6448a6b2bbce8e9cc9f2c8128"}, + {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c9198c989f47898b2c22201756f73249de3748e0fc9de44adaf54a8b259cc0c"}, + {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8f57c4461cd24fda22493109c45b3980863c58a25b8bec885ca8bea6b8d4b28"}, + {file = "watchfiles-0.21.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:853853cbf7bf9408b404754b92512ebe3e3a83587503d766d23e6bf83d092ee6"}, + {file = "watchfiles-0.21.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d5b1dc0e708fad9f92c296ab2f948af403bf201db8fb2eb4c8179db143732e49"}, + {file = "watchfiles-0.21.0-cp39-none-win32.whl", hash = "sha256:59137c0c6826bd56c710d1d2bda81553b5e6b7c84d5a676747d80caf0409ad94"}, + {file = "watchfiles-0.21.0-cp39-none-win_amd64.whl", hash = "sha256:6cb8fdc044909e2078c248986f2fc76f911f72b51ea4a4fbbf472e01d14faa58"}, + {file = "watchfiles-0.21.0-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:ab03a90b305d2588e8352168e8c5a1520b721d2d367f31e9332c4235b30b8994"}, + {file = "watchfiles-0.21.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:927c589500f9f41e370b0125c12ac9e7d3a2fd166b89e9ee2828b3dda20bfe6f"}, + {file = "watchfiles-0.21.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bd467213195e76f838caf2c28cd65e58302d0254e636e7c0fca81efa4a2e62c"}, + {file = "watchfiles-0.21.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02b73130687bc3f6bb79d8a170959042eb56eb3a42df3671c79b428cd73f17cc"}, + {file = "watchfiles-0.21.0-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:08dca260e85ffae975448e344834d765983237ad6dc308231aa16e7933db763e"}, + {file = "watchfiles-0.21.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:3ccceb50c611c433145502735e0370877cced72a6c70fd2410238bcbc7fe51d8"}, + {file = "watchfiles-0.21.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57d430f5fb63fea141ab71ca9c064e80de3a20b427ca2febcbfcef70ff0ce895"}, + {file = "watchfiles-0.21.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dd5fad9b9c0dd89904bbdea978ce89a2b692a7ee8a0ce19b940e538c88a809c"}, + {file = "watchfiles-0.21.0-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:be6dd5d52b73018b21adc1c5d28ac0c68184a64769052dfeb0c5d9998e7f56a2"}, + {file = "watchfiles-0.21.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:b3cab0e06143768499384a8a5efb9c4dc53e19382952859e4802f294214f36ec"}, + {file = "watchfiles-0.21.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c6ed10c2497e5fedadf61e465b3ca12a19f96004c15dcffe4bd442ebadc2d85"}, + {file = "watchfiles-0.21.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43babacef21c519bc6631c5fce2a61eccdfc011b4bcb9047255e9620732c8097"}, + {file = "watchfiles-0.21.0.tar.gz", hash = "sha256:c76c635fabf542bb78524905718c39f736a98e5ab25b23ec6d4abede1a85a6a3"}, +] + +[package.dependencies] +anyio = ">=3.0.0" + +[[package]] +name = "wcwidth" +version = "0.2.13" +description = "Measures the displayed width of unicode strings in a terminal" +optional = false +python-versions = "*" +files = [ + {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, + {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, +] + +[[package]] +name = "websocket-client" +version = "1.7.0" +description = "WebSocket client for Python with low level API options" +optional = false +python-versions = ">=3.8" +files = [ + {file = "websocket-client-1.7.0.tar.gz", hash = "sha256:10e511ea3a8c744631d3bd77e61eb17ed09304c413ad42cf6ddfa4c7787e8fe6"}, + {file = "websocket_client-1.7.0-py3-none-any.whl", hash = "sha256:f4c3d22fec12a2461427a29957ff07d35098ee2d976d3ba244e688b8b4057588"}, +] + +[package.extras] +docs = ["Sphinx (>=6.0)", "sphinx-rtd-theme (>=1.1.0)"] +optional = ["python-socks", "wsaccel"] +test = ["websockets"] + +[[package]] +name = "websockets" +version = "12.0" +description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "websockets-12.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d554236b2a2006e0ce16315c16eaa0d628dab009c33b63ea03f41c6107958374"}, + {file = "websockets-12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2d225bb6886591b1746b17c0573e29804619c8f755b5598d875bb4235ea639be"}, + {file = "websockets-12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eb809e816916a3b210bed3c82fb88eaf16e8afcf9c115ebb2bacede1797d2547"}, + {file = "websockets-12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c588f6abc13f78a67044c6b1273a99e1cf31038ad51815b3b016ce699f0d75c2"}, + {file = "websockets-12.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5aa9348186d79a5f232115ed3fa9020eab66d6c3437d72f9d2c8ac0c6858c558"}, + {file = "websockets-12.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6350b14a40c95ddd53e775dbdbbbc59b124a5c8ecd6fbb09c2e52029f7a9f480"}, + {file = "websockets-12.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:70ec754cc2a769bcd218ed8d7209055667b30860ffecb8633a834dde27d6307c"}, + {file = "websockets-12.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6e96f5ed1b83a8ddb07909b45bd94833b0710f738115751cdaa9da1fb0cb66e8"}, + {file = "websockets-12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4d87be612cbef86f994178d5186add3d94e9f31cc3cb499a0482b866ec477603"}, + {file = "websockets-12.0-cp310-cp310-win32.whl", hash = "sha256:befe90632d66caaf72e8b2ed4d7f02b348913813c8b0a32fae1cc5fe3730902f"}, + {file = "websockets-12.0-cp310-cp310-win_amd64.whl", hash = "sha256:363f57ca8bc8576195d0540c648aa58ac18cf85b76ad5202b9f976918f4219cf"}, + {file = "websockets-12.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5d873c7de42dea355d73f170be0f23788cf3fa9f7bed718fd2830eefedce01b4"}, + {file = "websockets-12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3f61726cae9f65b872502ff3c1496abc93ffbe31b278455c418492016e2afc8f"}, + {file = "websockets-12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed2fcf7a07334c77fc8a230755c2209223a7cc44fc27597729b8ef5425aa61a3"}, + {file = "websockets-12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e332c210b14b57904869ca9f9bf4ca32f5427a03eeb625da9b616c85a3a506c"}, + {file = "websockets-12.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5693ef74233122f8ebab026817b1b37fe25c411ecfca084b29bc7d6efc548f45"}, + {file = "websockets-12.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e9e7db18b4539a29cc5ad8c8b252738a30e2b13f033c2d6e9d0549b45841c04"}, + {file = "websockets-12.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6e2df67b8014767d0f785baa98393725739287684b9f8d8a1001eb2839031447"}, + {file = "websockets-12.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bea88d71630c5900690fcb03161ab18f8f244805c59e2e0dc4ffadae0a7ee0ca"}, + {file = "websockets-12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dff6cdf35e31d1315790149fee351f9e52978130cef6c87c4b6c9b3baf78bc53"}, + {file = "websockets-12.0-cp311-cp311-win32.whl", hash = "sha256:3e3aa8c468af01d70332a382350ee95f6986db479ce7af14d5e81ec52aa2b402"}, + {file = "websockets-12.0-cp311-cp311-win_amd64.whl", hash = "sha256:25eb766c8ad27da0f79420b2af4b85d29914ba0edf69f547cc4f06ca6f1d403b"}, + {file = "websockets-12.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0e6e2711d5a8e6e482cacb927a49a3d432345dfe7dea8ace7b5790df5932e4df"}, + {file = "websockets-12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:dbcf72a37f0b3316e993e13ecf32f10c0e1259c28ffd0a85cee26e8549595fbc"}, + {file = "websockets-12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12743ab88ab2af1d17dd4acb4645677cb7063ef4db93abffbf164218a5d54c6b"}, + {file = "websockets-12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b645f491f3c48d3f8a00d1fce07445fab7347fec54a3e65f0725d730d5b99cb"}, + {file = "websockets-12.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9893d1aa45a7f8b3bc4510f6ccf8db8c3b62120917af15e3de247f0780294b92"}, + {file = "websockets-12.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f38a7b376117ef7aff996e737583172bdf535932c9ca021746573bce40165ed"}, + {file = "websockets-12.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f764ba54e33daf20e167915edc443b6f88956f37fb606449b4a5b10ba42235a5"}, + {file = "websockets-12.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1e4b3f8ea6a9cfa8be8484c9221ec0257508e3a1ec43c36acdefb2a9c3b00aa2"}, + {file = "websockets-12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9fdf06fd06c32205a07e47328ab49c40fc1407cdec801d698a7c41167ea45113"}, + {file = "websockets-12.0-cp312-cp312-win32.whl", hash = "sha256:baa386875b70cbd81798fa9f71be689c1bf484f65fd6fb08d051a0ee4e79924d"}, + {file = "websockets-12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ae0a5da8f35a5be197f328d4727dbcfafa53d1824fac3d96cdd3a642fe09394f"}, + {file = "websockets-12.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5f6ffe2c6598f7f7207eef9a1228b6f5c818f9f4d53ee920aacd35cec8110438"}, + {file = "websockets-12.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9edf3fc590cc2ec20dc9d7a45108b5bbaf21c0d89f9fd3fd1685e223771dc0b2"}, + {file = "websockets-12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8572132c7be52632201a35f5e08348137f658e5ffd21f51f94572ca6c05ea81d"}, + {file = "websockets-12.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:604428d1b87edbf02b233e2c207d7d528460fa978f9e391bd8aaf9c8311de137"}, + {file = "websockets-12.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a9d160fd080c6285e202327aba140fc9a0d910b09e423afff4ae5cbbf1c7205"}, + {file = "websockets-12.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87b4aafed34653e465eb77b7c93ef058516cb5acf3eb21e42f33928616172def"}, + {file = "websockets-12.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b2ee7288b85959797970114deae81ab41b731f19ebcd3bd499ae9ca0e3f1d2c8"}, + {file = "websockets-12.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7fa3d25e81bfe6a89718e9791128398a50dec6d57faf23770787ff441d851967"}, + {file = "websockets-12.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a571f035a47212288e3b3519944f6bf4ac7bc7553243e41eac50dd48552b6df7"}, + {file = "websockets-12.0-cp38-cp38-win32.whl", hash = "sha256:3c6cc1360c10c17463aadd29dd3af332d4a1adaa8796f6b0e9f9df1fdb0bad62"}, + {file = "websockets-12.0-cp38-cp38-win_amd64.whl", hash = "sha256:1bf386089178ea69d720f8db6199a0504a406209a0fc23e603b27b300fdd6892"}, + {file = "websockets-12.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ab3d732ad50a4fbd04a4490ef08acd0517b6ae6b77eb967251f4c263011a990d"}, + {file = "websockets-12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1d9697f3337a89691e3bd8dc56dea45a6f6d975f92e7d5f773bc715c15dde28"}, + {file = "websockets-12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1df2fbd2c8a98d38a66f5238484405b8d1d16f929bb7a33ed73e4801222a6f53"}, + {file = "websockets-12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23509452b3bc38e3a057382c2e941d5ac2e01e251acce7adc74011d7d8de434c"}, + {file = "websockets-12.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e5fc14ec6ea568200ea4ef46545073da81900a2b67b3e666f04adf53ad452ec"}, + {file = "websockets-12.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46e71dbbd12850224243f5d2aeec90f0aaa0f2dde5aeeb8fc8df21e04d99eff9"}, + {file = "websockets-12.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b81f90dcc6c85a9b7f29873beb56c94c85d6f0dac2ea8b60d995bd18bf3e2aae"}, + {file = "websockets-12.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a02413bc474feda2849c59ed2dfb2cddb4cd3d2f03a2fedec51d6e959d9b608b"}, + {file = "websockets-12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bbe6013f9f791944ed31ca08b077e26249309639313fff132bfbf3ba105673b9"}, + {file = "websockets-12.0-cp39-cp39-win32.whl", hash = "sha256:cbe83a6bbdf207ff0541de01e11904827540aa069293696dd528a6640bd6a5f6"}, + {file = "websockets-12.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc4e7fa5414512b481a2483775a8e8be7803a35b30ca805afa4998a84f9fd9e8"}, + {file = "websockets-12.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:248d8e2446e13c1d4326e0a6a4e9629cb13a11195051a73acf414812700badbd"}, + {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44069528d45a933997a6fef143030d8ca8042f0dfaad753e2906398290e2870"}, + {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c4e37d36f0d19f0a4413d3e18c0d03d0c268ada2061868c1e6f5ab1a6d575077"}, + {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d829f975fc2e527a3ef2f9c8f25e553eb7bc779c6665e8e1d52aa22800bb38b"}, + {file = "websockets-12.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2c71bd45a777433dd9113847af751aae36e448bc6b8c361a566cb043eda6ec30"}, + {file = "websockets-12.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0bee75f400895aef54157b36ed6d3b308fcab62e5260703add87f44cee9c82a6"}, + {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:423fc1ed29f7512fceb727e2d2aecb952c46aa34895e9ed96071821309951123"}, + {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27a5e9964ef509016759f2ef3f2c1e13f403725a5e6a1775555994966a66e931"}, + {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3181df4583c4d3994d31fb235dc681d2aaad744fbdbf94c4802485ececdecf2"}, + {file = "websockets-12.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:b067cb952ce8bf40115f6c19f478dc71c5e719b7fbaa511359795dfd9d1a6468"}, + {file = "websockets-12.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:00700340c6c7ab788f176d118775202aadea7602c5cc6be6ae127761c16d6b0b"}, + {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e469d01137942849cff40517c97a30a93ae79917752b34029f0ec72df6b46399"}, + {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffefa1374cd508d633646d51a8e9277763a9b78ae71324183693959cf94635a7"}, + {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba0cab91b3956dfa9f512147860783a1829a8d905ee218a9837c18f683239611"}, + {file = "websockets-12.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2cb388a5bfb56df4d9a406783b7f9dbefb888c09b71629351cc6b036e9259370"}, + {file = "websockets-12.0-py3-none-any.whl", hash = "sha256:dc284bbc8d7c78a6c69e0c7325ab46ee5e40bb4d50e494d8131a07ef47500e9e"}, + {file = "websockets-12.0.tar.gz", hash = "sha256:81df9cbcbb6c260de1e007e58c011bfebe2dafc8435107b0537f393dd38c8b1b"}, +] + +[[package]] +name = "werkzeug" +version = "3.0.2" +description = "The comprehensive WSGI web application library." +optional = false +python-versions = ">=3.8" +files = [ + {file = "werkzeug-3.0.2-py3-none-any.whl", hash = "sha256:3aac3f5da756f93030740bc235d3e09449efcf65f2f55e3602e1d851b8f48795"}, + {file = "werkzeug-3.0.2.tar.gz", hash = "sha256:e39b645a6ac92822588e7b39a692e7828724ceae0b0d702ef96701f90e70128d"}, +] + +[package.dependencies] +MarkupSafe = ">=2.1.1" + +[package.extras] +watchdog = ["watchdog (>=2.3)"] + +[[package]] +name = "win32-setctime" +version = "1.1.0" +description = "A small Python utility to set file creation time on Windows" +optional = false +python-versions = ">=3.5" +files = [ + {file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"}, + {file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"}, +] + +[package.extras] +dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"] + +[[package]] +name = "wrapt" +version = "1.16.0" +description = "Module for decorators, wrappers and monkey patching." +optional = false +python-versions = ">=3.6" +files = [ + {file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"}, + {file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136"}, + {file = "wrapt-1.16.0-cp310-cp310-win32.whl", hash = "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d"}, + {file = "wrapt-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d"}, + {file = "wrapt-1.16.0-cp311-cp311-win32.whl", hash = "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362"}, + {file = "wrapt-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c"}, + {file = "wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc"}, + {file = "wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8"}, + {file = "wrapt-1.16.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465"}, + {file = "wrapt-1.16.0-cp36-cp36m-win32.whl", hash = "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e"}, + {file = "wrapt-1.16.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966"}, + {file = "wrapt-1.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win32.whl", hash = "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win_amd64.whl", hash = "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6"}, + {file = "wrapt-1.16.0-cp38-cp38-win32.whl", hash = "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b"}, + {file = "wrapt-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537"}, + {file = "wrapt-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3"}, + {file = "wrapt-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35"}, + {file = "wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1"}, + {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"}, +] + +[[package]] +name = "wsproto" +version = "1.2.0" +description = "WebSockets state-machine based protocol implementation" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736"}, + {file = "wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065"}, +] + +[package.dependencies] +h11 = ">=0.9.0,<1" + +[[package]] +name = "yarl" +version = "1.9.4" +description = "Yet another URL library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e"}, + {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2"}, + {file = "yarl-1.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541"}, + {file = "yarl-1.9.4-cp310-cp310-win32.whl", hash = "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d"}, + {file = "yarl-1.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98"}, + {file = "yarl-1.9.4-cp311-cp311-win32.whl", hash = "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31"}, + {file = "yarl-1.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10"}, + {file = "yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7"}, + {file = "yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984"}, + {file = "yarl-1.9.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434"}, + {file = "yarl-1.9.4-cp37-cp37m-win32.whl", hash = "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749"}, + {file = "yarl-1.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3"}, + {file = "yarl-1.9.4-cp38-cp38-win32.whl", hash = "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece"}, + {file = "yarl-1.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0"}, + {file = "yarl-1.9.4-cp39-cp39-win32.whl", hash = "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575"}, + {file = "yarl-1.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15"}, + {file = "yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad"}, + {file = "yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf"}, +] + +[package.dependencies] +idna = ">=2.0" +multidict = ">=4.0" + +[[package]] +name = "zipp" +version = "3.18.1" +description = "Backport of pathlib-compatible object wrapper for zip files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "zipp-3.18.1-py3-none-any.whl", hash = "sha256:206f5a15f2af3dbaee80769fb7dc6f249695e940acca08dfb2a4769fe61e538b"}, + {file = "zipp-3.18.1.tar.gz", hash = "sha256:2884ed22e7d8961de1c9a05142eb69a247f120291bc0206a00a7642f09b5b715"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] + +[[package]] +name = "zope-event" +version = "5.0" +description = "Very basic event publishing system" +optional = false +python-versions = ">=3.7" +files = [ + {file = "zope.event-5.0-py3-none-any.whl", hash = "sha256:2832e95014f4db26c47a13fdaef84cef2f4df37e66b59d8f1f4a8f319a632c26"}, + {file = "zope.event-5.0.tar.gz", hash = "sha256:bac440d8d9891b4068e2b5a2c5e2c9765a9df762944bda6955f96bb9b91e67cd"}, +] + +[package.dependencies] +setuptools = "*" + +[package.extras] +docs = ["Sphinx"] +test = ["zope.testrunner"] + +[[package]] +name = "zope-interface" +version = "6.2" +description = "Interfaces for Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "zope.interface-6.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:506f5410b36e5ba494136d9fa04c548eaf1a0d9c442b0b0e7a0944db7620e0ab"}, + {file = "zope.interface-6.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b386b8b9d2b6a5e1e4eadd4e62335571244cb9193b7328c2b6e38b64cfda4f0e"}, + {file = "zope.interface-6.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abb0b3f2cb606981c7432f690db23506b1db5899620ad274e29dbbbdd740e797"}, + {file = "zope.interface-6.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de7916380abaef4bb4891740879b1afcba2045aee51799dfd6d6ca9bdc71f35f"}, + {file = "zope.interface-6.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b240883fb43160574f8f738e6d09ddbdbf8fa3e8cea051603d9edfd947d9328"}, + {file = "zope.interface-6.2-cp310-cp310-win_amd64.whl", hash = "sha256:8af82afc5998e1f307d5e72712526dba07403c73a9e287d906a8aa2b1f2e33dd"}, + {file = "zope.interface-6.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4d45d2ba8195850e3e829f1f0016066a122bfa362cc9dc212527fc3d51369037"}, + {file = "zope.interface-6.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:76e0531d86523be7a46e15d379b0e975a9db84316617c0efe4af8338dc45b80c"}, + {file = "zope.interface-6.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59f7374769b326a217d0b2366f1c176a45a4ff21e8f7cebb3b4a3537077eff85"}, + {file = "zope.interface-6.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:25e0af9663eeac6b61b231b43c52293c2cb7f0c232d914bdcbfd3e3bd5c182ad"}, + {file = "zope.interface-6.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14e02a6fc1772b458ebb6be1c276528b362041217b9ca37e52ecea2cbdce9fac"}, + {file = "zope.interface-6.2-cp311-cp311-win_amd64.whl", hash = "sha256:02adbab560683c4eca3789cc0ac487dcc5f5a81cc48695ec247f00803cafe2fe"}, + {file = "zope.interface-6.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8f5d2c39f3283e461de3655e03faf10e4742bb87387113f787a7724f32db1e48"}, + {file = "zope.interface-6.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:75d2ec3d9b401df759b87bc9e19d1b24db73083147089b43ae748aefa63067ef"}, + {file = "zope.interface-6.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa994e8937e8ccc7e87395b7b35092818905cf27c651e3ff3e7f29729f5ce3ce"}, + {file = "zope.interface-6.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ede888382882f07b9e4cd942255921ffd9f2901684198b88e247c7eabd27a000"}, + {file = "zope.interface-6.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2606955a06c6852a6cff4abeca38346ed01e83f11e960caa9a821b3626a4467b"}, + {file = "zope.interface-6.2-cp312-cp312-win_amd64.whl", hash = "sha256:ac7c2046d907e3b4e2605a130d162b1b783c170292a11216479bb1deb7cadebe"}, + {file = "zope.interface-6.2-cp37-cp37m-macosx_11_0_x86_64.whl", hash = "sha256:febceb04ee7dd2aef08c2ff3d6f8a07de3052fc90137c507b0ede3ea80c21440"}, + {file = "zope.interface-6.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fc711acc4a1c702ca931fdbf7bf7c86f2a27d564c85c4964772dadf0e3c52f5"}, + {file = "zope.interface-6.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:396f5c94654301819a7f3a702c5830f0ea7468d7b154d124ceac823e2419d000"}, + {file = "zope.interface-6.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4dd374927c00764fcd6fe1046bea243ebdf403fba97a937493ae4be2c8912c2b"}, + {file = "zope.interface-6.2-cp37-cp37m-win_amd64.whl", hash = "sha256:a3046e8ab29b590d723821d0785598e0b2e32b636a0272a38409be43e3ae0550"}, + {file = "zope.interface-6.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:de125151a53ecdb39df3cb3deb9951ed834dd6a110a9e795d985b10bb6db4532"}, + {file = "zope.interface-6.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f444de0565db46d26c9fa931ca14f497900a295bd5eba480fc3fad25af8c763e"}, + {file = "zope.interface-6.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2fefad268ff5c5b314794e27e359e48aeb9c8bb2cbb5748a071757a56f6bb8f"}, + {file = "zope.interface-6.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:97785604824981ec8c81850dd25c8071d5ce04717a34296eeac771231fbdd5cd"}, + {file = "zope.interface-6.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7b2bed4eea047a949296e618552d3fed00632dc1b795ee430289bdd0e3717f3"}, + {file = "zope.interface-6.2-cp38-cp38-win_amd64.whl", hash = "sha256:d54f66c511ea01b9ef1d1a57420a93fbb9d48a08ec239f7d9c581092033156d0"}, + {file = "zope.interface-6.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5ee9789a20b0081dc469f65ff6c5007e67a940d5541419ca03ef20c6213dd099"}, + {file = "zope.interface-6.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:af27b3fe5b6bf9cd01b8e1c5ddea0a0d0a1b8c37dc1c7452f1e90bf817539c6d"}, + {file = "zope.interface-6.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bce517b85f5debe07b186fc7102b332676760f2e0c92b7185dd49c138734b70"}, + {file = "zope.interface-6.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4ae9793f114cee5c464cc0b821ae4d36e1eba961542c6086f391a61aee167b6f"}, + {file = "zope.interface-6.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e87698e2fea5ca2f0a99dff0a64ce8110ea857b640de536c76d92aaa2a91ff3a"}, + {file = "zope.interface-6.2-cp39-cp39-win_amd64.whl", hash = "sha256:b66335bbdbb4c004c25ae01cc4a54fd199afbc1fd164233813c6d3c2293bb7e1"}, + {file = "zope.interface-6.2.tar.gz", hash = "sha256:3b6c62813c63c543a06394a636978b22dffa8c5410affc9331ce6cdb5bfa8565"}, +] + +[package.dependencies] +setuptools = "*" + +[package.extras] +docs = ["Sphinx", "repoze.sphinx.autointerface", "sphinx_rtd_theme"] +test = ["coverage (>=5.0.3)", "zope.event", "zope.testing"] +testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"] + +[extras] +all = [] +deploy = [] +local = [] + +[metadata] +lock-version = "2.0" +python-versions = ">=3.10,<3.12" +content-hash = "27adc9d6515d9e92ee01a6aae0c9a8162aa403456134ab25a8dd98909ecbe5f2" diff --git a/src/backend/base/pyproject.toml b/src/backend/base/pyproject.toml new file mode 100644 index 000000000..9b164e369 --- /dev/null +++ b/src/backend/base/pyproject.toml @@ -0,0 +1,120 @@ +[tool.poetry] +name = "langflow-base" +version = "0.0.18" +description = "A Python package with a built-in web application" +authors = ["Logspace "] +maintainers = [ + "Carlos Coelho ", + "Cristhian Zanforlin ", + "Gabriel Almeida ", + "Gustavo Schaedler ", + "Igor Carvalho ", + "Lucas Eduoli ", + "Otávio Anovazzi ", + "Rodrigo Nader ", +] +repository = "https://github.com/logspace-ai/langflow" +license = "MIT" +readme = "README.md" +keywords = ["nlp", "langchain", "openai", "gpt", "gui"] +packages = [{ include = "langflow" }, { include = "langflow/py.typed" }] +include = ["pyproject.toml", "README.md", "langflow/**/*"] +documentation = "https://docs.langflow.org" + + +[tool.poetry.scripts] +langflow-base = "langflow.__main__:main" + +[tool.poetry.dependencies] +python = ">=3.10,<3.12" +fastapi = "^0.109.0" +httpx = "*" +uvicorn = "^0.27.0" +gunicorn = "^21.2.0" +langchain = "~0.1.0" +sqlmodel = "^0.0.14" +loguru = "^0.7.1" +rich = "^13.7.0" +langchain-experimental = "*" +pydantic = "^2.5.0" +pydantic-settings = "^2.1.0" +websockets = "*" +typer = "^0.9.0" +cachetools = "^5.3.1" +platformdirs = "^4.2.0" +python-multipart = "^0.0.7" +orjson = "3.9.15" +alembic = "^1.13.0" +passlib = "^1.7.4" +bcrypt = "4.0.1" +pillow = "^10.2.0" +docstring-parser = "^0.15" +python-jose = "^3.3.0" +pandas = "2.2.0" +multiprocess = "^0.70.14" +duckdb = "^0.9.2" +python-socketio = "^5.11.0" +python-docx = "^1.1.0" +jq = { version = "^1.7.0", markers = "sys_platform != 'win32'" } +pypdf = "^4.1.0" +chromadb = "^0.4.24" +langchain-anthropic = "^0.1.4" +langchain-astradb = "^0.1.0" +nest-asyncio = "^1.6.0" +emoji = "^2.11.0" +cryptography = "^42.0.5" +langchain-openai = "^0.1.1" + + +[tool.poetry.group.dev.dependencies] +pytest-asyncio = "^0.21.1" +types-redis = "^4.6.0.5" +ipykernel = "^6.26.0" +mypy = "^1.7.1" +ruff = "^0.1.5" +httpx = "*" +pytest = "^7.4.2" +types-requests = "^2.31.0" +requests = "^2.31.0" +pytest-cov = "^4.1.0" +pandas-stubs = "^2.0.0.230412" +types-pillow = "^9.5.0.2" +types-pyyaml = "^6.0.12.8" +types-python-jose = "^3.3.4.8" +types-passlib = "^1.7.7.13" +locust = "^2.16.1" +pytest-mock = "^3.11.1" +pytest-xdist = "^3.3.1" +types-pywin32 = "^306.0.0.4" +types-google-cloud-ndb = "^2.2.0.0" +pytest-sugar = "^0.9.7" + + +[tool.poetry.extras] +deploy = ["celery", "redis", "flower"] +local = ["llama-cpp-python", "sentence-transformers", "ctransformers"] +all = ["deploy", "local"] + + +[tool.pytest.ini_options] +minversion = "6.0" +addopts = "-ra" +testpaths = ["tests", "integration"] +console_output_style = "progress" +filterwarnings = ["ignore::DeprecationWarning"] +log_cli = true +markers = ["async_test"] + +[tool.mypy] +namespace_packages = true +mypy_path = "langflow" +ignore_missing_imports = true + + +[tool.ruff] +exclude = ["src/backend/langflow/alembic/*"] +line-length = 120 + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/src/backend/langflow/__init__.py b/src/backend/langflow/__init__.py deleted file mode 100644 index 2b6dd4fb8..000000000 --- a/src/backend/langflow/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -from importlib import metadata - -from langflow.interface.custom.custom_component import CustomComponent - -# Deactivate cache manager for now -# from langflow.services.cache import cache_service -from langflow.processing.load import load_flow_from_json - -try: - __version__ = metadata.version(__package__) -except metadata.PackageNotFoundError: - # Case where package metadata is not available. - __version__ = "" -del metadata # optional, avoids polluting the results of dir(__package__) - -__all__ = ["load_flow_from_json", "CustomComponent"] diff --git a/src/backend/langflow/api/v1/base.py b/src/backend/langflow/api/v1/base.py deleted file mode 100644 index 01e4e9c79..000000000 --- a/src/backend/langflow/api/v1/base.py +++ /dev/null @@ -1,160 +0,0 @@ -from typing import Optional - -from langchain.prompts import PromptTemplate -from pydantic import BaseModel, field_validator, model_serializer - -from langflow.interface.utils import extract_input_variables_from_prompt -from langflow.template.frontend_node.base import FrontendNode - - -class CacheResponse(BaseModel): - data: dict - - -class Code(BaseModel): - code: str - - -class FrontendNodeRequest(FrontendNode): - template: dict # type: ignore - - @model_serializer(mode="wrap") - def serialize_model(self, handler): - # Override the default serialization method in FrontendNode - # because we don't need the name in the response (i.e. {name: {}}) - return handler(self) - - -class ValidatePromptRequest(BaseModel): - name: str - template: str - # optional for tweak call - frontend_node: Optional[FrontendNodeRequest] = None - - -# Build ValidationResponse class for {"imports": {"errors": []}, "function": {"errors": []}} -class CodeValidationResponse(BaseModel): - imports: dict - function: dict - - @field_validator("imports") - @classmethod - def validate_imports(cls, v): - return v or {"errors": []} - - @field_validator("function") - @classmethod - def validate_function(cls, v): - return v or {"errors": []} - - -class PromptValidationResponse(BaseModel): - input_variables: list - # object return for tweak call - frontend_node: Optional[FrontendNodeRequest] = None - - -INVALID_CHARACTERS = { - " ", - ",", - ".", - ":", - ";", - "!", - "?", - "/", - "\\", - "(", - ")", - "[", - "]", - "{", - "}", -} - -INVALID_NAMES = { - "input_variables", - "output_parser", - "partial_variables", - "template", - "template_format", - "validate_template", -} - - -def validate_prompt(template: str): - input_variables = extract_input_variables_from_prompt(template) - - # Check if there are invalid characters in the input_variables - input_variables = check_input_variables(input_variables) - if any(var in INVALID_NAMES for var in input_variables): - raise ValueError(f"Invalid input variables. None of the variables can be named {', '.join(input_variables)}. ") - - try: - PromptTemplate(template=template, input_variables=input_variables) - except Exception as exc: - raise ValueError(str(exc)) from exc - - return input_variables - - -def check_input_variables(input_variables: list): - invalid_chars = [] - fixed_variables = [] - wrong_variables = [] - empty_variables = [] - for variable in input_variables: - new_var = variable - - # if variable is empty, then we should add that to the wrong variables - if not variable: - empty_variables.append(variable) - continue - - # if variable starts with a number we should add that to the invalid chars - # and wrong variables - if variable[0].isdigit(): - invalid_chars.append(variable[0]) - new_var = new_var.replace(variable[0], "") - wrong_variables.append(variable) - else: - for char in INVALID_CHARACTERS: - if char in variable: - invalid_chars.append(char) - new_var = new_var.replace(char, "") - wrong_variables.append(variable) - fixed_variables.append(new_var) - # If any of the input_variables is not in the fixed_variables, then it means that - # there are invalid characters in the input_variables - - if any(var not in fixed_variables for var in input_variables): - error_message = build_error_message( - input_variables, - invalid_chars, - wrong_variables, - fixed_variables, - empty_variables, - ) - raise ValueError(error_message) - return input_variables - - -def build_error_message(input_variables, invalid_chars, wrong_variables, fixed_variables, empty_variables): - input_variables_str = ", ".join([f"'{var}'" for var in input_variables]) - error_string = f"Invalid input variables: {input_variables_str}. " - - if wrong_variables and invalid_chars: - # fix the wrong variables replacing invalid chars and find them in the fixed variables - error_string_vars = "You can fix them by replacing the invalid characters: " - wvars = wrong_variables.copy() - for i, wrong_var in enumerate(wvars): - for char in invalid_chars: - wrong_var = wrong_var.replace(char, "") - if wrong_var in fixed_variables: - error_string_vars += f"'{wrong_variables[i]}' -> '{wrong_var}'" - error_string += error_string_vars - elif empty_variables: - error_string += f" There are {len(empty_variables)} empty variable{'s' if len(empty_variables) > 1 else ''}." - elif len(set(fixed_variables)) != len(fixed_variables): - error_string += "There are duplicate variables." - return error_string diff --git a/src/backend/langflow/api/v1/chat.py b/src/backend/langflow/api/v1/chat.py deleted file mode 100644 index b909a0209..000000000 --- a/src/backend/langflow/api/v1/chat.py +++ /dev/null @@ -1,245 +0,0 @@ -import time - -from fastapi import ( - APIRouter, - Depends, - HTTPException, - WebSocket, - WebSocketException, - status, -) -from fastapi.responses import StreamingResponse -from loguru import logger -from sqlmodel import Session - -from langflow.api.utils import build_input_keys_response, format_elapsed_time -from langflow.api.v1.schemas import BuildStatus, BuiltResponse, InitResponse, StreamData -from langflow.graph.graph.base import Graph -from langflow.services.auth.utils import ( - get_current_active_user, - get_current_user_for_websocket, -) -from langflow.services.cache.service import BaseCacheService -from langflow.services.cache.utils import update_build_status -from langflow.services.chat.service import ChatService -from langflow.services.deps import get_cache_service, get_chat_service, get_session - -router = APIRouter(tags=["Chat"]) - - -@router.websocket("/chat/{client_id}") -async def chat( - client_id: str, - websocket: WebSocket, - db: Session = Depends(get_session), - chat_service: "ChatService" = Depends(get_chat_service), -): - """Websocket endpoint for chat.""" - try: - user = await get_current_user_for_websocket(websocket, db) - await websocket.accept() - if not user: - await websocket.close(code=status.WS_1008_POLICY_VIOLATION, reason="Unauthorized") - elif not user.is_active: - await websocket.close(code=status.WS_1008_POLICY_VIOLATION, reason="Unauthorized") - - if client_id in chat_service.cache_service: - await chat_service.handle_websocket(client_id, websocket) - else: - # We accept the connection but close it immediately - # if the flow is not built yet - message = "Please, build the flow before sending messages" - await websocket.close(code=status.WS_1011_INTERNAL_ERROR, reason=message) - except WebSocketException as exc: - logger.error(f"Websocket exrror: {exc}") - await websocket.close(code=status.WS_1011_INTERNAL_ERROR, reason=str(exc)) - except Exception as exc: - logger.error(f"Error in chat websocket: {exc}") - messsage = exc.detail if isinstance(exc, HTTPException) else str(exc) - if "Could not validate credentials" in str(exc): - await websocket.close(code=status.WS_1008_POLICY_VIOLATION, reason="Unauthorized") - else: - await websocket.close(code=status.WS_1011_INTERNAL_ERROR, reason=messsage) - - -@router.post("/build/init/{flow_id}", response_model=InitResponse, status_code=201) -async def init_build( - graph_data: dict, - flow_id: str, - current_user=Depends(get_current_active_user), - chat_service: "ChatService" = Depends(get_chat_service), - cache_service: "BaseCacheService" = Depends(get_cache_service), -): - """Initialize the build by storing graph data and returning a unique session ID.""" - try: - if flow_id is None: - raise ValueError("No ID provided") - # Check if already building - if ( - flow_id in cache_service - and isinstance(cache_service[flow_id], dict) - and cache_service[flow_id].get("status") == BuildStatus.IN_PROGRESS - ): - return InitResponse(flowId=flow_id) - - # Delete from cache if already exists - if flow_id in chat_service.cache_service: - chat_service.cache_service.delete(flow_id) - logger.debug(f"Deleted flow {flow_id} from cache") - cache_service[flow_id] = { - "graph_data": graph_data, - "status": BuildStatus.STARTED, - "user_id": current_user.id, - } - - return InitResponse(flowId=flow_id) - except Exception as exc: - logger.error(f"Error initializing build: {exc}") - return HTTPException(status_code=500, detail=str(exc)) - - -@router.get("/build/{flow_id}/status", response_model=BuiltResponse) -async def build_status(flow_id: str, cache_service: "BaseCacheService" = Depends(get_cache_service)): - """Check the flow_id is in the cache_service.""" - try: - built = flow_id in cache_service and cache_service[flow_id]["status"] == BuildStatus.SUCCESS - - return BuiltResponse( - built=built, - ) - - except Exception as exc: - logger.error(f"Error checking build status: {exc}") - return HTTPException(status_code=500, detail=str(exc)) - - -@router.get("/build/stream/{flow_id}", response_class=StreamingResponse) -async def stream_build( - flow_id: str, - chat_service: "ChatService" = Depends(get_chat_service), - cache_service: "BaseCacheService" = Depends(get_cache_service), -): - """Stream the build process based on stored flow data.""" - - async def event_stream(flow_id): - final_response = {"end_of_stream": True} - artifacts = {} - flow_cache = cache_service[flow_id] - flow_cache = flow_cache if isinstance(flow_cache, dict) else {} - try: - if flow_id not in cache_service: - error_message = "Invalid session ID" - yield str(StreamData(event="error", data={"error": error_message})) - return - - if flow_cache.get("status") == BuildStatus.IN_PROGRESS: - error_message = "Already building" - yield str(StreamData(event="error", data={"error": error_message})) - return - - graph_data = flow_cache.get("graph_data") - - if not graph_data: - error_message = "No data provided" - yield str(StreamData(event="error", data={"error": error_message})) - return - - logger.debug("Building langchain object") - - # Some error could happen when building the graph - graph = Graph.from_payload(graph_data) - - number_of_nodes = len(graph.vertices) - update_build_status(cache_service, flow_id, BuildStatus.IN_PROGRESS) - time_elapsed = "" - try: - user_id = flow_cache["user_id"] - except KeyError: - logger.debug("No user_id found in cache_service") - user_id = None - for i, vertex in enumerate(graph.generator_build(), 1): - start_time = time.perf_counter() - try: - log_dict = { - "log": f"Building node {vertex.vertex_type}", - } - yield str(StreamData(event="log", data=log_dict)) - if vertex.is_task: - vertex = await try_running_celery_task(vertex, user_id) - else: - await vertex.build(user_id=user_id) - time_elapsed = format_elapsed_time(time.perf_counter() - start_time) - params = vertex._built_object_repr() - valid = True - - logger.debug(f"Building node {str(vertex.vertex_type)}") - logger.debug(f"Output: {params[:100]}{'...' if len(params) > 100 else ''}") - if vertex.artifacts: - # The artifacts will be prompt variables - # passed to build_input_keys_response - # to set the input_keys values - artifacts.update(vertex.artifacts) - except Exception as exc: - logger.exception(exc) - params = str(exc) - valid = False - time_elapsed = format_elapsed_time(time.perf_counter() - start_time) - update_build_status(cache_service, flow_id, BuildStatus.FAILURE) - - vertex_id = vertex.parent_node_id if vertex.parent_is_top_level else vertex.id - if vertex_id in graph.top_level_vertices: - response = { - "valid": valid, - "params": params, - "id": vertex_id, - "progress": round(i / number_of_nodes, 2), - "duration": time_elapsed, - } - - yield str(StreamData(event="message", data=response)) - - langchain_object = await graph.build() - # Now we need to check the input_keys to send them to the client - if hasattr(langchain_object, "input_keys"): - input_keys_response = build_input_keys_response(langchain_object, artifacts) - else: - input_keys_response = { - "input_keys": None, - "memory_keys": [], - "handle_keys": [], - } - yield str(StreamData(event="message", data=input_keys_response)) - chat_service.set_cache(flow_id, langchain_object) - # We need to reset the chat history - chat_service.chat_history.empty_history(flow_id) - update_build_status(cache_service, flow_id, BuildStatus.SUCCESS) - except Exception as exc: - logger.exception(exc) - logger.error("Error while building the flow: %s", exc) - - update_build_status(cache_service, flow_id, BuildStatus.FAILURE) - yield str(StreamData(event="error", data={"error": str(exc)})) - finally: - yield str(StreamData(event="message", data=final_response)) - - try: - return StreamingResponse(event_stream(flow_id), media_type="text/event-stream") - except Exception as exc: - logger.error(f"Error streaming build: {exc}") - raise HTTPException(status_code=500, detail=str(exc)) - - -async def try_running_celery_task(vertex, user_id): - # Try running the task in celery - # and set the task_id to the local vertex - # if it fails, run the task locally - try: - from langflow.worker import build_vertex - - task = build_vertex.delay(vertex) - vertex.task_id = task.id - except Exception as exc: - logger.debug(f"Error running task in celery: {exc}") - vertex.task_id = None - await vertex.build(user_id=user_id) - return vertex diff --git a/src/backend/langflow/api/v1/credential.py b/src/backend/langflow/api/v1/credential.py deleted file mode 100644 index 1026319c4..000000000 --- a/src/backend/langflow/api/v1/credential.py +++ /dev/null @@ -1,86 +0,0 @@ -from datetime import datetime -from uuid import UUID - -from fastapi import APIRouter, Depends, HTTPException -from langflow.services.auth import utils as auth_utils -from langflow.services.auth.utils import get_current_active_user -from langflow.services.database.models.credential import Credential, CredentialCreate, CredentialRead, CredentialUpdate -from langflow.services.database.models.user.model import User -from langflow.services.deps import get_session, get_settings_service -from sqlmodel import Session, select - -router = APIRouter(prefix="/credentials", tags=["Credentials"]) - - -@router.post("/", response_model=CredentialRead, status_code=201) -def create_credential( - *, - session: Session = Depends(get_session), - credential: CredentialCreate, - current_user: User = Depends(get_current_active_user), - settings_service=Depends(get_settings_service), -): - """Create a new credential.""" - try: - # check if credential name already exists - credential_exists = session.exec( - select(Credential).where(Credential.name == credential.name, Credential.user_id == current_user.id) - ).first() - if credential_exists: - raise HTTPException(status_code=400, detail="Credential name already exists") - - db_credential = Credential.model_validate(credential, from_attributes=True) - if not db_credential.value: - raise HTTPException(status_code=400, detail="Credential value cannot be empty") - encrypted = auth_utils.encrypt_api_key(db_credential.value, settings_service=settings_service) - db_credential.value = encrypted - db_credential.user_id = current_user.id - session.add(db_credential) - session.commit() - session.refresh(db_credential) - return db_credential - except Exception as e: - if isinstance(e, HTTPException): - raise e - raise HTTPException(status_code=500, detail=str(e)) from e - - -@router.get("/", response_model=list[CredentialRead], status_code=200) -def read_credentials( - *, - session: Session = Depends(get_session), - current_user: User = Depends(get_current_active_user), -): - """Read all credentials.""" - try: - credentials = session.exec(select(Credential).where(Credential.user_id == current_user.id)).all() - return credentials - except Exception as e: - raise HTTPException(status_code=500, detail=str(e)) from e - - -@router.patch("/{credential_id}", response_model=CredentialRead, status_code=200) -def update_credential( - *, - session: Session = Depends(get_session), - credential_id: UUID, - credential: CredentialUpdate, - current_user: User = Depends(get_current_active_user), -): - """Update a credential.""" - try: - db_credential = session.exec( - select(Credential).where(Credential.id == credential_id, Credential.user_id == current_user.id) - ).first() - if not db_credential: - raise HTTPException(status_code=404, detail="Credential not found") - - credential_data = credential.model_dump(exclude_unset=True) - for key, value in credential_data.items(): - setattr(db_credential, key, value) - db_credential.updated_at = datetime.utcnow() - session.commit() - session.refresh(db_credential) - return db_credential - except Exception as e: - raise HTTPException(status_code=500, detail=str(e)) from e diff --git a/src/backend/langflow/api/v1/endpoints.py b/src/backend/langflow/api/v1/endpoints.py deleted file mode 100644 index c8ef86906..000000000 --- a/src/backend/langflow/api/v1/endpoints.py +++ /dev/null @@ -1,394 +0,0 @@ -from http import HTTPStatus -from typing import Annotated, Any, List, Optional, Union - -import sqlalchemy as sa -from fastapi import APIRouter, Body, Depends, HTTPException, UploadFile, status -from langflow.api.utils import update_frontend_node_with_template_values -from langflow.api.v1.schemas import ( - CustomComponentCode, - PreloadResponse, - ProcessResponse, - TaskResponse, - TaskStatusResponse, - UploadFileResponse, -) -from langflow.interface.custom.custom_component import CustomComponent -from langflow.interface.custom.directory_reader import DirectoryReader -from langflow.interface.custom.utils import build_custom_component_template -from langflow.processing.process import build_graph_and_generate_result, process_graph_cached, process_tweaks -from langflow.services.auth.utils import api_key_security, get_current_active_user -from langflow.services.cache.utils import save_uploaded_file -from langflow.services.database.models.flow import Flow -from langflow.services.database.models.user.model import User -from langflow.services.deps import get_session, get_session_service, get_settings_service, get_task_service -from langflow.services.session.service import SessionService -from loguru import logger -from sqlmodel import select - -try: - from langflow.worker import process_graph_cached_task -except ImportError: - - def process_graph_cached_task(*args, **kwargs): - raise NotImplementedError("Celery is not installed") - - -from langflow.services.task.service import TaskService -from sqlmodel import Session - -# build router -router = APIRouter(tags=["Base"]) - - -async def process_graph_data( - graph_data: dict, - inputs: Optional[Union[List[dict], dict]] = None, - tweaks: Optional[dict] = None, - clear_cache: bool = False, - session_id: Optional[str] = None, - task_service: "TaskService" = Depends(get_task_service), - sync: bool = True, -): - task_result: Any = None - task_status = None - if tweaks: - try: - graph_data = process_tweaks(graph_data, tweaks) - except Exception as exc: - logger.error(f"Error processing tweaks: {exc}") - if sync: - result = await process_graph_cached( - graph_data, - inputs, - clear_cache, - session_id, - ) - task_id = str(id(result)) - if isinstance(result, dict) and "result" in result: - task_result = result["result"] - session_id = result["session_id"] - elif hasattr(result, "result") and hasattr(result, "session_id"): - task_result = result.result - - session_id = result.session_id - else: - task_result = result - else: - logger.warning( - "This is an experimental feature and may not work as expected." - "Please report any issues to our GitHub repository." - ) - if session_id is None: - # Generate a session ID - session_id = get_session_service().generate_key(session_id=session_id, data_graph=graph_data) - task_id, task = await task_service.launch_task( - process_graph_cached_task if task_service.use_celery else process_graph_cached, - graph_data, - inputs, - clear_cache, - session_id, - ) - task_status = task.status - if task.status == "FAILURE": - logger.error(f"Task {task_id} failed: {task.traceback}") - task_result = str(task._exception) - else: - task_result = task.result - - if task_id: - task_response = TaskResponse(id=task_id, href=f"api/v1/task/{task_id}") - else: - task_response = None - - return ProcessResponse( - result=task_result, - status=task_status, - task=task_response, - session_id=session_id, - backend=task_service.backend_name, - ) - - -@router.get("/all", dependencies=[Depends(get_current_active_user)]) -def get_all( - settings_service=Depends(get_settings_service), -): - from langflow.interface.types import get_all_types_dict - - logger.debug("Building langchain types dict") - try: - return get_all_types_dict(settings_service) - except Exception as exc: - raise HTTPException(status_code=500, detail=str(exc)) from exc - - -@router.post("/process/json", response_model=ProcessResponse) -async def process_json( - session: Annotated[Session, Depends(get_session)], - data: dict, - inputs: Optional[dict] = None, - tweaks: Optional[dict] = None, - clear_cache: Annotated[bool, Body(embed=True)] = False, # noqa: F821 - session_id: Annotated[Union[None, str], Body(embed=True)] = None, # noqa: F821 - task_service: "TaskService" = Depends(get_task_service), - sync: Annotated[bool, Body(embed=True)] = True, # noqa: F821 -): - try: - return await process_graph_data( - graph_data=data, - inputs=inputs, - tweaks=tweaks, - clear_cache=clear_cache, - session_id=session_id, - task_service=task_service, - sync=sync, - ) - except Exception as exc: - logger.exception(exc) - raise HTTPException(status_code=500, detail=str(exc)) from exc - - -# Endpoint to preload a graph -@router.post("/process/preload/{flow_id}", response_model=PreloadResponse) -async def preload_flow( - session: Annotated[Session, Depends(get_session)], - flow_id: str, - session_id: Optional[str] = None, - session_service: SessionService = Depends(get_session_service), - api_key_user: User = Depends(api_key_security), - clear_session: Annotated[bool, Body(embed=True)] = False, # noqa: F821 -): - try: - # Get the flow that matches the flow_id and belongs to the user - # flow = session.query(Flow).filter(Flow.id == flow_id).filter(Flow.user_id == api_key_user.id).first() - if clear_session: - session_service.clear_session(session_id) - # Check if the session exists - session_data = await session_service.load_session(session_id) - # Session data is a tuple of (graph, artifacts) - # or (None, None) if the session is empty - if isinstance(session_data, tuple): - graph, artifacts = session_data - is_clear = graph is None and artifacts is None - else: - is_clear = session_data is None - return PreloadResponse(session_id=session_id, is_clear=is_clear) - else: - if session_id is None: - session_id = flow_id - flow = session.exec(select(Flow).where(Flow.id == flow_id).where(Flow.user_id == api_key_user.id)).first() - if flow is None: - raise ValueError(f"Flow {flow_id} not found") - - if flow.data is None: - raise ValueError(f"Flow {flow_id} has no data") - graph_data = flow.data - session_service.clear_session(session_id) - # Load the graph using SessionService - session_data = await session_service.load_session(session_id, graph_data) - graph, artifacts = session_data if session_data else (None, None) - if not graph: - raise ValueError("Graph not found in the session") - _ = await graph.build() - session_service.update_session(session_id, (graph, artifacts)) - return PreloadResponse(session_id=session_id) - except Exception as exc: - logger.exception(exc) - raise HTTPException(status_code=500, detail=str(exc)) from exc - - -@router.post( - "/predict/{flow_id}", - response_model=ProcessResponse, - dependencies=[Depends(api_key_security)], -) -@router.post( - "/process/{flow_id}", - response_model=ProcessResponse, -) -async def process( - session: Annotated[Session, Depends(get_session)], - flow_id: str, - inputs: Optional[Union[List[dict], dict]] = None, - tweaks: Optional[dict] = None, - clear_cache: Annotated[bool, Body(embed=True)] = False, # noqa: F821 - session_id: Annotated[Union[None, str], Body(embed=True)] = None, # noqa: F821 - task_service: "TaskService" = Depends(get_task_service), - api_key_user: User = Depends(api_key_security), - sync: Annotated[bool, Body(embed=True)] = True, # noqa: F821 - session_service: SessionService = Depends(get_session_service), -): - """ - Endpoint to process an input with a given flow_id. - """ - - try: - if session_id: - session_data = await session_service.load_session(session_id) - graph, artifacts = session_data if session_data else (None, None) - task_result: Any = None - task_status = None - task_id = None - if not graph: - raise ValueError("Graph not found in the session") - result = await build_graph_and_generate_result( - graph=graph, - inputs=inputs, - artifacts=artifacts, - session_id=session_id, - session_service=session_service, - ) - task_id = str(id(result)) - if isinstance(result, dict) and "result" in result: - task_result = result["result"] - session_id = result["session_id"] - elif hasattr(result, "result") and hasattr(result, "session_id"): - task_result = result.result - - session_id = result.session_id - else: - task_result = result - if task_id: - task_response = TaskResponse(id=task_id, href=f"api/v1/task/{task_id}") - else: - task_response = None - return ProcessResponse( - result=task_result, - status=task_status, - task=task_response, - session_id=session_id, - backend=task_service.backend_name, - ) - - else: - if api_key_user is None: - raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail="Invalid API Key", - ) - - # Get the flow that matches the flow_id and belongs to the user - # flow = session.query(Flow).filter(Flow.id == flow_id).filter(Flow.user_id == api_key_user.id).first() - flow = session.exec(select(Flow).where(Flow.id == flow_id).where(Flow.user_id == api_key_user.id)).first() - if flow is None: - raise ValueError(f"Flow {flow_id} not found") - - if flow.data is None: - raise ValueError(f"Flow {flow_id} has no data") - graph_data = flow.data - return await process_graph_data( - graph_data=graph_data, - inputs=inputs, - tweaks=tweaks, - clear_cache=clear_cache, - session_id=session_id, - task_service=task_service, - sync=sync, - ) - except sa.exc.StatementError as exc: - # StatementError('(builtins.ValueError) badly formed hexadecimal UUID string') - if "badly formed hexadecimal UUID string" in str(exc): - # This means the Flow ID is not a valid UUID which means it can't find the flow - raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc - except ValueError as exc: - if f"Flow {flow_id} not found" in str(exc): - raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc - else: - raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(exc)) from exc - except Exception as e: - # Log stack trace - logger.exception(e) - raise HTTPException(status_code=500, detail=str(e)) from e - - -@router.get("/task/{task_id}", response_model=TaskStatusResponse) -async def get_task_status(task_id: str): - task_service = get_task_service() - task = task_service.get_task(task_id) - result = None - if task is None: - raise HTTPException(status_code=404, detail="Task not found") - if task.ready(): - result = task.result - # If result isinstance of Exception, can we get the traceback? - if isinstance(result, Exception): - logger.exception(task.traceback) - - if isinstance(result, dict) and "result" in result: - result = result["result"] - elif hasattr(result, "result"): - result = result.result - - if task.status == "FAILURE": - result = str(task.result) - logger.error(f"Task {task_id} failed: {task.traceback}") - - return TaskStatusResponse(status=task.status, result=result) - - -@router.post( - "/upload/{flow_id}", - response_model=UploadFileResponse, - status_code=HTTPStatus.CREATED, -) -async def create_upload_file(file: UploadFile, flow_id: str): - # Cache file - try: - file_path = save_uploaded_file(file, folder_name=flow_id) - - return UploadFileResponse( - flowId=flow_id, - file_path=file_path, - ) - except Exception as exc: - logger.error(f"Error saving file: {exc}") - raise HTTPException(status_code=500, detail=str(exc)) from exc - - -# get endpoint to return version of langflow -@router.get("/version") -def get_version(): - from langflow import __version__ - - return {"version": __version__} - - -@router.post("/custom_component", status_code=HTTPStatus.OK) -async def custom_component( - raw_code: CustomComponentCode, - user: User = Depends(get_current_active_user), -): - component = CustomComponent(code=raw_code.code) - - built_frontend_node = build_custom_component_template(component, user_id=user.id) - - built_frontend_node = update_frontend_node_with_template_values(built_frontend_node, raw_code.frontend_node) - return built_frontend_node - - -@router.post("/custom_component/reload", status_code=HTTPStatus.OK) -async def reload_custom_component(path: str, user: User = Depends(get_current_active_user)): - from langflow.interface.custom.utils import build_custom_component_template - - try: - reader = DirectoryReader("") - valid, content = reader.process_file(path) - if not valid: - raise ValueError(content) - - extractor = CustomComponent(code=content) - return build_custom_component_template(extractor, user_id=user.id) - except Exception as exc: - raise HTTPException(status_code=400, detail=str(exc)) - - -@router.post("/custom_component/update", status_code=HTTPStatus.OK) -async def custom_component_update( - raw_code: CustomComponentCode, - user: User = Depends(get_current_active_user), -): - component = CustomComponent(code=raw_code.code) - - component_node = build_custom_component_template(component, user_id=user.id, update_field=raw_code.field) - # Update the field - return component_node diff --git a/src/backend/langflow/api/v1/schemas.py b/src/backend/langflow/api/v1/schemas.py deleted file mode 100644 index b28cc8c2c..000000000 --- a/src/backend/langflow/api/v1/schemas.py +++ /dev/null @@ -1,214 +0,0 @@ -from enum import Enum -from pathlib import Path -from typing import Any, Dict, List, Optional, Union -from uuid import UUID - -from langflow.services.database.models.api_key.model import ApiKeyRead -from langflow.services.database.models.base import orjson_dumps -from langflow.services.database.models.flow import FlowCreate, FlowRead -from langflow.services.database.models.user import UserRead -from pydantic import BaseModel, Field, field_validator - - -class BuildStatus(Enum): - """Status of the build.""" - - SUCCESS = "success" - FAILURE = "failure" - STARTED = "started" - IN_PROGRESS = "in_progress" - - -class GraphData(BaseModel): - """Data inside the exported flow.""" - - nodes: List[Dict[str, Any]] - edges: List[Dict[str, Any]] - - -class ExportedFlow(BaseModel): - """Exported flow from Langflow.""" - - description: str - name: str - id: str - data: GraphData - - -class InputRequest(BaseModel): - input: dict - - -class TweaksRequest(BaseModel): - tweaks: Optional[Dict[str, Dict[str, str]]] = Field(default_factory=dict) - - -class UpdateTemplateRequest(BaseModel): - template: dict - - -class TaskResponse(BaseModel): - """Task response schema.""" - - id: Optional[str] = Field(None) - href: Optional[str] = Field(None) - - -class ProcessResponse(BaseModel): - """Process response schema.""" - - result: Any - status: Optional[str] = None - task: Optional[TaskResponse] = None - session_id: Optional[str] = None - backend: Optional[str] = None - - -class PreloadResponse(BaseModel): - """Preload response schema.""" - - session_id: Optional[str] = None - is_clear: Optional[bool] = None - - -# TaskStatusResponse( -# status=task.status, result=task.result if task.ready() else None -# ) -class TaskStatusResponse(BaseModel): - """Task status response schema.""" - - status: str - result: Optional[Any] = None - - -class ChatMessage(BaseModel): - """Chat message schema.""" - - is_bot: bool = False - message: Union[str, None, dict] = None - chatKey: Optional[str] = None - type: str = "human" - - -class ChatResponse(ChatMessage): - """Chat response schema.""" - - intermediate_steps: str - - type: str - is_bot: bool = True - files: list = [] - - @field_validator("type") - @classmethod - def validate_message_type(cls, v): - if v not in ["start", "stream", "end", "error", "info", "file"]: - raise ValueError("type must be start, stream, end, error, info, or file") - return v - - -class PromptResponse(ChatMessage): - """Prompt response schema.""" - - prompt: str - type: str = "prompt" - is_bot: bool = True - - -class FileResponse(ChatMessage): - """File response schema.""" - - data: Any = None - data_type: str - type: str = "file" - is_bot: bool = True - - @field_validator("data_type") - @classmethod - def validate_data_type(cls, v): - if v not in ["image", "csv"]: - raise ValueError("data_type must be image or csv") - return v - - -class FlowListCreate(BaseModel): - flows: List[FlowCreate] - - -class FlowListRead(BaseModel): - flows: List[FlowRead] - - -class InitResponse(BaseModel): - flowId: str - - -class BuiltResponse(BaseModel): - built: bool - - -class UploadFileResponse(BaseModel): - """Upload file response schema.""" - - flowId: str - file_path: Path - - -class StreamData(BaseModel): - event: str - data: dict - - def __str__(self) -> str: - return f"event: {self.event}\ndata: {orjson_dumps(self.data, indent_2=False)}\n\n" - - -class CustomComponentCode(BaseModel): - code: str - field: Optional[str] = None - frontend_node: Optional[dict] = None - - -class CustomComponentResponseError(BaseModel): - detail: str - traceback: str - - -class ComponentListCreate(BaseModel): - flows: List[FlowCreate] - - -class ComponentListRead(BaseModel): - flows: List[FlowRead] - - -class UsersResponse(BaseModel): - total_count: int - users: List[UserRead] - - -class ApiKeyResponse(BaseModel): - id: str - api_key: str - name: str - created_at: str - last_used_at: str - - -class ApiKeysResponse(BaseModel): - total_count: int - user_id: UUID - api_keys: List[ApiKeyRead] - - -class CreateApiKeyRequest(BaseModel): - name: str - - -class Token(BaseModel): - access_token: str - refresh_token: str - token_type: str - - -class ApiKeyCreateRequest(BaseModel): - api_key: str diff --git a/src/backend/langflow/api/v1/validate.py b/src/backend/langflow/api/v1/validate.py deleted file mode 100644 index 51d0f0d76..000000000 --- a/src/backend/langflow/api/v1/validate.py +++ /dev/null @@ -1,120 +0,0 @@ -from fastapi import APIRouter, HTTPException -from langflow.api.v1.base import ( - Code, - CodeValidationResponse, - PromptValidationResponse, - ValidatePromptRequest, - validate_prompt, -) -from langflow.template.field.base import TemplateField -from langflow.utils.validate import validate_code -from loguru import logger - -# build router -router = APIRouter(prefix="/validate", tags=["Validate"]) - - -@router.post("/code", status_code=200, response_model=CodeValidationResponse) -def post_validate_code(code: Code): - try: - errors = validate_code(code.code) - return CodeValidationResponse( - imports=errors.get("imports", {}), - function=errors.get("function", {}), - ) - except Exception as e: - return HTTPException(status_code=500, detail=str(e)) - - -@router.post("/prompt", status_code=200, response_model=PromptValidationResponse) -def post_validate_prompt(prompt_request: ValidatePromptRequest): - try: - input_variables = validate_prompt(prompt_request.template) - # Check if frontend_node is None before proceeding to avoid attempting to update a non-existent node. - if prompt_request.frontend_node is None: - return PromptValidationResponse( - input_variables=input_variables, - frontend_node=None, - ) - old_custom_fields = get_old_custom_fields(prompt_request) - - add_new_variables_to_template(input_variables, prompt_request) - - remove_old_variables_from_template(old_custom_fields, input_variables, prompt_request) - - update_input_variables_field(input_variables, prompt_request) - - return PromptValidationResponse( - input_variables=input_variables, - frontend_node=prompt_request.frontend_node, - ) - except Exception as e: - logger.exception(e) - raise HTTPException(status_code=500, detail=str(e)) from e - - -def get_old_custom_fields(prompt_request): - try: - if len(prompt_request.frontend_node.custom_fields) == 1 and prompt_request.name == "": - # If there is only one custom field and the name is empty string - # then we are dealing with the first prompt request after the node was created - prompt_request.name = list(prompt_request.frontend_node.custom_fields.keys())[0] - - old_custom_fields = prompt_request.frontend_node.custom_fields[prompt_request.name] - if old_custom_fields is None: - old_custom_fields = [] - - old_custom_fields = old_custom_fields.copy() - except KeyError: - old_custom_fields = [] - prompt_request.frontend_node.custom_fields[prompt_request.name] = [] - return old_custom_fields - - -def add_new_variables_to_template(input_variables, prompt_request): - for variable in input_variables: - try: - template_field = TemplateField( - name=variable, - display_name=variable, - field_type="str", - show=True, - advanced=False, - multiline=True, - input_types=["Document", "BaseOutputParser"], - value="", # Set the value to empty string - ) - if variable in prompt_request.frontend_node.template: - # Set the new field with the old value - template_field.value = prompt_request.frontend_node.template[variable]["value"] - - prompt_request.frontend_node.template[variable] = template_field.to_dict() - - # Check if variable is not already in the list before appending - if variable not in prompt_request.frontend_node.custom_fields[prompt_request.name]: - prompt_request.frontend_node.custom_fields[prompt_request.name].append(variable) - - except Exception as exc: - logger.exception(exc) - raise HTTPException(status_code=500, detail=str(exc)) from exc - - -def remove_old_variables_from_template(old_custom_fields, input_variables, prompt_request): - for variable in old_custom_fields: - if variable not in input_variables: - try: - # Remove the variable from custom_fields associated with the given name - if variable in prompt_request.frontend_node.custom_fields[prompt_request.name]: - prompt_request.frontend_node.custom_fields[prompt_request.name].remove(variable) - - # Remove the variable from the template - prompt_request.frontend_node.template.pop(variable, None) - - except Exception as exc: - logger.exception(exc) - raise HTTPException(status_code=500, detail=str(exc)) from exc - - -def update_input_variables_field(input_variables, prompt_request): - if "input_variables" in prompt_request.frontend_node.template: - prompt_request.frontend_node.template["input_variables"]["value"] = input_variables diff --git a/src/backend/langflow/components/agents/CSVAgent.py b/src/backend/langflow/components/agents/CSVAgent.py deleted file mode 100644 index b54e5d90d..000000000 --- a/src/backend/langflow/components/agents/CSVAgent.py +++ /dev/null @@ -1,23 +0,0 @@ -from langflow import CustomComponent -from langflow.field_typing import BaseLanguageModel, AgentExecutor -from langchain_experimental.agents.agent_toolkits.csv.base import create_csv_agent - - -class CSVAgentComponent(CustomComponent): - display_name = "CSVAgent" - description = "Construct a CSV agent from a CSV and tools." - documentation = "https://python.langchain.com/docs/modules/agents/toolkits/csv" - - def build_config(self): - return { - "llm": {"display_name": "LLM", "type": BaseLanguageModel}, - "path": {"display_name": "Path", "field_type": "file", "suffixes": [".csv"], "file_types": [".csv"]}, - } - - def build( - self, - llm: BaseLanguageModel, - path: str, - ) -> AgentExecutor: - # Instantiate and return the CSV agent class with the provided llm and path - return create_csv_agent(llm=llm, path=path) diff --git a/src/backend/langflow/components/chains/ConversationChain.py b/src/backend/langflow/components/chains/ConversationChain.py deleted file mode 100644 index 76e6d8e25..000000000 --- a/src/backend/langflow/components/chains/ConversationChain.py +++ /dev/null @@ -1,29 +0,0 @@ -from langflow import CustomComponent -from langchain.chains import ConversationChain -from typing import Optional, Union, Callable -from langflow.field_typing import BaseLanguageModel, BaseMemory, Chain - - -class ConversationChainComponent(CustomComponent): - display_name = "ConversationChain" - description = "Chain to have a conversation and load context from memory." - - def build_config(self): - return { - "prompt": {"display_name": "Prompt"}, - "llm": {"display_name": "LLM"}, - "memory": { - "display_name": "Memory", - "info": "Memory to load context from. If none is provided, a ConversationBufferMemory will be used.", - }, - "code": {"show": False}, - } - - def build( - self, - llm: BaseLanguageModel, - memory: Optional[BaseMemory] = None, - ) -> Union[Chain, Callable]: - if memory is None: - return ConversationChain(llm=llm) - return ConversationChain(llm=llm, memory=memory) diff --git a/src/backend/langflow/components/chains/LLMCheckerChain.py b/src/backend/langflow/components/chains/LLMCheckerChain.py deleted file mode 100644 index 527cafbb7..000000000 --- a/src/backend/langflow/components/chains/LLMCheckerChain.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Callable, Union - -from langchain.chains import LLMCheckerChain -from langflow import CustomComponent -from langflow.field_typing import BaseLanguageModel, Chain - - -class LLMCheckerChainComponent(CustomComponent): - display_name = "LLMCheckerChain" - description = "" - documentation = "https://python.langchain.com/docs/modules/chains/additional/llm_checker" - - def build_config(self): - return { - "llm": {"display_name": "LLM"}, - } - - def build( - self, - llm: BaseLanguageModel, - ) -> Union[Chain, Callable]: - return LLMCheckerChain.from_llm(llm=llm) diff --git a/src/backend/langflow/components/chains/PromptRunner.py b/src/backend/langflow/components/chains/PromptRunner.py deleted file mode 100644 index 16a3ce429..000000000 --- a/src/backend/langflow/components/chains/PromptRunner.py +++ /dev/null @@ -1,28 +0,0 @@ -from langchain.llms.base import BaseLLM -from langchain.prompts import PromptTemplate -from langchain_core.documents import Document - -from langflow import CustomComponent - - -class PromptRunner(CustomComponent): - display_name: str = "Prompt Runner" - description: str = "Run a Chain with the given PromptTemplate" - beta: bool = True - field_config = { - "llm": {"display_name": "LLM"}, - "prompt": { - "display_name": "Prompt Template", - "info": "Make sure the prompt has all variables filled.", - }, - "code": {"show": False}, - } - - def build(self, llm: BaseLLM, prompt: PromptTemplate, inputs: dict = {}) -> Document: - chain = prompt | llm - # The input is an empty dict because the prompt is already filled - result = chain.invoke(input=inputs) - if hasattr(result, "content"): - result = result.content - self.repr_value = result - return Document(page_content=str(result)) diff --git a/src/backend/langflow/components/chains/RetrievalQA.py b/src/backend/langflow/components/chains/RetrievalQA.py deleted file mode 100644 index 5f1232443..000000000 --- a/src/backend/langflow/components/chains/RetrievalQA.py +++ /dev/null @@ -1,39 +0,0 @@ -from typing import Callable, Optional, Union - -from langchain.chains.combine_documents.base import BaseCombineDocumentsChain -from langchain.chains.retrieval_qa.base import BaseRetrievalQA, RetrievalQA -from langflow import CustomComponent -from langflow.field_typing import BaseMemory, BaseRetriever - - -class RetrievalQAComponent(CustomComponent): - display_name = "RetrievalQA" - description = "Chain for question-answering against an index." - - def build_config(self): - return { - "combine_documents_chain": {"display_name": "Combine Documents Chain"}, - "retriever": {"display_name": "Retriever"}, - "memory": {"display_name": "Memory", "required": False}, - "input_key": {"display_name": "Input Key", "advanced": True}, - "output_key": {"display_name": "Output Key", "advanced": True}, - "return_source_documents": {"display_name": "Return Source Documents"}, - } - - def build( - self, - combine_documents_chain: BaseCombineDocumentsChain, - retriever: BaseRetriever, - memory: Optional[BaseMemory] = None, - input_key: str = "query", - output_key: str = "result", - return_source_documents: bool = True, - ) -> Union[BaseRetrievalQA, Callable]: - return RetrievalQA( - combine_documents_chain=combine_documents_chain, - retriever=retriever, - memory=memory, - input_key=input_key, - output_key=output_key, - return_source_documents=return_source_documents, - ) diff --git a/src/backend/langflow/components/chains/RetrievalQAWithSourcesChain.py b/src/backend/langflow/components/chains/RetrievalQAWithSourcesChain.py deleted file mode 100644 index 3c46cd8bd..000000000 --- a/src/backend/langflow/components/chains/RetrievalQAWithSourcesChain.py +++ /dev/null @@ -1,42 +0,0 @@ -from typing import Optional - -from langchain.chains import RetrievalQAWithSourcesChain -from langchain.chains.qa_with_sources.base import BaseQAWithSourcesChain -from langchain.chains.combine_documents.base import BaseCombineDocumentsChain - -from langflow import CustomComponent -from langflow.field_typing import BaseLanguageModel, BaseMemory, BaseRetriever - - -class RetrievalQAWithSourcesChainComponent(CustomComponent): - display_name = "RetrievalQAWithSourcesChain" - description = "Question-answering with sources over an index." - - def build_config(self): - return { - "llm": {"display_name": "LLM"}, - "chain_type": { - "display_name": "Chain Type", - "options": ["stuff", "map_reduce", "map_rerank", "refine"], - }, - "memory": {"display_name": "Memory"}, - "return_source_documents": {"display_name": "Return Source Documents"}, - } - - def build( - self, - retriever: BaseRetriever, - llm: BaseLanguageModel, - combine_documents_chain: BaseCombineDocumentsChain, - chain_type: str, - memory: Optional[BaseMemory] = None, - return_source_documents: Optional[bool] = True, - ) -> BaseQAWithSourcesChain: - return RetrievalQAWithSourcesChain.from_chain_type( - llm=llm, - chain_type=chain_type, - combine_documents_chain=combine_documents_chain, - memory=memory, - return_source_documents=return_source_documents, - retriever=retriever, - ) diff --git a/src/backend/langflow/components/chains/SQLDatabaseChain.py b/src/backend/langflow/components/chains/SQLDatabaseChain.py deleted file mode 100644 index 56bd433ba..000000000 --- a/src/backend/langflow/components/chains/SQLDatabaseChain.py +++ /dev/null @@ -1,25 +0,0 @@ -from langflow import CustomComponent -from typing import Callable, Union -from langflow.field_typing import BasePromptTemplate, BaseLanguageModel, Chain -from langchain_community.utilities.sql_database import SQLDatabase -from langchain_experimental.sql.base import SQLDatabaseChain - - -class SQLDatabaseChainComponent(CustomComponent): - display_name = "SQLDatabaseChain" - description = "" - - def build_config(self): - return { - "db": {"display_name": "Database"}, - "llm": {"display_name": "LLM"}, - "prompt": {"display_name": "Prompt"}, - } - - def build( - self, - db: SQLDatabase, - llm: BaseLanguageModel, - prompt: BasePromptTemplate, - ) -> Union[Chain, Callable, SQLDatabaseChain]: - return SQLDatabaseChain.from_llm(llm=llm, db=db, prompt=prompt) diff --git a/src/backend/langflow/components/custom_components/CustomComponent.py b/src/backend/langflow/components/custom_components/CustomComponent.py deleted file mode 100644 index 533ccb727..000000000 --- a/src/backend/langflow/components/custom_components/CustomComponent.py +++ /dev/null @@ -1,12 +0,0 @@ -from langflow import CustomComponent -from langflow.field_typing import Data - - -class Component(CustomComponent): - documentation: str = "http://docs.langflow.org/components/custom" - - def build_config(self): - return {"param": {"display_name": "Parameter"}} - - def build(self, param: Data) -> Data: - return param diff --git a/src/backend/langflow/components/documentloaders/DirectoryLoader.py b/src/backend/langflow/components/documentloaders/DirectoryLoader.py deleted file mode 100644 index 5b0875126..000000000 --- a/src/backend/langflow/components/documentloaders/DirectoryLoader.py +++ /dev/null @@ -1,42 +0,0 @@ -from typing import Any, Dict, List - -from langchain.docstore.document import Document -from langchain.document_loaders.directory import DirectoryLoader -from langflow import CustomComponent - - -class DirectoryLoaderComponent(CustomComponent): - display_name = "DirectoryLoader" - description = "Load from a directory." - - def build_config(self) -> Dict[str, Any]: - return { - "glob": {"display_name": "Glob Pattern", "value": "**/*.txt"}, - "load_hidden": {"display_name": "Load Hidden Files", "value": False, "advanced": True}, - "max_concurrency": {"display_name": "Max Concurrency", "value": 10, "advanced": True}, - "metadata": {"display_name": "Metadata", "value": {}}, - "path": {"display_name": "Local Directory"}, - "recursive": {"display_name": "Recursive", "value": True, "advanced": True}, - "silent_errors": {"display_name": "Silent Errors", "value": False, "advanced": True}, - "use_multithreading": {"display_name": "Use Multithreading", "value": True, "advanced": True}, - } - - def build( - self, - glob: str, - path: str, - max_concurrency: int = 2, - load_hidden: bool = False, - recursive: bool = True, - silent_errors: bool = False, - use_multithreading: bool = True, - ) -> List[Document]: - return DirectoryLoader( - glob=glob, - path=path, - load_hidden=load_hidden, - max_concurrency=max_concurrency, - recursive=recursive, - silent_errors=silent_errors, - use_multithreading=use_multithreading, - ).load() diff --git a/src/backend/langflow/components/documentloaders/FileLoader.py b/src/backend/langflow/components/documentloaders/FileLoader.py deleted file mode 100644 index 07160557d..000000000 --- a/src/backend/langflow/components/documentloaders/FileLoader.py +++ /dev/null @@ -1,113 +0,0 @@ -from langchain_core.documents import Document -from langflow import CustomComponent -from langflow.utils.constants import LOADERS_INFO - - -class FileLoaderComponent(CustomComponent): - display_name: str = "File Loader" - description: str = "Generic File Loader" - beta = True - - def build_config(self): - loader_options = ["Automatic"] + [loader_info["name"] for loader_info in LOADERS_INFO] - - file_types = [] - suffixes = [] - - for loader_info in LOADERS_INFO: - if "allowedTypes" in loader_info: - file_types.extend(loader_info["allowedTypes"]) - suffixes.extend([f".{ext}" for ext in loader_info["allowedTypes"]]) - - return { - "file_path": { - "display_name": "File Path", - "required": True, - "field_type": "file", - "file_types": [ - "json", - "txt", - "csv", - "jsonl", - "html", - "htm", - "conllu", - "enex", - "msg", - "pdf", - "srt", - "eml", - "md", - "pptx", - "docx", - ], - "suffixes": [ - ".json", - ".txt", - ".csv", - ".jsonl", - ".html", - ".htm", - ".conllu", - ".enex", - ".msg", - ".pdf", - ".srt", - ".eml", - ".md", - ".pptx", - ".docx", - ], - # "file_types" : file_types, - # "suffixes": suffixes, - }, - "loader": { - "display_name": "Loader", - "is_list": True, - "required": True, - "options": loader_options, - "value": "Automatic", - }, - "code": {"show": False}, - } - - def build(self, file_path: str, loader: str) -> Document: - file_type = file_path.split(".")[-1] - - # Mapeie o nome do loader selecionado para suas informações - selected_loader_info = None - for loader_info in LOADERS_INFO: - if loader_info["name"] == loader: - selected_loader_info = loader_info - break - - if selected_loader_info is None and loader != "Automatic": - raise ValueError(f"Loader {loader} not found in the loader info list") - - if loader == "Automatic": - # Determine o loader automaticamente com base na extensão do arquivo - default_loader_info = None - for info in LOADERS_INFO: - if "defaultFor" in info and file_type in info["defaultFor"]: - default_loader_info = info - break - - if default_loader_info is None: - raise ValueError(f"No default loader found for file type: {file_type}") - - selected_loader_info = default_loader_info - if isinstance(selected_loader_info, dict): - loader_import: str = selected_loader_info["import"] - else: - raise ValueError(f"Loader info for {loader} is not a dict\nLoader info:\n{selected_loader_info}") - module_name, class_name = loader_import.rsplit(".", 1) - - try: - # Importe o loader dinamicamente - loader_module = __import__(module_name, fromlist=[class_name]) - loader_instance = getattr(loader_module, class_name) - except ImportError as e: - raise ValueError(f"Loader {loader} could not be imported\nLoader info:\n{selected_loader_info}") from e - - result = loader_instance(file_path=file_path) - return result.load() diff --git a/src/backend/langflow/components/documentloaders/UrlLoader.py b/src/backend/langflow/components/documentloaders/UrlLoader.py deleted file mode 100644 index eb60ac572..000000000 --- a/src/backend/langflow/components/documentloaders/UrlLoader.py +++ /dev/null @@ -1,47 +0,0 @@ -from typing import List - -from langchain import document_loaders -from langchain_core.documents import Document - -from langflow import CustomComponent - - -class UrlLoaderComponent(CustomComponent): - display_name: str = "Url Loader" - description: str = "Generic Url Loader Component" - - def build_config(self): - return { - "web_path": { - "display_name": "Url", - "required": True, - }, - "loader": { - "display_name": "Loader", - "is_list": True, - "required": True, - "options": [ - "AZLyricsLoader", - "CollegeConfidentialLoader", - "GitbookLoader", - "HNLoader", - "IFixitLoader", - "IMSDbLoader", - "WebBaseLoader", - ], - "value": "WebBaseLoader", - }, - "code": {"show": False}, - } - - def build(self, web_path: str, loader: str) -> List[Document]: - try: - loader_instance = getattr(document_loaders, loader)(web_path=web_path) - except Exception as e: - raise ValueError(f"No loader found for: {web_path}") from e - docs = loader_instance.load() - avg_length = sum(len(doc.page_content) for doc in docs if hasattr(doc, "page_content")) / len(docs) - self.status = f"""{len(docs)} documents) - \nAvg. Document Length (characters): {int(avg_length)} - Documents: {docs[:3]}...""" - return docs diff --git a/src/backend/langflow/components/llms/CTransformers.py b/src/backend/langflow/components/llms/CTransformers.py deleted file mode 100644 index a0668814e..000000000 --- a/src/backend/langflow/components/llms/CTransformers.py +++ /dev/null @@ -1,33 +0,0 @@ -from typing import Dict, Optional - -from langchain_community.llms.ctransformers import CTransformers - -from langflow import CustomComponent - - -class CTransformersComponent(CustomComponent): - display_name = "CTransformers" - description = "C Transformers LLM models" - documentation = "https://python.langchain.com/docs/modules/model_io/models/llms/integrations/ctransformers" - - def build_config(self): - return { - "model": {"display_name": "Model", "required": True}, - "model_file": { - "display_name": "Model File", - "required": False, - "field_type": "file", - "file_types": [".bin"], - }, - "model_type": {"display_name": "Model Type", "required": True}, - "config": { - "display_name": "Config", - "advanced": True, - "required": False, - "field_type": "dict", - "value": '{"top_k":40,"top_p":0.95,"temperature":0.8,"repetition_penalty":1.1,"last_n_tokens":64,"seed":-1,"max_new_tokens":256,"stop":"","stream":"False","reset":"True","batch_size":8,"threads":-1,"context_length":-1,"gpu_layers":0}', - }, - } - - def build(self, model: str, model_file: str, model_type: str, config: Optional[Dict] = None) -> CTransformers: - return CTransformers(model=model, model_file=model_file, model_type=model_type, config=config) # type: ignore diff --git a/src/backend/langflow/components/llms/GoogleGenerativeAI.py b/src/backend/langflow/components/llms/GoogleGenerativeAI.py deleted file mode 100644 index 2fa9002bb..000000000 --- a/src/backend/langflow/components/llms/GoogleGenerativeAI.py +++ /dev/null @@ -1,72 +0,0 @@ -from typing import Optional - -from langchain_google_genai import ChatGoogleGenerativeAI # type: ignore -from langflow import CustomComponent -from langflow.field_typing import BaseLanguageModel, RangeSpec, TemplateField -from pydantic.v1.types import SecretStr - - -class GoogleGenerativeAIComponent(CustomComponent): - display_name: str = "Google Generative AI" - description: str = "A component that uses Google Generative AI to generate text." - documentation: str = "http://docs.langflow.org/components/custom" - - def build_config(self): - return { - "google_api_key": TemplateField( - display_name="Google API Key", - info="The Google API Key to use for the Google Generative AI.", - ), - "max_output_tokens": TemplateField( - display_name="Max Output Tokens", - info="The maximum number of tokens to generate.", - ), - "temperature": TemplateField( - display_name="Temperature", - info="Run inference with this temperature. Must by in the closed interval [0.0, 1.0].", - ), - "top_k": TemplateField( - display_name="Top K", - info="Decode using top-k sampling: consider the set of top_k most probable tokens. Must be positive.", - range_spec=RangeSpec(min=0, max=2, step=0.1), - advanced=True, - ), - "top_p": TemplateField( - display_name="Top P", - info="The maximum cumulative probability of tokens to consider when sampling.", - advanced=True, - ), - "n": TemplateField( - display_name="N", - info="Number of chat completions to generate for each prompt. Note that the API may not return the full n completions if duplicates are generated.", - advanced=True, - ), - "model": TemplateField( - display_name="Model", - info="The name of the model to use. Supported examples: gemini-pro", - options=["gemini-pro", "gemini-pro-vision"], - ), - "code": TemplateField( - advanced=True, - ), - } - - def build( - self, - google_api_key: str, - model: str, - max_output_tokens: Optional[int] = None, - temperature: float = 0.1, - top_k: Optional[int] = None, - top_p: Optional[float] = None, - n: Optional[int] = 1, - ) -> BaseLanguageModel: - return ChatGoogleGenerativeAI( - model=model, - max_output_tokens=max_output_tokens or None, # type: ignore - temperature=temperature, - top_k=top_k or None, - top_p=top_p or None, # type: ignore - n=n or 1, - google_api_key=SecretStr(google_api_key), - ) diff --git a/src/backend/langflow/components/llms/LlamaCpp.py b/src/backend/langflow/components/llms/LlamaCpp.py deleted file mode 100644 index 831665bfa..000000000 --- a/src/backend/langflow/components/llms/LlamaCpp.py +++ /dev/null @@ -1,129 +0,0 @@ -from typing import Optional, List, Dict, Any -from langflow import CustomComponent -from langchain_community.llms.llamacpp import LlamaCpp - - -class LlamaCppComponent(CustomComponent): - display_name = "LlamaCpp" - description = "llama.cpp model." - documentation = "https://python.langchain.com/docs/modules/model_io/models/llms/integrations/llamacpp" - - def build_config(self): - return { - "grammar": {"display_name": "Grammar", "advanced": True}, - "cache": {"display_name": "Cache", "advanced": True}, - "client": {"display_name": "Client", "advanced": True}, - "echo": {"display_name": "Echo", "advanced": True}, - "f16_kv": {"display_name": "F16 KV", "advanced": True}, - "grammar_path": {"display_name": "Grammar Path", "advanced": True}, - "last_n_tokens_size": {"display_name": "Last N Tokens Size", "advanced": True}, - "logits_all": {"display_name": "Logits All", "advanced": True}, - "logprobs": {"display_name": "Logprobs", "advanced": True}, - "lora_base": {"display_name": "Lora Base", "advanced": True}, - "lora_path": {"display_name": "Lora Path", "advanced": True}, - "max_tokens": {"display_name": "Max Tokens", "advanced": True}, - "metadata": {"display_name": "Metadata", "advanced": True}, - "model_kwargs": {"display_name": "Model Kwargs", "advanced": True}, - "model_path": { - "display_name": "Model Path", - "field_type": "file", - "file_types": [".bin"], - "required": True, - }, - "n_batch": {"display_name": "N Batch", "advanced": True}, - "n_ctx": {"display_name": "N Ctx", "advanced": True}, - "n_gpu_layers": {"display_name": "N GPU Layers", "advanced": True}, - "n_parts": {"display_name": "N Parts", "advanced": True}, - "n_threads": {"display_name": "N Threads", "advanced": True}, - "repeat_penalty": {"display_name": "Repeat Penalty", "advanced": True}, - "rope_freq_base": {"display_name": "Rope Freq Base", "advanced": True}, - "rope_freq_scale": {"display_name": "Rope Freq Scale", "advanced": True}, - "seed": {"display_name": "Seed", "advanced": True}, - "stop": {"display_name": "Stop", "advanced": True}, - "streaming": {"display_name": "Streaming", "advanced": True}, - "suffix": {"display_name": "Suffix", "advanced": True}, - "tags": {"display_name": "Tags", "advanced": True}, - "temperature": {"display_name": "Temperature"}, - "top_k": {"display_name": "Top K", "advanced": True}, - "top_p": {"display_name": "Top P", "advanced": True}, - "use_mlock": {"display_name": "Use Mlock", "advanced": True}, - "use_mmap": {"display_name": "Use Mmap", "advanced": True}, - "verbose": {"display_name": "Verbose", "advanced": True}, - "vocab_only": {"display_name": "Vocab Only", "advanced": True}, - } - - def build( - self, - model_path: str, - grammar: Optional[str] = None, - cache: Optional[bool] = None, - client: Optional[Any] = None, - echo: Optional[bool] = False, - f16_kv: bool = True, - grammar_path: Optional[str] = None, - last_n_tokens_size: Optional[int] = 64, - logits_all: bool = False, - logprobs: Optional[int] = None, - lora_base: Optional[str] = None, - lora_path: Optional[str] = None, - max_tokens: Optional[int] = 256, - metadata: Optional[Dict] = None, - model_kwargs: Dict = {}, - n_batch: Optional[int] = 8, - n_ctx: int = 512, - n_gpu_layers: Optional[int] = 1, - n_parts: int = -1, - n_threads: Optional[int] = 1, - repeat_penalty: Optional[float] = 1.1, - rope_freq_base: float = 10000.0, - rope_freq_scale: float = 1.0, - seed: int = -1, - stop: Optional[List[str]] = [], - streaming: bool = True, - suffix: Optional[str] = "", - tags: Optional[List[str]] = [], - temperature: Optional[float] = 0.8, - top_k: Optional[int] = 40, - top_p: Optional[float] = 0.95, - use_mlock: bool = False, - use_mmap: Optional[bool] = True, - verbose: bool = True, - vocab_only: bool = False, - ) -> LlamaCpp: - return LlamaCpp( - model_path=model_path, - grammar=grammar, - cache=cache, - client=client, - echo=echo, - f16_kv=f16_kv, - grammar_path=grammar_path, - last_n_tokens_size=last_n_tokens_size, - logits_all=logits_all, - logprobs=logprobs, - lora_base=lora_base, - lora_path=lora_path, - max_tokens=max_tokens, - metadata=metadata, - model_kwargs=model_kwargs, - n_batch=n_batch, - n_ctx=n_ctx, - n_gpu_layers=n_gpu_layers, - n_parts=n_parts, - n_threads=n_threads, - repeat_penalty=repeat_penalty, - rope_freq_base=rope_freq_base, - rope_freq_scale=rope_freq_scale, - seed=seed, - stop=stop, - streaming=streaming, - suffix=suffix, - tags=tags, - temperature=temperature, - top_k=top_k, - top_p=top_p, - use_mlock=use_mlock, - use_mmap=use_mmap, - verbose=verbose, - vocab_only=vocab_only, - ) diff --git a/src/backend/langflow/components/utilities/GetRequest.py b/src/backend/langflow/components/utilities/GetRequest.py deleted file mode 100644 index b143a8e7e..000000000 --- a/src/backend/langflow/components/utilities/GetRequest.py +++ /dev/null @@ -1,74 +0,0 @@ -from typing import Optional - -import requests -from langchain_core.documents import Document -from langflow import CustomComponent -from langflow.services.database.models.base import orjson_dumps - - -class GetRequest(CustomComponent): - display_name: str = "GET Request" - description: str = "Make a GET request to the given URL." - output_types: list[str] = ["Document"] - documentation: str = "https://docs.langflow.org/components/utilities#get-request" - beta: bool = True - field_config = { - "url": { - "display_name": "URL", - "info": "The URL to make the request to", - "is_list": True, - }, - "headers": { - "display_name": "Headers", - "info": "The headers to send with the request.", - }, - "code": {"show": False}, - "timeout": { - "display_name": "Timeout", - "field_type": "int", - "info": "The timeout to use for the request.", - "value": 5, - }, - } - - def get_document(self, session: requests.Session, url: str, headers: Optional[dict], timeout: int) -> Document: - try: - response = session.get(url, headers=headers, timeout=int(timeout)) - try: - response_json = response.json() - result = orjson_dumps(response_json, indent_2=False) - except Exception: - result = response.text - self.repr_value = result - return Document( - page_content=result, - metadata={ - "source": url, - "headers": headers, - "status_code": response.status_code, - }, - ) - except requests.Timeout: - return Document( - page_content="Request Timed Out", - metadata={"source": url, "headers": headers, "status_code": 408}, - ) - except Exception as exc: - return Document( - page_content=str(exc), - metadata={"source": url, "headers": headers, "status_code": 500}, - ) - - def build( - self, - url: str, - headers: Optional[dict] = None, - timeout: int = 5, - ) -> list[Document]: - if headers is None: - headers = {} - urls = url if isinstance(url, list) else [url] - with requests.Session() as session: - documents = [self.get_document(session, u, headers, timeout) for u in urls] - self.repr_value = documents - return documents diff --git a/src/backend/langflow/components/utilities/PostRequest.py b/src/backend/langflow/components/utilities/PostRequest.py deleted file mode 100644 index baf734f54..000000000 --- a/src/backend/langflow/components/utilities/PostRequest.py +++ /dev/null @@ -1,77 +0,0 @@ -from typing import Optional - -import requests -from langchain_core.documents import Document -from langflow import CustomComponent -from langflow.services.database.models.base import orjson_dumps - - -class PostRequest(CustomComponent): - display_name: str = "POST Request" - description: str = "Make a POST request to the given URL." - output_types: list[str] = ["Document"] - documentation: str = "https://docs.langflow.org/components/utilities#post-request" - beta: bool = True - field_config = { - "url": {"display_name": "URL", "info": "The URL to make the request to."}, - "headers": { - "display_name": "Headers", - "info": "The headers to send with the request.", - }, - "code": {"show": False}, - "document": {"display_name": "Document"}, - } - - def post_document( - self, - session: requests.Session, - document: Document, - url: str, - headers: Optional[dict] = None, - ) -> Document: - try: - response = session.post(url, headers=headers, data=document.page_content) - try: - response_json = response.json() - result = orjson_dumps(response_json, indent_2=False) - except Exception: - result = response.text - self.repr_value = result - return Document( - page_content=result, - metadata={ - "source": url, - "headers": headers, - "status_code": response, - }, - ) - except Exception as exc: - return Document( - page_content=str(exc), - metadata={ - "source": url, - "headers": headers, - "status_code": 500, - }, - ) - - def build( - self, - document: Document, - url: str, - headers: Optional[dict] = None, - ) -> list[Document]: - if headers is None: - headers = {} - - if not isinstance(document, list) and isinstance(document, Document): - documents: list[Document] = [document] - elif isinstance(document, list) and all(isinstance(doc, Document) for doc in document): - documents = document - else: - raise ValueError("document must be a Document or a list of Documents") - - with requests.Session() as session: - documents = [self.post_document(session, doc, url, headers) for doc in documents] - self.repr_value = documents - return documents diff --git a/src/backend/langflow/components/utilities/UpdateRequest.py b/src/backend/langflow/components/utilities/UpdateRequest.py deleted file mode 100644 index bd40f642d..000000000 --- a/src/backend/langflow/components/utilities/UpdateRequest.py +++ /dev/null @@ -1,88 +0,0 @@ -from typing import List, Optional - -import requests -from langchain_core.documents import Document -from langflow import CustomComponent -from langflow.services.database.models.base import orjson_dumps - - -class UpdateRequest(CustomComponent): - display_name: str = "Update Request" - description: str = "Make a PATCH request to the given URL." - output_types: list[str] = ["Document"] - documentation: str = "https://docs.langflow.org/components/utilities#update-request" - beta: bool = True - field_config = { - "url": {"display_name": "URL", "info": "The URL to make the request to."}, - "headers": { - "display_name": "Headers", - "field_type": "NestedDict", - "info": "The headers to send with the request.", - }, - "code": {"show": False}, - "document": {"display_name": "Document"}, - "method": { - "display_name": "Method", - "field_type": "str", - "info": "The HTTP method to use.", - "options": ["PATCH", "PUT"], - "value": "PATCH", - }, - } - - def update_document( - self, - session: requests.Session, - document: Document, - url: str, - headers: Optional[dict] = None, - method: str = "PATCH", - ) -> Document: - try: - if method == "PATCH": - response = session.patch(url, headers=headers, data=document.page_content) - elif method == "PUT": - response = session.put(url, headers=headers, data=document.page_content) - else: - raise ValueError(f"Unsupported method: {method}") - try: - response_json = response.json() - result = orjson_dumps(response_json, indent_2=False) - except Exception: - result = response.text - self.repr_value = result - return Document( - page_content=result, - metadata={ - "source": url, - "headers": headers, - "status_code": response.status_code, - }, - ) - except Exception as exc: - return Document( - page_content=str(exc), - metadata={"source": url, "headers": headers, "status_code": 500}, - ) - - def build( - self, - method: str, - document: Document, - url: str, - headers: Optional[dict] = None, - ) -> List[Document]: - if headers is None: - headers = {} - - if not isinstance(document, list) and isinstance(document, Document): - documents: list[Document] = [document] - elif isinstance(document, list) and all(isinstance(doc, Document) for doc in document): - documents = document - else: - raise ValueError("document must be a Document or a list of Documents") - - with requests.Session() as session: - documents = [self.update_document(session, doc, url, headers, method) for doc in documents] - self.repr_value = documents - return documents diff --git a/src/backend/langflow/components/vectorstores/FAISS.py b/src/backend/langflow/components/vectorstores/FAISS.py deleted file mode 100644 index dec14f6db..000000000 --- a/src/backend/langflow/components/vectorstores/FAISS.py +++ /dev/null @@ -1,26 +0,0 @@ -from typing import List, Union - -from langchain.schema import BaseRetriever -from langchain_community.vectorstores import VectorStore -from langchain_community.vectorstores.faiss import FAISS -from langflow import CustomComponent -from langflow.field_typing import Document, Embeddings - - -class FAISSComponent(CustomComponent): - display_name = "FAISS" - description = "Construct FAISS wrapper from raw documents." - documentation = "https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/faiss" - - def build_config(self): - return { - "documents": {"display_name": "Documents"}, - "embedding": {"display_name": "Embedding"}, - } - - def build( - self, - embedding: Embeddings, - documents: List[Document], - ) -> Union[VectorStore, FAISS, BaseRetriever]: - return FAISS.from_documents(documents=documents, embedding=embedding) diff --git a/src/backend/langflow/components/vectorstores/MongoDBAtlasVectorSearch.py b/src/backend/langflow/components/vectorstores/MongoDBAtlasVectorSearch.py deleted file mode 100644 index 13b62b708..000000000 --- a/src/backend/langflow/components/vectorstores/MongoDBAtlasVectorSearch.py +++ /dev/null @@ -1,48 +0,0 @@ -from typing import List, Optional - -from langchain_community.vectorstores.mongodb_atlas import MongoDBAtlasVectorSearch - -from langflow import CustomComponent -from langflow.field_typing import Document, Embeddings, NestedDict - - -class MongoDBAtlasComponent(CustomComponent): - display_name = "MongoDB Atlas" - description = "a `MongoDB Atlas Vector Search` vector store from raw documents." - - def build_config(self): - return { - "documents": {"display_name": "Documents", "is_list": True}, - "embedding": {"display_name": "Embedding"}, - "collection_name": {"display_name": "Collection Name"}, - "db_name": {"display_name": "Database Name"}, - "index_name": {"display_name": "Index Name"}, - "mongodb_atlas_cluster_uri": {"display_name": "MongoDB Atlas Cluster URI"}, - "search_kwargs": {"display_name": "Search Kwargs", "advanced": True}, - } - - def build( - self, - embedding: Embeddings, - documents: Optional[List[Document]] = None, - collection_name: str = "", - db_name: str = "", - index_name: str = "", - mongodb_atlas_cluster_uri: str = "", - search_kwargs: Optional[NestedDict] = None, - ) -> MongoDBAtlasVectorSearch: - search_kwargs = search_kwargs or {} - vector_store = MongoDBAtlasVectorSearch.from_connection_string( - connection_string=mongodb_atlas_cluster_uri, - namespace=f"{db_name}.{collection_name}", - embedding=embedding, - index_name=index_name, - ) - - if documents is not None: - if len(documents) == 0: - raise ValueError("If documents are provided, there must be at least one document.") - - vector_store.add_documents(documents) - - return vector_store diff --git a/src/backend/langflow/field_typing/range_spec.py b/src/backend/langflow/field_typing/range_spec.py deleted file mode 100644 index 036d21fa9..000000000 --- a/src/backend/langflow/field_typing/range_spec.py +++ /dev/null @@ -1,21 +0,0 @@ -from pydantic import BaseModel, field_validator - - -class RangeSpec(BaseModel): - min: float = -1.0 - max: float = 1.0 - step: float = 0.1 - - @field_validator("max") - @classmethod - def max_must_be_greater_than_min(cls, v, values, **kwargs): - if "min" in values.data and v <= values.data["min"]: - raise ValueError("max must be greater than min") - return v - - @field_validator("step") - @classmethod - def step_must_be_positive(cls, v): - if v <= 0: - raise ValueError("step must be positive") - return v diff --git a/src/backend/langflow/graph/graph/base.py b/src/backend/langflow/graph/graph/base.py deleted file mode 100644 index d1629d49b..000000000 --- a/src/backend/langflow/graph/graph/base.py +++ /dev/null @@ -1,255 +0,0 @@ -from typing import Dict, Generator, List, Type, Union - -from langchain.chains.base import Chain -from loguru import logger - -from langflow.graph.edge.base import Edge -from langflow.graph.graph.constants import lazy_load_vertex_dict -from langflow.graph.graph.utils import process_flow -from langflow.graph.vertex.base import Vertex -from langflow.graph.vertex.types import FileToolVertex, LLMVertex, ToolkitVertex -from langflow.interface.tools.constants import FILE_TOOLS -from langflow.utils import payload - - -class Graph: - """A class representing a graph of vertices and edges.""" - - def __init__( - self, - nodes: List[Dict], - edges: List[Dict[str, str]], - ) -> None: - self._vertices = nodes - self._edges = edges - self.raw_graph_data = {"nodes": nodes, "edges": edges} - - self.top_level_vertices = [] - for vertex in self._vertices: - if vertex_id := vertex.get("id"): - self.top_level_vertices.append(vertex_id) - self._graph_data = process_flow(self.raw_graph_data) - - self._vertices = self._graph_data["nodes"] - self._edges = self._graph_data["edges"] - self._build_graph() - - def __getstate__(self): - return self.raw_graph_data - - def __setstate__(self, state): - self.__init__(**state) - - @classmethod - def from_payload(cls, payload: Dict) -> "Graph": - """ - Creates a graph from a payload. - - Args: - payload (Dict): The payload to create the graph from.˜` - - Returns: - Graph: The created graph. - """ - if "data" in payload: - payload = payload["data"] - try: - vertices = payload["nodes"] - edges = payload["edges"] - return cls(vertices, edges) - except KeyError as exc: - logger.exception(exc) - raise ValueError( - f"Invalid payload. Expected keys 'nodes' and 'edges'. Found {list(payload.keys())}" - ) from exc - - def __eq__(self, other: object) -> bool: - if not isinstance(other, Graph): - return False - return self.__repr__() == other.__repr__() - - def _build_graph(self) -> None: - """Builds the graph from the vertices and edges.""" - self.vertices = self._build_vertices() - self.vertex_map = {vertex.id: vertex for vertex in self.vertices} - self.edges = self._build_edges() - - # This is a hack to make sure that the LLM vertex is sent to - # the toolkit vertex - self._build_vertex_params() - # remove invalid vertices - self._validate_vertices() - - def _build_vertex_params(self) -> None: - """Identifies and handles the LLM vertex within the graph.""" - llm_vertex = None - for vertex in self.vertices: - vertex._build_params() - if isinstance(vertex, LLMVertex): - llm_vertex = vertex - - if llm_vertex: - for vertex in self.vertices: - if isinstance(vertex, ToolkitVertex): - vertex.params["llm"] = llm_vertex - - def _validate_vertices(self) -> None: - """Check that all vertices have edges""" - if len(self.vertices) == 1: - return - for vertex in self.vertices: - if not self._validate_vertex(vertex): - raise ValueError(f"{vertex.vertex_type} is not connected to any other components") - - def _validate_vertex(self, vertex: Vertex) -> bool: - """Validates a vertex.""" - # All vertices that do not have edges are invalid - return len(self.get_vertex_edges(vertex.id)) > 0 - - def get_vertex(self, vertex_id: str) -> Union[None, Vertex]: - """Returns a vertex by id.""" - return self.vertex_map.get(vertex_id) - - def get_vertex_edges(self, vertex_id: str) -> List[Edge]: - """Returns a list of edges for a given vertex.""" - return [edge for edge in self.edges if edge.source_id == vertex_id or edge.target_id == vertex_id] - - def get_vertices_with_target(self, vertex_id: str) -> List[Vertex]: - """Returns the vertices connected to a vertex.""" - vertices: List[Vertex] = [] - for edge in self.edges: - if edge.target_id == vertex_id: - vertex = self.get_vertex(edge.source_id) - if vertex is None: - continue - vertices.append(vertex) - return vertices - - async def build(self) -> Chain: - """Builds the graph.""" - # Get root vertex - root_vertex = payload.get_root_vertex(self) - if root_vertex is None: - raise ValueError("No root vertex found") - return await root_vertex.build() - - def topological_sort(self) -> List[Vertex]: - """ - Performs a topological sort of the vertices in the graph. - - Returns: - List[Vertex]: A list of vertices in topological order. - - Raises: - ValueError: If the graph contains a cycle. - """ - # States: 0 = unvisited, 1 = visiting, 2 = visited - state = {vertex: 0 for vertex in self.vertices} - sorted_vertices = [] - - def dfs(vertex): - if state[vertex] == 1: - # We have a cycle - raise ValueError("Graph contains a cycle, cannot perform topological sort") - if state[vertex] == 0: - state[vertex] = 1 - for edge in vertex.edges: - if edge.source_id == vertex.id: - dfs(self.get_vertex(edge.target_id)) - state[vertex] = 2 - sorted_vertices.append(vertex) - - # Visit each vertex - for vertex in self.vertices: - if state[vertex] == 0: - dfs(vertex) - - return list(reversed(sorted_vertices)) - - def generator_build(self) -> Generator[Vertex, None, None]: - """Builds each vertex in the graph and yields it.""" - sorted_vertices = self.topological_sort() - logger.debug("There are %s vertices in the graph", len(sorted_vertices)) - yield from sorted_vertices - - def get_vertex_neighbors(self, vertex: Vertex) -> Dict[Vertex, int]: - """Returns the neighbors of a vertex.""" - neighbors: Dict[Vertex, int] = {} - for edge in self.edges: - if edge.source_id == vertex.id: - neighbor = self.get_vertex(edge.target_id) - if neighbor is None: - continue - if neighbor not in neighbors: - neighbors[neighbor] = 0 - neighbors[neighbor] += 1 - elif edge.target_id == vertex.id: - neighbor = self.get_vertex(edge.source_id) - if neighbor is None: - continue - if neighbor not in neighbors: - neighbors[neighbor] = 0 - neighbors[neighbor] += 1 - return neighbors - - def _build_edges(self) -> List[Edge]: - """Builds the edges of the graph.""" - # Edge takes two vertices as arguments, so we need to build the vertices first - # and then build the edges - # if we can't find a vertex, we raise an error - - edges: List[Edge] = [] - for edge in self._edges: - source = self.get_vertex(edge["source"]) - target = self.get_vertex(edge["target"]) - if source is None: - raise ValueError(f"Source vertex {edge['source']} not found") - if target is None: - raise ValueError(f"Target vertex {edge['target']} not found") - edges.append(Edge(source, target, edge)) - return edges - - def _get_vertex_class(self, vertex_type: str, vertex_base_type: str) -> Type[Vertex]: - """Returns the vertex class based on the vertex type.""" - if vertex_type in FILE_TOOLS: - return FileToolVertex - if vertex_base_type == "CustomComponent": - return lazy_load_vertex_dict.get_custom_component_vertex_type() - - if vertex_base_type in lazy_load_vertex_dict.VERTEX_TYPE_MAP: - return lazy_load_vertex_dict.VERTEX_TYPE_MAP[vertex_base_type] - return ( - lazy_load_vertex_dict.VERTEX_TYPE_MAP[vertex_type] - if vertex_type in lazy_load_vertex_dict.VERTEX_TYPE_MAP - else Vertex - ) - - def _build_vertices(self) -> List[Vertex]: - """Builds the vertices of the graph.""" - vertices: List[Vertex] = [] - for vertex in self._vertices: - vertex_data = vertex["data"] - vertex_type: str = vertex_data["type"] # type: ignore - vertex_base_type: str = vertex_data["node"]["template"]["_type"] # type: ignore - - VertexClass = self._get_vertex_class(vertex_type, vertex_base_type) - vertex_instance = VertexClass(vertex, graph=self) - vertex_instance.set_top_level(self.top_level_vertices) - vertices.append(vertex_instance) - - return vertices - - def get_children_by_vertex_type(self, vertex: Vertex, vertex_type: str) -> List[Vertex]: - """Returns the children of a vertex based on the vertex type.""" - children = [] - vertex_types = [vertex.data["type"]] - if "node" in vertex.data: - vertex_types += vertex.data["node"]["base_classes"] - if vertex_type in vertex_types: - children.append(vertex) - return children - - def __repr__(self): - vertex_ids = [vertex.id for vertex in self.vertices] - edges_repr = "\n".join([f"{edge.source_id} --> {edge.target_id}" for edge in self.edges]) - return f"Graph:\nNodes: {vertex_ids}\nConnections:\n{edges_repr}" diff --git a/src/backend/langflow/graph/vertex/base.py b/src/backend/langflow/graph/vertex/base.py deleted file mode 100644 index bd38186e1..000000000 --- a/src/backend/langflow/graph/vertex/base.py +++ /dev/null @@ -1,378 +0,0 @@ -import ast -import inspect -import types -from typing import TYPE_CHECKING, Any, Coroutine, Dict, List, Optional - -from langflow.graph.utils import UnbuiltObject -from langflow.interface.initialize import loading -from langflow.interface.listing import lazy_load_dict -from langflow.utils.constants import DIRECT_TYPES -from langflow.utils.util import sync_to_async -from loguru import logger - -if TYPE_CHECKING: - from langflow.graph.edge.base import Edge - from langflow.graph.graph.base import Graph - - -class Vertex: - def __init__( - self, - data: Dict, - graph: "Graph", - base_type: Optional[str] = None, - is_task: bool = False, - params: Optional[Dict] = None, - ) -> None: - self.graph = graph - self.id: str = data["id"] - self._data = data - self.base_type: Optional[str] = base_type - self._parse_data() - self._built_object = UnbuiltObject() - self._built = False - self.artifacts: Dict[str, Any] = {} - self.task_id: Optional[str] = None - self.is_task = is_task - self.params = params or {} - self.parent_node_id: Optional[str] = self._data.get("parent_node_id") - self.parent_is_top_level = False - - @property - def edges(self) -> List["Edge"]: - return self.graph.get_vertex_edges(self.id) - - def __getstate__(self): - return { - "_data": self._data, - "params": {}, - "base_type": self.base_type, - "is_task": self.is_task, - "id": self.id, - "_built_object": UnbuiltObject(), - "_built": False, - "parent_node_id": self.parent_node_id, - "parent_is_top_level": self.parent_is_top_level, - } - - def __setstate__(self, state): - self._data = state["_data"] - self.params = state["params"] - self.base_type = state["base_type"] - self.is_task = state["is_task"] - self.id = state["id"] - self._parse_data() - if "_built_object" in state: - self._built_object = state["_built_object"] - self._built = state["_built"] - else: - self._built_object = UnbuiltObject() - self._built = False - self.artifacts: Dict[str, Any] = {} - self.task_id: Optional[str] = None - self.parent_node_id = state["parent_node_id"] - self.parent_is_top_level = state["parent_is_top_level"] - - def set_top_level(self, top_level_vertices: List[str]) -> None: - self.parent_is_top_level = self.parent_node_id in top_level_vertices - - def _parse_data(self) -> None: - self.data = self._data["data"] - self.output = self.data["node"]["base_classes"] - template_dicts = {key: value for key, value in self.data["node"]["template"].items() if isinstance(value, dict)} - - self.required_inputs = [ - template_dicts[key]["type"] for key, value in template_dicts.items() if value["required"] - ] - self.optional_inputs = [ - template_dicts[key]["type"] for key, value in template_dicts.items() if not value["required"] - ] - # Add the template_dicts[key]["input_types"] to the optional_inputs - self.optional_inputs.extend( - [input_type for value in template_dicts.values() for input_type in value.get("input_types", [])] - ) - - template_dict = self.data["node"]["template"] - self.vertex_type = ( - self.data["type"] - if "Tool" not in self.output or template_dict["_type"].islower() - else template_dict["_type"] - ) - - if self.base_type is None: - for base_type, value in lazy_load_dict.ALL_TYPES_DICT.items(): - if self.vertex_type in value: - self.base_type = base_type - break - - def get_task(self): - # using the task_id, get the task from celery - # and return it - from celery.result import AsyncResult # type: ignore - - return AsyncResult(self.task_id) - - def _build_params(self): - # sourcery skip: merge-list-append, remove-redundant-if - # Some params are required, some are optional - # but most importantly, some params are python base classes - # like str and others are LangChain objects like LLMChain, BasePromptTemplate - # so we need to be able to distinguish between the two - - # The dicts with "type" == "str" are the ones that are python base classes - # and most likely have a "value" key - - # So for each key besides "_type" in the template dict, we have a dict - # with a "type" key. If the type is not "str", then we need to get the - # edge that connects to that node and get the Node with the required data - # and use that as the value for the param - # If the type is "str", then we need to get the value of the "value" key - # and use that as the value for the param - - if self.graph is None: - raise ValueError("Graph not found") - - template_dict = {key: value for key, value in self.data["node"]["template"].items() if isinstance(value, dict)} - params = self.params.copy() if self.params else {} - - for edge in self.edges: - if not hasattr(edge, "target_param"): - continue - param_key = edge.target_param - - # If the param_key is in the template_dict and the edge.target_id is the current node - # We check this to make sure params with the same name but different target_id - # don't get overwritten - if param_key in template_dict and edge.target_id == self.id: - if template_dict[param_key]["list"]: - if param_key not in params: - params[param_key] = [] - params[param_key].append(self.graph.get_vertex(edge.source_id)) - elif edge.target_id == self.id: - params[param_key] = self.graph.get_vertex(edge.source_id) - - for key, value in template_dict.items(): - if key in params: - continue - # Skip _type and any value that has show == False and is not code - # If we don't want to show code but we want to use it - if key == "_type" or (not value.get("show") and key != "code"): - continue - # If the type is not transformable to a python base class - # then we need to get the edge that connects to this node - if value.get("type") == "file": - # Load the type in value.get('fileTypes') using - # what is inside value.get('content') - # value.get('value') is the file name - if file_path := value.get("file_path"): - params[key] = file_path - else: - raise ValueError(f"File path not found for {self.vertex_type}") - elif value.get("type") in DIRECT_TYPES and params.get(key) is None: - val = value.get("value") - if value.get("type") == "code": - try: - params[key] = ast.literal_eval(val) if val else None - except Exception as exc: - logger.debug(f"Error parsing code: {exc}") - params[key] = val - elif value.get("type") in ["dict", "NestedDict"]: - # When dict comes from the frontend it comes as a - # list of dicts, so we need to convert it to a dict - # before passing it to the build method - if isinstance(val, list): - params[key] = {k: v for item in value.get("value", []) for k, v in item.items()} - elif isinstance(val, dict): - params[key] = val - elif value.get("type") == "int" and val is not None: - try: - params[key] = int(val) - except ValueError: - params[key] = val - elif value.get("type") == "float" and val is not None: - try: - params[key] = float(val) - except ValueError: - params[key] = val - elif val is not None and val != "": - params[key] = val - - if not value.get("required") and params.get(key) is None: - if value.get("default"): - params[key] = value.get("default") - else: - params.pop(key, None) - # Add _type to params - self._raw_params = params - self.params = params - - async def _build(self, user_id=None): - """ - Initiate the build process. - """ - logger.debug(f"Building {self.vertex_type}") - await self._build_each_node_in_params_dict(user_id) - await self._get_and_instantiate_class(user_id) - self._validate_built_object() - - self._built = True - - async def _build_each_node_in_params_dict(self, user_id=None): - """ - Iterates over each node in the params dictionary and builds it. - """ - for key, value in self.params.copy().items(): - if self._is_node(value): - if value == self: - del self.params[key] - continue - await self._build_node_and_update_params(key, value, user_id) - elif isinstance(value, list) and self._is_list_of_nodes(value): - await self._build_list_of_nodes_and_update_params(key, value, user_id) - - def _is_node(self, value): - """ - Checks if the provided value is an instance of Vertex. - """ - return isinstance(value, Vertex) - - def _is_list_of_nodes(self, value): - """ - Checks if the provided value is a list of Vertex instances. - """ - return all(self._is_node(node) for node in value) - - async def get_result(self, user_id=None, timeout=None) -> Any: - # Check if the Vertex was built already - if self._built: - return self._built_object - - if self.is_task and self.task_id is not None: - task = self.get_task() - - result = task.get(timeout=timeout) - if isinstance(result, Coroutine): - result = await result - if result is not None: # If result is ready - self._update_built_object_and_artifacts(result) - return self._built_object - else: - # Handle the case when the result is not ready (retry, throw exception, etc.) - pass - - # If there's no task_id, build the vertex locally - await self.build(user_id=user_id) - return self._built_object - - async def _build_node_and_update_params(self, key, node, user_id=None): - """ - Builds a given node and updates the params dictionary accordingly. - """ - - result = await node.get_result(user_id) - self._handle_func(key, result) - if isinstance(result, list): - self._extend_params_list_with_result(key, result) - self.params[key] = result - - async def _build_list_of_nodes_and_update_params(self, key, nodes: List["Vertex"], user_id=None): - """ - Iterates over a list of nodes, builds each and updates the params dictionary. - """ - self.params[key] = [] - for node in nodes: - built = await node.get_result(user_id) - if isinstance(built, list): - if key not in self.params: - self.params[key] = [] - self.params[key].extend(built) - else: - self.params[key].append(built) - - def _handle_func(self, key, result): - """ - Handles 'func' key by checking if the result is a function and setting it as coroutine. - """ - if key == "func": - if not isinstance(result, types.FunctionType): - if hasattr(result, "run"): - result = result.run # type: ignore - elif hasattr(result, "get_function"): - result = result.get_function() # type: ignore - elif inspect.iscoroutinefunction(result): - self.params["coroutine"] = result - else: - self.params["coroutine"] = sync_to_async(result) - - def _extend_params_list_with_result(self, key, result): - """ - Extends a list in the params dictionary with the given result if it exists. - """ - if isinstance(self.params[key], list): - self.params[key].extend(result) - - async def _get_and_instantiate_class(self, user_id=None): - """ - Gets the class from a dictionary and instantiates it with the params. - """ - if self.base_type is None: - raise ValueError(f"Base type for node {self.vertex_type} not found") - try: - result = await loading.instantiate_class( - node_type=self.vertex_type, - base_type=self.base_type, - params=self.params, - user_id=user_id, - ) - self._update_built_object_and_artifacts(result) - except Exception as exc: - logger.exception(exc) - raise ValueError(f"Error building node {self.vertex_type}(ID:{self.id}): {str(exc)}") from exc - - def _update_built_object_and_artifacts(self, result): - """ - Updates the built object and its artifacts. - """ - if isinstance(result, tuple): - self._built_object, self.artifacts = result - else: - self._built_object = result - - def _validate_built_object(self): - """ - Checks if the built object is None and raises a ValueError if so. - """ - if isinstance(self._built_object, UnbuiltObject): - raise ValueError(f"{self.vertex_type}: {self._built_object_repr()}") - elif self._built_object is None: - message = f"{self.vertex_type} returned None." - if self.base_type == "custom_components": - message += " Make sure your build method returns a component." - - logger.warning(message) - - async def build(self, force: bool = False, user_id=None, *args, **kwargs) -> Any: - if not self._built or force: - await self._build(user_id, *args, **kwargs) - - return self._built_object - - def add_edge(self, edge: "Edge") -> None: - if edge not in self.edges: - self.edges.append(edge) - - def __repr__(self) -> str: - return f"Vertex(id={self.id}, data={self.data})" - - def __eq__(self, __o: object) -> bool: - try: - return self.id == __o.id if isinstance(__o, Vertex) else False - except AttributeError: - return False - - def __hash__(self) -> int: - return id(self) - - def _built_object_repr(self): - # Add a message with an emoji, stars for sucess, - return "Built sucessfully ✨" if self._built_object is not None else "Failed to build 😵‍💫" diff --git a/src/backend/langflow/graph/vertex/types.py b/src/backend/langflow/graph/vertex/types.py deleted file mode 100644 index 7439876fa..000000000 --- a/src/backend/langflow/graph/vertex/types.py +++ /dev/null @@ -1,302 +0,0 @@ -import ast -from typing import Any, Dict, List, Optional, Union - -from langflow.graph.utils import UnbuiltObject, flatten_list -from langflow.graph.vertex.base import Vertex -from langflow.interface.utils import extract_input_variables_from_prompt - - -class AgentVertex(Vertex): - def __init__(self, data: Dict, graph, params: Optional[Dict] = None): - super().__init__(data, graph=graph, base_type="agents", params=params) - - self.tools: List[Union[ToolkitVertex, ToolVertex]] = [] - self.chains: List[ChainVertex] = [] - - def __getstate__(self): - state = super().__getstate__() - state["tools"] = self.tools - state["chains"] = self.chains - return state - - def __setstate__(self, state): - self.tools = state["tools"] - self.chains = state["chains"] - super().__setstate__(state) - - def _set_tools_and_chains(self) -> None: - for edge in self.edges: - if not hasattr(edge, "source_id"): - continue - source_node = self.graph.get_vertex(edge.source_id) - if isinstance(source_node, (ToolVertex, ToolkitVertex)): - self.tools.append(source_node) - elif isinstance(source_node, ChainVertex): - self.chains.append(source_node) - - async def build(self, force: bool = False, user_id=None, *args, **kwargs) -> Any: - if not self._built or force: - self._set_tools_and_chains() - # First, build the tools - for tool_node in self.tools: - await tool_node.build(user_id=user_id) - - # Next, build the chains and the rest - for chain_node in self.chains: - await chain_node.build(tools=self.tools, user_id=user_id) - - await self._build(user_id=user_id) - - return self._built_object - - -class ToolVertex(Vertex): - def __init__( - self, - data: Dict, - graph, - params: Optional[Dict] = None, - ): - super().__init__(data, graph=graph, base_type="tools", params=params) - - -class LLMVertex(Vertex): - built_node_type = None - class_built_object = None - - def __init__(self, data: Dict, graph, params: Optional[Dict] = None): - super().__init__(data, graph=graph, base_type="llms", params=params) - - async def build(self, force: bool = False, user_id=None, *args, **kwargs) -> Any: - # LLM is different because some models might take up too much memory - # or time to load. So we only load them when we need them.ß - if self.vertex_type == self.built_node_type: - return self.class_built_object - if not self._built or force: - await self._build(user_id=user_id) - self.built_node_type = self.vertex_type - self.class_built_object = self._built_object - # Avoid deepcopying the LLM - # that are loaded from a file - return self._built_object - - -class ToolkitVertex(Vertex): - def __init__(self, data: Dict, graph, params=None): - super().__init__(data, graph=graph, base_type="toolkits", params=params) - - -class FileToolVertex(ToolVertex): - def __init__(self, data: Dict, graph, params=None): - super().__init__(data, graph=graph, params=params) - - -class WrapperVertex(Vertex): - def __init__(self, data: Dict, graph): - super().__init__(data, graph=graph, base_type="wrappers") - - async def build(self, force: bool = False, user_id=None, *args, **kwargs) -> Any: - if not self._built or force: - if "headers" in self.params: - self.params["headers"] = ast.literal_eval(self.params["headers"]) - await self._build(user_id=user_id) - return self._built_object - - -class DocumentLoaderVertex(Vertex): - def __init__(self, data: Dict, graph, params: Optional[Dict] = None): - super().__init__(data, graph=graph, base_type="documentloaders", params=params) - - def _built_object_repr(self): - # This built_object is a list of documents. Maybe we should - # show how many documents are in the list? - - if self._built_object and not isinstance(self._built_object, UnbuiltObject): - avg_length = sum(len(doc.page_content) for doc in self._built_object if hasattr(doc, "page_content")) / len( - self._built_object - ) - return f"""{self.vertex_type}({len(self._built_object)} documents) - \nAvg. Document Length (characters): {int(avg_length)} - Documents: {self._built_object[:3]}...""" - return f"{self.vertex_type}()" - - -class EmbeddingVertex(Vertex): - def __init__(self, data: Dict, graph, params: Optional[Dict] = None): - super().__init__(data, graph=graph, base_type="embeddings", params=params) - - -class VectorStoreVertex(Vertex): - def __init__(self, data: Dict, graph, params=None): - super().__init__(data, graph=graph, base_type="vectorstores") - - self.params = params or {} - - # VectorStores may contain databse connections - # so we need to define the __reduce__ method and the __setstate__ method - # to avoid pickling errors - - def remove_docs_and_texts_from_params(self): - # remove documents and texts from params - # so that we don't try to pickle a database connection - self.params.pop("documents", None) - self.params.pop("texts", None) - - # def __getstate__(self): - # # We want to save the params attribute - # # and if "documents" or "texts" are in the params - # # we want to remove them because they have already - # # been processed. - # params = self.params.copy() - # params.pop("documents", None) - # params.pop("texts", None) - - # return super().__getstate__() - - def __setstate__(self, state): - super().__setstate__(state) - self.remove_docs_and_texts_from_params() - - -class MemoryVertex(Vertex): - def __init__(self, data: Dict, graph): - super().__init__(data, graph=graph, base_type="memory") - - -class RetrieverVertex(Vertex): - def __init__(self, data: Dict, graph): - super().__init__(data, graph=graph, base_type="retrievers") - - -class TextSplitterVertex(Vertex): - def __init__(self, data: Dict, graph, params: Optional[Dict] = None): - super().__init__(data, graph=graph, base_type="textsplitters", params=params) - - def _built_object_repr(self): - # This built_object is a list of documents. Maybe we should - # show how many documents are in the list? - - if self._built_object and not isinstance(self._built_object, UnbuiltObject): - avg_length = sum(len(doc.page_content) for doc in self._built_object) / len(self._built_object) - return f"""{self.vertex_type}({len(self._built_object)} documents) - \nAvg. Document Length (characters): {int(avg_length)} - \nDocuments: {self._built_object[:3]}...""" - return f"{self.vertex_type}()" - - -class ChainVertex(Vertex): - def __init__(self, data: Dict, graph): - super().__init__(data, graph=graph, base_type="chains") - - async def build( - self, - force: bool = False, - user_id=None, - *args, - **kwargs, - ) -> Any: - if not self._built or force: - # Temporarily remove the code from the params - self.params.pop("code", None) - # Check if the chain requires a PromptVertex - - # Temporarily remove "code" from the params - self.params.pop("code", None) - - for key, value in self.params.items(): - if isinstance(value, PromptVertex): - # Build the PromptVertex, passing the tools if available - tools = kwargs.get("tools", None) - self.params[key] = await value.build(tools=tools, force=force) - - await self._build(user_id=user_id) - - return self._built_object - - -class PromptVertex(Vertex): - def __init__(self, data: Dict, graph): - super().__init__(data, graph=graph, base_type="prompts") - - async def build( - self, - force: bool = False, - user_id=None, - tools: Optional[List[Union[ToolkitVertex, ToolVertex]]] = None, - *args, - **kwargs, - ) -> Any: - if not self._built or force: - if "input_variables" not in self.params or self.params["input_variables"] is None: - self.params["input_variables"] = [] - # Check if it is a ZeroShotPrompt and needs a tool - if "ShotPrompt" in self.vertex_type: - tools = [await tool_node.build(user_id=user_id) for tool_node in tools] if tools is not None else [] - # flatten the list of tools if it is a list of lists - # first check if it is a list - if tools and isinstance(tools, list) and isinstance(tools[0], list): - tools = flatten_list(tools) - self.params["tools"] = tools - prompt_params = [ - key for key, value in self.params.items() if isinstance(value, str) and key != "format_instructions" - ] - else: - prompt_params = ["template"] - - if "prompt" not in self.params and "messages" not in self.params: - for param in prompt_params: - prompt_text = self.params[param] - variables = extract_input_variables_from_prompt(prompt_text) - self.params["input_variables"].extend(variables) - self.params["input_variables"] = list(set(self.params["input_variables"])) - elif isinstance(self.params, dict): - self.params.pop("input_variables", None) - - await self._build(user_id=user_id) - return self._built_object - - def _built_object_repr(self): - if not self.artifacts or self._built_object is None or not hasattr(self._built_object, "format"): - return super()._built_object_repr() - # We'll build the prompt with the artifacts - # to show the user what the prompt looks like - # with the variables filled in - artifacts = self.artifacts.copy() - # Remove the handle_keys from the artifacts - # so the prompt format doesn't break - artifacts.pop("handle_keys", None) - try: - if ( - not hasattr(self._built_object, "template") - and hasattr(self._built_object, "prompt") - and not isinstance(self._built_object, UnbuiltObject) - ): - template = self._built_object.prompt.template - elif not isinstance(self._built_object, UnbuiltObject) and hasattr(self._built_object, "template"): - template = self._built_object.template - for key, value in artifacts.items(): - if value: - replace_key = "{" + key + "}" - template = template.replace(replace_key, value) - return template if isinstance(template, str) else f"{self.vertex_type}({template})" - except KeyError: - return str(self._built_object) - - -class OutputParserVertex(Vertex): - def __init__(self, data: Dict, graph): - super().__init__(data, graph=graph, base_type="output_parsers") - - -class CustomComponentVertex(Vertex): - def __init__(self, data: Dict, graph): - super().__init__(data, graph=graph, base_type="custom_components", is_task=False) - - def _built_object_repr(self): - if self.task_id and self.is_task: - if task := self.get_task(): - return str(task.info) - else: - return f"Task {self.task_id} is not running" - if self.artifacts and "repr" in self.artifacts: - return self.artifacts["repr"] or super()._built_object_repr() diff --git a/src/backend/langflow/graph/vertex/utils.py b/src/backend/langflow/graph/vertex/utils.py deleted file mode 100644 index e1d439f4b..000000000 --- a/src/backend/langflow/graph/vertex/utils.py +++ /dev/null @@ -1,5 +0,0 @@ -from langflow.utils.constants import PYTHON_BASIC_TYPES - - -def is_basic_type(obj): - return type(obj) in PYTHON_BASIC_TYPES diff --git a/src/backend/langflow/interface/custom/custom_component/custom_component.py b/src/backend/langflow/interface/custom/custom_component/custom_component.py deleted file mode 100644 index 3cc52438e..000000000 --- a/src/backend/langflow/interface/custom/custom_component/custom_component.py +++ /dev/null @@ -1,238 +0,0 @@ -import operator -from typing import Any, Callable, ClassVar, List, Optional, Union -from uuid import UUID - -import yaml -from cachetools import TTLCache, cachedmethod -from fastapi import HTTPException -from langflow.interface.custom.code_parser.utils import ( - extract_inner_type_from_generic_alias, - extract_union_types_from_generic_alias, -) -from langflow.interface.custom.custom_component.component import Component -from langflow.services.database.models.flow import Flow -from langflow.services.database.utils import session_getter -from langflow.services.deps import get_credential_service, get_db_service -from langflow.utils import validate - - -class CustomComponent(Component): - display_name: Optional[str] = None - """The display name of the component. Defaults to None.""" - description: Optional[str] = None - """The description of the component. Defaults to None.""" - icon: Optional[str] = None - """The icon of the component. It should be an emoji. Defaults to None.""" - code: Optional[str] = None - """The code of the component. Defaults to None.""" - field_config: dict = {} - """The field configuration of the component. Defaults to an empty dictionary.""" - field_order: Optional[List[str]] = None - """The field order of the component. Defaults to an empty list.""" - code_class_base_inheritance: ClassVar[str] = "CustomComponent" - function_entrypoint_name: ClassVar[str] = "build" - function: Optional[Callable] = None - repr_value: Optional[Any] = "" - user_id: Optional[Union[UUID, str]] = None - status: Optional[Any] = None - """The status of the component. This is displayed on the frontend. Defaults to None.""" - _tree: Optional[dict] = None - - def __init__(self, **data): - self.cache = TTLCache(maxsize=1024, ttl=60) - super().__init__(**data) - - def _get_field_order(self): - return self.field_order or list(self.field_config.keys()) - - def custom_repr(self): - if self.repr_value == "": - self.repr_value = self.status - if isinstance(self.repr_value, dict): - return yaml.dump(self.repr_value) - if isinstance(self.repr_value, str): - return self.repr_value - return str(self.repr_value) - - def build_config(self): - return self.field_config - - @property - def tree(self): - return self.get_code_tree(self.code or "") - - @property - def get_function_entrypoint_args(self) -> list: - build_method = self.get_build_method() - if not build_method: - return [] - - args = build_method["args"] - for arg in args: - if arg.get("type") == "prompt": - raise HTTPException( - status_code=400, - detail={ - "error": "Type hint Error", - "traceback": ( - "Prompt type is not supported in the build method." " Try using PromptTemplate instead." - ), - }, - ) - elif not arg.get("type") and arg.get("name") != "self": - # Set the type to Data - arg["type"] = "Data" - return args - - @cachedmethod(operator.attrgetter("cache")) - def get_build_method(self): - if not self.code: - return {} - - component_classes = [cls for cls in self.tree["classes"] if self.code_class_base_inheritance in cls["bases"]] - if not component_classes: - return {} - - # Assume the first Component class is the one we're interested in - component_class = component_classes[0] - build_methods = [ - method for method in component_class["methods"] if method["name"] == self.function_entrypoint_name - ] - - return build_methods[0] if build_methods else {} - - @property - def get_function_entrypoint_return_type(self) -> List[Any]: - build_method = self.get_build_method() - if not build_method or not build_method.get("has_return"): - return [] - return_type = build_method["return_type"] - - # If list or List is in the return type, then we remove it and return the inner type - if hasattr(return_type, "__origin__") and return_type.__origin__ in [list, List]: - return_type = extract_inner_type_from_generic_alias(return_type) - - # If the return type is not a Union, then we just return it as a list - if not hasattr(return_type, "__origin__") or return_type.__origin__ != Union: - return return_type if isinstance(return_type, list) else [return_type] - # If the return type is a Union, then we need to parse itx - return_type = extract_union_types_from_generic_alias(return_type) - return return_type - - @property - def get_main_class_name(self): - if not self.code: - return "" - - base_name = self.code_class_base_inheritance - method_name = self.function_entrypoint_name - - classes = [] - for item in self.tree.get("classes", []): - if base_name in item["bases"]: - method_names = [method["name"] for method in item["methods"]] - if method_name in method_names: - classes.append(item["name"]) - - # Get just the first item - return next(iter(classes), "") - - @property - def template_config(self): - return self.build_template_config() - - def build_template_config(self): - if not self.code: - return {} - - attributes = [ - main_class["attributes"] - for main_class in self.tree.get("classes", []) - if main_class["name"] == self.get_main_class_name - ] - # Get just the first item - attributes = next(iter(attributes), []) - - return super().build_template_config(attributes) - - @property - def keys(self): - def get_credential(name: str): - if hasattr(self, "_user_id") and not self._user_id: - raise ValueError(f"User id is not set for {self.__class__.__name__}") - credential_service = get_credential_service() # Get service instance - # Retrieve and decrypt the credential by name for the current user - db_service = get_db_service() - with session_getter(db_service) as session: - return credential_service.get_credential(user_id=self._user_id or "", name=name, session=session) - - return get_credential - - def list_key_names(self): - if hasattr(self, "_user_id") and not self._user_id: - raise ValueError(f"User id is not set for {self.__class__.__name__}") - credential_service = get_credential_service() - db_service = get_db_service() - with session_getter(db_service) as session: - return credential_service.list_credentials(user_id=self._user_id, session=session) - - def index(self, value: int = 0): - """Returns a function that returns the value at the given index in the iterable.""" - - def get_index(iterable: List[Any]): - return iterable[value] if iterable else iterable - - return get_index - - @property - def get_function(self): - return validate.create_function(self.code, self.function_entrypoint_name) - - async def load_flow(self, flow_id: str, tweaks: Optional[dict] = None) -> Any: - from langflow.processing.process import build_sorted_vertices, process_tweaks - - db_service = get_db_service() - with session_getter(db_service) as session: - graph_data = flow.data if (flow := session.get(Flow, flow_id)) else None - if not graph_data: - raise ValueError(f"Flow {flow_id} not found") - if tweaks: - graph_data = process_tweaks(graph_data=graph_data, tweaks=tweaks) - return await build_sorted_vertices(graph_data, self.user_id) - - def list_flows(self, *, get_session: Optional[Callable] = None) -> List[Flow]: - if not self._user_id: - raise ValueError("Session is invalid") - try: - get_session = get_session or session_getter - db_service = get_db_service() - with get_session(db_service) as session: - flows = session.query(Flow).filter(Flow.user_id == self.user_id).all() - return flows - except Exception as e: - raise ValueError("Session is invalid") from e - - async def get_flow( - self, - *, - flow_name: Optional[str] = None, - flow_id: Optional[str] = None, - tweaks: Optional[dict] = None, - get_session: Optional[Callable] = None, - ) -> Flow: - get_session = get_session or session_getter - db_service = get_db_service() - with get_session(db_service) as session: - if flow_id: - flow = session.query(Flow).get(flow_id) - elif flow_name: - flow = (session.query(Flow).filter(Flow.name == flow_name).filter(Flow.user_id == self.user_id)).first() - else: - raise ValueError("Either flow_name or flow_id must be provided") - - if not flow: - raise ValueError(f"Flow {flow_name or flow_id} not found") - return await self.load_flow(flow.id, tweaks) - - def build(self, *args: Any, **kwargs: Any) -> Any: - raise NotImplementedError diff --git a/src/backend/langflow/processing/load.py b/src/backend/langflow/processing/load.py deleted file mode 100644 index d564d101f..000000000 --- a/src/backend/langflow/processing/load.py +++ /dev/null @@ -1,52 +0,0 @@ -import asyncio -import json -from pathlib import Path -from typing import Optional, Union - -from langflow.graph import Graph -from langflow.processing.process import fix_memory_inputs, process_tweaks - - -def load_flow_from_json(flow: Union[Path, str, dict], tweaks: Optional[dict] = None, build=True): - """ - Load flow from a JSON file or a JSON object. - - :param flow: JSON file path or JSON object - :param tweaks: Optional tweaks to be processed - :param build: If True, build the graph, otherwise return the graph object - :return: Langchain object or Graph object depending on the build parameter - """ - # If input is a file path, load JSON from the file - if isinstance(flow, (str, Path)): - with open(flow, "r", encoding="utf-8") as f: - flow_graph = json.load(f) - # If input is a dictionary, assume it's a JSON object - elif isinstance(flow, dict): - flow_graph = flow - else: - raise TypeError("Input must be either a file path (str) or a JSON object (dict)") - - graph_data = flow_graph["data"] - if tweaks is not None: - graph_data = process_tweaks(graph_data, tweaks) - nodes = graph_data["nodes"] - edges = graph_data["edges"] - graph = Graph(nodes, edges) - - if build: - langchain_object = asyncio.run(graph.build()) - - if hasattr(langchain_object, "verbose"): - langchain_object.verbose = True - - if hasattr(langchain_object, "return_intermediate_steps"): - # Deactivating until we have a frontend solution - # to display intermediate steps - langchain_object.return_intermediate_steps = False - - fix_memory_inputs(langchain_object) - return langchain_object - - return graph - - return graph diff --git a/src/backend/langflow/processing/process.py b/src/backend/langflow/processing/process.py deleted file mode 100644 index 394fb1fde..000000000 --- a/src/backend/langflow/processing/process.py +++ /dev/null @@ -1,299 +0,0 @@ -import asyncio -from typing import Any, Coroutine, Dict, List, Optional, Tuple, Union - -from langchain.agents import AgentExecutor -from langchain.chains.base import Chain -from langchain.schema import AgentAction, Document -from langchain_community.vectorstores import VectorStore -from langchain_core.messages import AIMessage -from langchain_core.runnables.base import Runnable -from loguru import logger -from pydantic import BaseModel - -from langflow.graph.graph.base import Graph -from langflow.interface.run import build_sorted_vertices, get_memory_key, update_memory_keys -from langflow.services.deps import get_session_service -from langflow.services.session.service import SessionService - - -def fix_memory_inputs(langchain_object): - """ - Given a LangChain object, this function checks if it has a memory attribute and if that memory key exists in the - object's input variables. If so, it does nothing. Otherwise, it gets a possible new memory key using the - get_memory_key function and updates the memory keys using the update_memory_keys function. - """ - if not hasattr(langchain_object, "memory") or langchain_object.memory is None: - return - try: - if ( - hasattr(langchain_object.memory, "memory_key") - and langchain_object.memory.memory_key in langchain_object.input_variables - ): - return - except AttributeError: - input_variables = ( - langchain_object.prompt.input_variables - if hasattr(langchain_object, "prompt") - else langchain_object.input_keys - ) - if langchain_object.memory.memory_key in input_variables: - return - - possible_new_mem_key = get_memory_key(langchain_object) - if possible_new_mem_key is not None: - update_memory_keys(langchain_object, possible_new_mem_key) - - -def format_actions(actions: List[Tuple[AgentAction, str]]) -> str: - """Format a list of (AgentAction, answer) tuples into a string.""" - output = [] - for action, answer in actions: - log = action.log - tool = action.tool - tool_input = action.tool_input - output.append(f"Log: {log}") - if "Action" not in log and "Action Input" not in log: - output.append(f"Tool: {tool}") - output.append(f"Tool Input: {tool_input}") - output.append(f"Answer: {answer}") - output.append("") # Add a blank line - return "\n".join(output) - - -def get_result_and_thought(langchain_object: Any, inputs: dict): - """Get result and thought from extracted json""" - try: - if hasattr(langchain_object, "verbose"): - langchain_object.verbose = True - - if hasattr(langchain_object, "return_intermediate_steps"): - langchain_object.return_intermediate_steps = False - - try: - if not isinstance(langchain_object, AgentExecutor): - fix_memory_inputs(langchain_object) - except Exception as exc: - logger.error(f"Error fixing memory inputs: {exc}") - - try: - output = langchain_object(inputs, return_only_outputs=True) - except ValueError as exc: - # make the error message more informative - logger.debug(f"Error: {str(exc)}") - output = langchain_object.run(inputs) - - except Exception as exc: - raise ValueError(f"Error: {str(exc)}") from exc - return output - - -def get_input_str_if_only_one_input(inputs: dict) -> Optional[str]: - """Get input string if only one input is provided""" - return list(inputs.values())[0] if len(inputs) == 1 else None - - -def get_build_result(data_graph, session_id): - # If session_id is provided, load the langchain_object from the session - # using build_sorted_vertices_with_caching.get_result_by_session_id - # if it returns something different than None, return it - # otherwise, build the graph and return the result - if session_id: - logger.debug(f"Loading LangChain object from session {session_id}") - result = build_sorted_vertices(data_graph=data_graph) - if result is not None: - logger.debug("Loaded LangChain object") - return result - - logger.debug("Building langchain object") - return build_sorted_vertices(data_graph) - - -def process_inputs( - inputs: Optional[Union[dict, List[dict]]] = None, artifacts: Optional[Dict[str, Any]] = None -) -> Union[dict, List[dict]]: - if inputs is None: - inputs = {} - if artifacts is None: - artifacts = {} - - if isinstance(inputs, dict): - inputs = update_inputs_dict(inputs, artifacts) - elif isinstance(inputs, List): - inputs = [update_inputs_dict(inp, artifacts) for inp in inputs] - - return inputs - - -def update_inputs_dict(inputs: dict, artifacts: Dict[str, Any]) -> dict: - for key, value in artifacts.items(): - if key == "repr": - continue - elif key not in inputs or not inputs[key]: - inputs[key] = value - - return inputs - - -async def process_runnable(runnable: Runnable, inputs: Union[dict, List[dict]]): - if isinstance(inputs, List) and hasattr(runnable, "abatch"): - result = await runnable.abatch(inputs) - elif isinstance(inputs, dict) and hasattr(runnable, "ainvoke"): - result = await runnable.ainvoke(inputs) - else: - raise ValueError(f"Runnable {runnable} does not support inputs of type {type(inputs)}") - # Check if the result is a list of AIMessages - if isinstance(result, list) and all(isinstance(r, AIMessage) for r in result): - result = [r.content for r in result] - elif isinstance(result, AIMessage): - result = result.content - return result - - -async def process_inputs_dict(built_object: Union[Chain, VectorStore, Runnable], inputs: dict): - if isinstance(built_object, Chain): - if inputs is None: - raise ValueError("Inputs must be provided for a Chain") - logger.debug("Generating result and thought") - result = get_result_and_thought(built_object, inputs) - - logger.debug("Generated result and thought") - elif isinstance(built_object, VectorStore) and "query" in inputs: - if isinstance(inputs, dict) and "search_type" not in inputs: - inputs["search_type"] = "similarity" - logger.info("search_type not provided, using default value: similarity") - result = built_object.search(**inputs) - elif isinstance(built_object, Document): - result = built_object.dict() - elif isinstance(built_object, Runnable): - result = await process_runnable(built_object, inputs) - if isinstance(result, list): - result = [r.content if hasattr(r, "content") else r for r in result] - elif hasattr(result, "content"): - result = result.content - else: - result = result - else: - result = None - - return result - - -async def process_inputs_list(built_object: Runnable, inputs: List[dict]): - return await process_runnable(built_object, inputs) - - -async def generate_result(built_object: Union[Chain, VectorStore, Runnable], inputs: Union[dict, List[dict]]): - if isinstance(inputs, dict): - result = await process_inputs_dict(built_object, inputs) - elif isinstance(inputs, List) and isinstance(built_object, Runnable): - result = await process_inputs_list(built_object, inputs) - else: - raise ValueError(f"Invalid inputs type: {type(inputs)}") - - if result is None: - logger.warning(f"Unknown built_object type: {type(built_object)}") - if isinstance(built_object, Coroutine): - result = asyncio.run(built_object) - result = built_object - - return result - - -class Result(BaseModel): - result: Any - session_id: str - - -async def process_graph_cached( - data_graph: Dict[str, Any], - inputs: Optional[Union[dict, List[dict]]] = None, - clear_cache=False, - session_id=None, -) -> Result: - session_service = get_session_service() - if clear_cache: - session_service.clear_session(session_id) - if session_id is None: - session_id = session_service.generate_key(session_id=session_id, data_graph=data_graph) - # Load the graph using SessionService - session = await session_service.load_session(session_id, data_graph) - graph, artifacts = session if session else (None, None) - if not graph: - raise ValueError("Graph not found in the session") - - result = await build_graph_and_generate_result( - graph=graph, session_id=session_id, inputs=inputs, artifacts=artifacts, session_service=session_service - ) - - return result - - -async def build_graph_and_generate_result( - graph: "Graph", - session_id: str, - inputs: Optional[Union[dict, List[dict]]] = None, - artifacts: Optional[Dict[str, Any]] = None, - session_service: Optional[SessionService] = None, -): - """Build the graph and generate the result""" - built_object = await graph.build() - processed_inputs = process_inputs(inputs, artifacts or {}) - result = await generate_result(built_object, processed_inputs) - # langchain_object is now updated with the new memory - # we need to update the cache with the updated langchain_object - if session_id and session_service: - session_service.update_session(session_id, (graph, artifacts)) - return Result(result=result, session_id=session_id) - - -def validate_input(graph_data: Dict[str, Any], tweaks: Dict[str, Dict[str, Any]]) -> List[Dict[str, Any]]: - if not isinstance(graph_data, dict) or not isinstance(tweaks, dict): - raise ValueError("graph_data and tweaks should be dictionaries") - - nodes = graph_data.get("data", {}).get("nodes") or graph_data.get("nodes") - - if not isinstance(nodes, list): - raise ValueError("graph_data should contain a list of nodes under 'data' key or directly under 'nodes' key") - - return nodes - - -def apply_tweaks(node: Dict[str, Any], node_tweaks: Dict[str, Any]) -> None: - template_data = node.get("data", {}).get("node", {}).get("template") - - if not isinstance(template_data, dict): - logger.warning(f"Template data for node {node.get('id')} should be a dictionary") - return - - for tweak_name, tweak_value in node_tweaks.items(): - if tweak_name and tweak_value and tweak_name in template_data: - key = tweak_name if tweak_name == "file_path" else "value" - template_data[tweak_name][key] = tweak_value - - -def process_tweaks(graph_data: Dict[str, Any], tweaks: Dict[str, Dict[str, Any]]) -> Dict[str, Any]: - """ - This function is used to tweak the graph data using the node id and the tweaks dict. - - :param graph_data: The dictionary containing the graph data. It must contain a 'data' key with - 'nodes' as its child or directly contain 'nodes' key. Each node should have an 'id' and 'data'. - :param tweaks: A dictionary where the key is the node id and the value is a dictionary of the tweaks. - The inner dictionary contains the name of a certain parameter as the key and the value to be tweaked. - - :return: The modified graph_data dictionary. - - :raises ValueError: If the input is not in the expected format. - """ - nodes = validate_input(graph_data, tweaks) - - for node in nodes: - if isinstance(node, dict) and isinstance(node.get("id"), str): - node_id = node["id"] - if node_tweaks := tweaks.get(node_id): - apply_tweaks(node, node_tweaks) - else: - logger.warning("Each node should be a dictionary with an 'id' key of type str") - - return graph_data - return graph_data - return graph_data diff --git a/src/backend/langflow/services/base.py b/src/backend/langflow/services/base.py deleted file mode 100644 index 301771944..000000000 --- a/src/backend/langflow/services/base.py +++ /dev/null @@ -1,12 +0,0 @@ -from abc import ABC - - -class Service(ABC): - name: str - ready: bool = False - - def teardown(self): - pass - - def set_ready(self): - self.ready = True diff --git a/src/backend/langflow/services/cache/__init__.py b/src/backend/langflow/services/cache/__init__.py deleted file mode 100644 index bf3a7c5ee..000000000 --- a/src/backend/langflow/services/cache/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -from . import factory, service -from langflow.services.cache.service import InMemoryCache - - -__all__ = [ - "factory", - "service", - "InMemoryCache", -] diff --git a/src/backend/langflow/services/cache/base.py b/src/backend/langflow/services/cache/base.py deleted file mode 100644 index 3b34e12f6..000000000 --- a/src/backend/langflow/services/cache/base.py +++ /dev/null @@ -1,98 +0,0 @@ -import abc - -from langflow.services.base import Service - - -class BaseCacheService(Service): - """ - Abstract base class for a cache. - """ - - name = "cache_service" - - @abc.abstractmethod - def get(self, key): - """ - Retrieve an item from the cache. - - Args: - key: The key of the item to retrieve. - - Returns: - The value associated with the key, or None if the key is not found. - """ - - @abc.abstractmethod - def set(self, key, value): - """ - Add an item to the cache. - - Args: - key: The key of the item. - value: The value to cache. - """ - - @abc.abstractmethod - def upsert(self, key, value): - """ - Add an item to the cache if it doesn't exist, or update it if it does. - - Args: - key: The key of the item. - value: The value to cache. - """ - - @abc.abstractmethod - def delete(self, key): - """ - Remove an item from the cache. - - Args: - key: The key of the item to remove. - """ - - @abc.abstractmethod - def clear(self): - """ - Clear all items from the cache. - """ - - @abc.abstractmethod - def __contains__(self, key): - """ - Check if the key is in the cache. - - Args: - key: The key of the item to check. - - Returns: - True if the key is in the cache, False otherwise. - """ - - @abc.abstractmethod - def __getitem__(self, key): - """ - Retrieve an item from the cache using the square bracket notation. - - Args: - key: The key of the item to retrieve. - """ - - @abc.abstractmethod - def __setitem__(self, key, value): - """ - Add an item to the cache using the square bracket notation. - - Args: - key: The key of the item. - value: The value to cache. - """ - - @abc.abstractmethod - def __delitem__(self, key): - """ - Remove an item from the cache using the square bracket notation. - - Args: - key: The key of the item to remove. - """ diff --git a/src/backend/langflow/services/chat/service.py b/src/backend/langflow/services/chat/service.py deleted file mode 100644 index 91fe98845..000000000 --- a/src/backend/langflow/services/chat/service.py +++ /dev/null @@ -1,260 +0,0 @@ -import asyncio -import uuid -from collections import defaultdict -from typing import Any, Dict, List - -import orjson -from fastapi import WebSocket, status -from loguru import logger -from starlette.websockets import WebSocketState - -from langflow.api.v1.schemas import ChatMessage, ChatResponse, FileResponse -from langflow.interface.utils import pil_to_base64 -from langflow.services import ServiceType, service_manager -from langflow.services.base import Service -from langflow.services.chat.cache import Subject -from langflow.services.chat.utils import process_graph - -from .cache import cache_service - - -class ChatHistory(Subject): - def __init__(self): - super().__init__() - self.history: Dict[str, List[ChatMessage]] = defaultdict(list) - - def add_message(self, client_id: str, message: ChatMessage): - """Add a message to the chat history.""" - - self.history[client_id].append(message) - - if not isinstance(message, FileResponse): - self.notify() - - def get_history(self, client_id: str, filter_messages=True) -> List[ChatMessage]: - """Get the chat history for a client.""" - if history := self.history.get(client_id, []): - if filter_messages: - return [msg for msg in history if msg.type not in ["start", "stream"]] - return history - else: - return [] - - def empty_history(self, client_id: str): - """Empty the chat history for a client.""" - self.history[client_id] = [] - - -class ChatService(Service): - name = "chat_service" - - def __init__(self): - self.active_connections: Dict[str, WebSocket] = {} - self.connection_ids: Dict[str, str] = {} - self.chat_history = ChatHistory() - self.chat_cache = cache_service - self.chat_cache.attach(self.update) - self.cache_service = service_manager.get(ServiceType.CACHE_SERVICE) - - def on_chat_history_update(self): - """Send the last chat message to the client.""" - client_id = self.chat_cache.current_client_id - if client_id in self.active_connections: - chat_response = self.chat_history.get_history(client_id, filter_messages=False)[-1] - if chat_response.is_bot: - # Process FileResponse - if isinstance(chat_response, FileResponse): - # If data_type is pandas, convert to csv - if chat_response.data_type == "pandas": - chat_response.data = chat_response.data.to_csv() - elif chat_response.data_type == "image": - # Base64 encode the image - chat_response.data = pil_to_base64(chat_response.data) - # get event loop - loop = asyncio.get_event_loop() - - coroutine = self.send_json(client_id, chat_response) - asyncio.run_coroutine_threadsafe(coroutine, loop) - - def update(self): - if self.chat_cache.current_client_id in self.active_connections: - self.last_cached_object_dict = self.chat_cache.get_last() - # Add a new ChatResponse with the data - chat_response = FileResponse( - message=None, - type="file", - data=self.last_cached_object_dict["obj"], - data_type=self.last_cached_object_dict["type"], - ) - - self.chat_history.add_message(self.chat_cache.current_client_id, chat_response) - - async def connect(self, client_id: str, websocket: WebSocket): - self.active_connections[client_id] = websocket - # This is to avoid having multiple clients with the same id - #! Temporary solution - self.connection_ids[client_id] = f"{client_id}-{uuid.uuid4()}" - - def disconnect(self, client_id: str): - self.active_connections.pop(client_id, None) - self.connection_ids.pop(client_id, None) - - async def send_message(self, client_id: str, message: str): - websocket = self.active_connections[client_id] - await websocket.send_text(message) - - async def send_json(self, client_id: str, message: ChatMessage): - websocket = self.active_connections[client_id] - await websocket.send_json(message.model_dump()) - - async def close_connection(self, client_id: str, code: int, reason: str): - if websocket := self.active_connections[client_id]: - try: - await websocket.close(code=code, reason=reason) - self.disconnect(client_id) - except RuntimeError as exc: - # This is to catch the following error: - # Unexpected ASGI message 'websocket.close', after sending 'websocket.close' - if "after sending" in str(exc): - logger.error(f"Error closing connection: {exc}") - - async def process_message(self, client_id: str, payload: Dict, build_result: Any): - # Process the graph data and chat message - chat_inputs = payload.pop("inputs", {}) - chatkey = payload.pop("chatKey", None) - chat_inputs = ChatMessage(message=chat_inputs, chatKey=chatkey) - self.chat_history.add_message(client_id, chat_inputs) - - # graph_data = payload - start_resp = ChatResponse(message=None, type="start", intermediate_steps="") - await self.send_json(client_id, start_resp) - - # is_first_message = len(self.chat_history.get_history(client_id=client_id)) <= 1 - # Generate result and thought - try: - logger.debug("Generating result and thought") - - result, intermediate_steps, raw_output = await process_graph( - build_result=build_result, - chat_inputs=chat_inputs, - client_id=client_id, - session_id=self.connection_ids[client_id], - ) - self.set_cache(client_id, build_result) - except Exception as e: - # Log stack trace - logger.exception(e) - self.chat_history.empty_history(client_id) - raise e - # Send a response back to the frontend, if needed - intermediate_steps = intermediate_steps or "" - history = self.chat_history.get_history(client_id, filter_messages=False) - file_responses = [] - if history: - # Iterate backwards through the history - for msg in reversed(history): - if isinstance(msg, FileResponse): - if msg.data_type == "image": - # Base64 encode the image - if isinstance(msg.data, str): - continue - msg.data = pil_to_base64(msg.data) - file_responses.append(msg) - if msg.type == "start": - break - - response = ChatResponse( - message=result, - intermediate_steps=intermediate_steps.strip(), - type="end", - files=file_responses, - ) - await self.send_json(client_id, response) - self.chat_history.add_message(client_id, response) - - def set_cache(self, client_id: str, langchain_object: Any) -> bool: - """ - Set the cache for a client. - """ - # client_id is the flow id but that already exists in the cache - # so we need to change it to something else - - result_dict = { - "result": langchain_object, - "type": type(langchain_object), - } - self.cache_service.upsert(client_id, result_dict) - return client_id in self.cache_service - - async def handle_websocket(self, client_id: str, websocket: WebSocket): - await self.connect(client_id, websocket) - - try: - chat_history = self.chat_history.get_history(client_id) - # iterate and make BaseModel into dict - chat_history = [chat.model_dump() for chat in chat_history] - await websocket.send_json(chat_history) - - while True: - json_payload = await websocket.receive_json() - if isinstance(json_payload, str): - payload = orjson.loads(json_payload) - elif isinstance(json_payload, dict): - payload = json_payload - if "clear_history" in payload and payload["clear_history"]: - self.chat_history.history[client_id] = [] - continue - - with self.chat_cache.set_client_id(client_id): - if build_result := self.cache_service.get(client_id).get("result"): - await self.process_message(client_id, payload, build_result) - - else: - raise RuntimeError(f"Could not find a build result for client_id {client_id}") - except Exception as exc: - # Handle any exceptions that might occur - logger.exception(f"Error handling websocket: {exc}") - if websocket.client_state == WebSocketState.CONNECTED: - await self.close_connection( - client_id=client_id, - code=status.WS_1011_INTERNAL_ERROR, - reason=str(exc), - ) - elif websocket.client_state == WebSocketState.DISCONNECTED: - self.disconnect(client_id) - - finally: - try: - # first check if the connection is still open - if websocket.client_state == WebSocketState.CONNECTED: - await self.close_connection( - client_id=client_id, - code=status.WS_1000_NORMAL_CLOSURE, - reason="Client disconnected", - ) - except Exception as exc: - logger.error(f"Error closing connection: {exc}") - self.disconnect(client_id) - - -def dict_to_markdown_table(my_dict): - markdown_table = "| Key | Value |\n|---|---|\n" - for key, value in my_dict.items(): - markdown_table += f"| {key} | {value} |\n" - return markdown_table - - -def list_of_dicts_to_markdown_table(dict_list): - if not dict_list: - return "No data provided." - - # Extract headers from the keys of the first dictionary - headers = dict_list[0].keys() - markdown_table = "| " + " | ".join(headers) + " |\n" - markdown_table += "| " + " | ".join("---" for _ in headers) + " |\n" - - for row_dict in dict_list: - row = [str(row_dict.get(header, "")) for header in headers] - markdown_table += "| " + " | ".join(row) + " |\n" - - return markdown_table diff --git a/src/backend/langflow/services/credentials/service.py b/src/backend/langflow/services/credentials/service.py deleted file mode 100644 index 08e04fdaa..000000000 --- a/src/backend/langflow/services/credentials/service.py +++ /dev/null @@ -1,37 +0,0 @@ -from typing import TYPE_CHECKING, Optional, Union -from uuid import UUID - -from fastapi import Depends -from langflow.services.auth import utils as auth_utils -from langflow.services.base import Service -from langflow.services.database.models.credential.model import Credential -from langflow.services.deps import get_session -from sqlmodel import Session, select - -if TYPE_CHECKING: - from langflow.services.settings.service import SettingsService - - -class CredentialService(Service): - name = "credential_service" - - def __init__(self, settings_service: "SettingsService"): - self.settings_service = settings_service - - def get_credential(self, user_id: Union[UUID, str], name: str, session: Session = Depends(get_session)) -> str: - # we get the credential from the database - # credential = session.query(Credential).filter(Credential.user_id == user_id, Credential.name == name).first() - credential = session.exec( - select(Credential).where(Credential.user_id == user_id, Credential.name == name) - ).first() - # we decrypt the value - if not credential or not credential.value: - raise ValueError(f"{name} credential not found.") - decrypted = auth_utils.decrypt_api_key(credential.value, settings_service=self.settings_service) - return decrypted - - def list_credentials( - self, user_id: Union[UUID, str], session: Session = Depends(get_session) - ) -> list[Optional[str]]: - credentials = session.exec(select(Credential).where(Credential.user_id == user_id)).all() - return [credential.name for credential in credentials] diff --git a/src/backend/langflow/services/database/models/__init__.py b/src/backend/langflow/services/database/models/__init__.py deleted file mode 100644 index 9dd3e0285..000000000 --- a/src/backend/langflow/services/database/models/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -from .api_key import ApiKey -from .credential import Credential -from .flow import Flow -from .user import User - -__all__ = ["Flow", "User", "ApiKey", "Credential"] diff --git a/src/backend/langflow/services/database/models/component/__init__.py b/src/backend/langflow/services/database/models/component/__init__.py deleted file mode 100644 index c5ad7d47f..000000000 --- a/src/backend/langflow/services/database/models/component/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .model import Component, ComponentModel - -__all__ = ["Component", "ComponentModel"] diff --git a/src/backend/langflow/services/database/models/component/model.py b/src/backend/langflow/services/database/models/component/model.py deleted file mode 100644 index 0a5afc440..000000000 --- a/src/backend/langflow/services/database/models/component/model.py +++ /dev/null @@ -1,29 +0,0 @@ -import uuid -from datetime import datetime -from typing import Optional - -from sqlmodel import Field, SQLModel - - -class Component(SQLModel, table=True): - id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True) - frontend_node_id: uuid.UUID = Field(index=True) - name: str = Field(index=True) - description: Optional[str] = Field(default=None) - python_code: Optional[str] = Field(default=None) - return_type: Optional[str] = Field(default=None) - is_disabled: bool = Field(default=False) - is_read_only: bool = Field(default=False) - create_at: datetime = Field(default_factory=datetime.utcnow) - update_at: datetime = Field(default_factory=datetime.utcnow) - - -class ComponentModel(SQLModel): - id: uuid.UUID = Field(default_factory=uuid.uuid4) - frontend_node_id: uuid.UUID = Field(default=uuid.uuid4()) - name: str = Field(default="") - description: Optional[str] = None - python_code: Optional[str] = None - return_type: Optional[str] = None - is_disabled: bool = False - is_read_only: bool = False diff --git a/src/backend/langflow/services/database/models/credential/__init__.py b/src/backend/langflow/services/database/models/credential/__init__.py deleted file mode 100644 index 2f8b6cd01..000000000 --- a/src/backend/langflow/services/database/models/credential/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .model import Credential, CredentialCreate, CredentialRead, CredentialUpdate - -__all__ = ["Credential", "CredentialCreate", "CredentialRead", "CredentialUpdate"] diff --git a/src/backend/langflow/services/database/models/credential/model.py b/src/backend/langflow/services/database/models/credential/model.py deleted file mode 100644 index 95bd4b829..000000000 --- a/src/backend/langflow/services/database/models/credential/model.py +++ /dev/null @@ -1,43 +0,0 @@ -from datetime import datetime -from typing import TYPE_CHECKING, Optional -from uuid import UUID, uuid4 - -from sqlmodel import Field, Relationship, SQLModel - -from langflow.services.database.models.credential.schema import CredentialType - -if TYPE_CHECKING: - from langflow.services.database.models.user import User - - -class CredentialBase(SQLModel): - name: Optional[str] = Field(None, description="Name of the credential") - value: Optional[str] = Field(None, description="Encrypted value of the credential") - provider: Optional[str] = Field(None, description="Provider of the credential (e.g OpenAI)") - - -class Credential(CredentialBase, table=True): - id: Optional[UUID] = Field(default_factory=uuid4, primary_key=True, description="Unique ID for the credential") - # name is unique per user - created_at: datetime = Field(default_factory=datetime.utcnow, description="Creation time of the credential") - updated_at: Optional[datetime] = Field(None, description="Last update time of the credential") - # foreign key to user table - user_id: UUID = Field(description="User ID associated with this credential", foreign_key="user.id") - user: "User" = Relationship(back_populates="credentials") - - -class CredentialCreate(CredentialBase): - # AcceptedProviders is a custom Enum - provider: CredentialType = Field(description="Provider of the credential (e.g OpenAI)") - - -class CredentialRead(SQLModel): - id: UUID - name: Optional[str] = Field(None, description="Name of the credential") - provider: Optional[str] = Field(None, description="Provider of the credential (e.g OpenAI)") - - -class CredentialUpdate(SQLModel): - id: UUID # Include the ID for updating - name: Optional[str] = Field(None, description="Name of the credential") - value: Optional[str] = Field(None, description="Encrypted value of the credential") diff --git a/src/backend/langflow/services/database/models/credential/schema.py b/src/backend/langflow/services/database/models/credential/schema.py deleted file mode 100644 index 985915340..000000000 --- a/src/backend/langflow/services/database/models/credential/schema.py +++ /dev/null @@ -1,8 +0,0 @@ -from enum import Enum - - -class CredentialType(str, Enum): - """CredentialType is an Enum of the accepted providers""" - - OPENAI_API_KEY = "OPENAI_API_KEY" - ANTHROPIC_API_KEY = "ANTHROPIC_API_KEY" diff --git a/src/backend/langflow/services/database/models/flow/model.py b/src/backend/langflow/services/database/models/flow/model.py deleted file mode 100644 index d942fa93c..000000000 --- a/src/backend/langflow/services/database/models/flow/model.py +++ /dev/null @@ -1,73 +0,0 @@ -# Path: src/backend/langflow/database/models/flow.py - -from datetime import datetime -from typing import TYPE_CHECKING, Dict, Optional -from uuid import UUID, uuid4 - -from pydantic import field_serializer, field_validator -from sqlmodel import JSON, Column, Field, Relationship, SQLModel - -if TYPE_CHECKING: - from langflow.services.database.models.user import User - - -class FlowBase(SQLModel): - name: str = Field(index=True) - description: Optional[str] = Field(index=True, nullable=True, default=None) - data: Optional[Dict] = Field(default=None, nullable=True) - is_component: Optional[bool] = Field(default=False, nullable=True) - updated_at: Optional[datetime] = Field(default_factory=datetime.utcnow, nullable=True) - folder: Optional[str] = Field(default=None, nullable=True) - - @field_validator("data") - def validate_json(v): - if not v: - return v - if not isinstance(v, dict): - raise ValueError("Flow must be a valid JSON") - - # data must contain nodes and edges - if "nodes" not in v.keys(): - raise ValueError("Flow must have nodes") - if "edges" not in v.keys(): - raise ValueError("Flow must have edges") - - return v - - # updated_at can be serialized to JSON - @field_serializer("updated_at") - def serialize_dt(self, dt: datetime, _info): - if dt is None: - return None - return dt.isoformat() - - @field_validator("updated_at", mode="before") - def validate_dt(cls, v): - if v is None: - return v - elif isinstance(v, datetime): - return v - - return datetime.fromisoformat(v) - - -class Flow(FlowBase, table=True): - id: UUID = Field(default_factory=uuid4, primary_key=True, unique=True) - data: Optional[Dict] = Field(default=None, sa_column=Column(JSON)) - user_id: UUID = Field(index=True, foreign_key="user.id", nullable=True) - user: "User" = Relationship(back_populates="flows") - - -class FlowCreate(FlowBase): - user_id: Optional[UUID] = None - - -class FlowRead(FlowBase): - id: UUID - user_id: UUID = Field() - - -class FlowUpdate(SQLModel): - name: Optional[str] = None - description: Optional[str] = None - data: Optional[Dict] = None diff --git a/src/backend/langflow/services/deps.py b/src/backend/langflow/services/deps.py deleted file mode 100644 index 1ac06738b..000000000 --- a/src/backend/langflow/services/deps.py +++ /dev/null @@ -1,63 +0,0 @@ -from typing import TYPE_CHECKING, Generator - -from langflow.services import ServiceType, service_manager - -if TYPE_CHECKING: - from langflow.services.cache.service import BaseCacheService - from langflow.services.chat.service import ChatService - from langflow.services.credentials.service import CredentialService - from langflow.services.database.service import DatabaseService - from langflow.services.plugins.service import PluginService - from langflow.services.session.service import SessionService - from langflow.services.settings.service import SettingsService - from langflow.services.store.service import StoreService - from langflow.services.task.service import TaskService - from sqlmodel import Session - - -def get_credential_service() -> "CredentialService": - return service_manager.get(ServiceType.CREDENTIAL_SERVICE) # type: ignore - - -def get_plugins_service() -> "PluginService": - return service_manager.get(ServiceType.PLUGIN_SERVICE) # type: ignore - - -def get_settings_service() -> "SettingsService": - try: - return service_manager.get(ServiceType.SETTINGS_SERVICE) # type: ignore - except ValueError: - # initialize settings service - from langflow.services.manager import initialize_settings_service - - initialize_settings_service() - return service_manager.get(ServiceType.SETTINGS_SERVICE) # type: ignore - - -def get_db_service() -> "DatabaseService": - return service_manager.get(ServiceType.DATABASE_SERVICE) # type: ignore - - -def get_session() -> Generator["Session", None, None]: - db_service = get_db_service() - yield from db_service.get_session() - - -def get_cache_service() -> "BaseCacheService": - return service_manager.get(ServiceType.CACHE_SERVICE) # type: ignore - - -def get_session_service() -> "SessionService": - return service_manager.get(ServiceType.SESSION_SERVICE) # type: ignore - - -def get_task_service() -> "TaskService": - return service_manager.get(ServiceType.TASK_SERVICE) # type: ignore - - -def get_chat_service() -> "ChatService": - return service_manager.get(ServiceType.CHAT_SERVICE) # type: ignore - - -def get_store_service() -> "StoreService": - return service_manager.get(ServiceType.STORE_SERVICE) # type: ignore diff --git a/src/backend/langflow/services/factory.py b/src/backend/langflow/services/factory.py deleted file mode 100644 index 874d7374c..000000000 --- a/src/backend/langflow/services/factory.py +++ /dev/null @@ -1,12 +0,0 @@ -from typing import TYPE_CHECKING - -if TYPE_CHECKING: - from langflow.services.base import Service - - -class ServiceFactory: - def __init__(self, service_class): - self.service_class = service_class - - def create(self, *args, **kwargs) -> "Service": - raise NotImplementedError diff --git a/src/backend/langflow/utils/types.py b/src/backend/langflow/utils/types.py deleted file mode 100644 index 3657d550e..000000000 --- a/src/backend/langflow/utils/types.py +++ /dev/null @@ -1,2 +0,0 @@ -class Prompt: - pass diff --git a/src/backend/langflow/version/__init__.py b/src/backend/langflow/version/__init__.py new file mode 100644 index 000000000..5c0cf285c --- /dev/null +++ b/src/backend/langflow/version/__init__.py @@ -0,0 +1 @@ +from .version import __version__ # noqa: F401 diff --git a/src/backend/langflow/version/version.py b/src/backend/langflow/version/version.py new file mode 100644 index 000000000..540b465f9 --- /dev/null +++ b/src/backend/langflow/version/version.py @@ -0,0 +1,7 @@ +from importlib import metadata + +try: + __version__ = metadata.version("langflow") +except metadata.PackageNotFoundError: + __version__ = "" +del metadata diff --git a/src/backend/langflow/worker.py b/src/backend/langflow/worker.py deleted file mode 100644 index b3872bcd8..000000000 --- a/src/backend/langflow/worker.py +++ /dev/null @@ -1,75 +0,0 @@ -from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union - -from asgiref.sync import async_to_sync -from celery.exceptions import SoftTimeLimitExceeded # type: ignore -from langflow.core.celery_app import celery_app -from langflow.processing.process import Result, generate_result, process_inputs -from langflow.services.deps import get_session_service -from langflow.services.manager import initialize_session_service -from loguru import logger -from rich import print - -if TYPE_CHECKING: - from langflow.graph.vertex.base import Vertex - - -@celery_app.task(acks_late=True) -def test_celery(word: str) -> str: - return f"test task return {word}" - - -@celery_app.task(bind=True, soft_time_limit=30, max_retries=3) -def build_vertex(self, vertex: "Vertex") -> "Vertex": - """ - Build a vertex - """ - try: - vertex.task_id = self.request.id - async_to_sync(vertex.build)() - return vertex - except SoftTimeLimitExceeded as e: - raise self.retry(exc=SoftTimeLimitExceeded("Task took too long"), countdown=2) from e - - -@celery_app.task(acks_late=True) -def process_graph_cached_task( - data_graph: Dict[str, Any], - inputs: Optional[Union[dict, List[dict]]] = None, - clear_cache=False, - session_id=None, -) -> Dict[str, Any]: - try: - initialize_session_service() - session_service = get_session_service() - - if clear_cache: - session_service.clear_session(session_id) - - if session_id is None: - session_id = session_service.generate_key(session_id=session_id, data_graph=data_graph) - - # Use async_to_sync to handle the asynchronous part of the session service - session_data = async_to_sync(session_service.load_session, force_new_loop=True)(session_id, data_graph) - logger.warning(f"session_data: {session_data}") - graph, artifacts = session_data if session_data else (None, None) - - if not graph: - raise ValueError("Graph not found in the session") - - # Use async_to_sync for the asynchronous build method - built_object = async_to_sync(graph.build, force_new_loop=True)() - - logger.debug(f"Built object: {built_object}") - - processed_inputs = process_inputs(inputs, artifacts or {}) - result = async_to_sync(generate_result, force_new_loop=True)(built_object, processed_inputs) - - # Update the session with the new data - session_service.update_session(session_id, (graph, artifacts)) - result_object = Result(result=result, session_id=session_id).model_dump() - print(f"Result object: {result_object}") - return result_object - except Exception as e: - logger.error(f"Error in process_graph_cached_task: {e}") - # Handle the exception as needed, maybe re-raise or return an error message - raise diff --git a/src/frontend/.eslintrc.json b/src/frontend/.eslintrc.json new file mode 100644 index 000000000..682c7fc87 --- /dev/null +++ b/src/frontend/.eslintrc.json @@ -0,0 +1,29 @@ +{ + "extends": ["eslint:recommended", "plugin:node/recommended"], + "parserOptions": { + "ecmaVersion": 2018 + }, + "rules": { + "no-console": "warn", + "no-self-assign": "warn", + "no-self-compare": "warn", + "complexity": ["error", { "max": 15 }], + "indent": ["error", 2, { "SwitchCase": 1 }], + "no-dupe-keys": "error", + "no-invalid-regexp": "error", + "no-undef": "error", + "no-return-assign": "error", + "no-redeclare": "error", + "no-empty": "error", + "no-await-in-loop": "error", + "node/exports-style": ["error", "module.exports"], + "node/file-extension-in-import": ["error", "always"], + "node/prefer-global/buffer": ["error", "always"], + "node/prefer-global/console": ["error", "always"], + "node/prefer-global/process": ["error", "always"], + "node/prefer-global/url-search-params": ["error", "always"], + "node/prefer-global/url": ["error", "always"], + "node/prefer-promises/dns": "error", + "node/prefer-promises/fs": "error" + } +} diff --git a/src/frontend/.github/workflows/playwright.yml b/src/frontend/.github/workflows/playwright.yml deleted file mode 100644 index 90b6b700d..000000000 --- a/src/frontend/.github/workflows/playwright.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Playwright Tests -on: - push: - branches: [ main, master ] - pull_request: - branches: [ main, master ] -jobs: - test: - timeout-minutes: 60 - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: 18 - - name: Install dependencies - run: npm ci - - name: Install Playwright Browsers - run: npx playwright install --with-deps - - name: Run Playwright tests - run: npx playwright test - - uses: actions/upload-artifact@v3 - if: always() - with: - name: playwright-report - path: playwright-report/ - retention-days: 30 diff --git a/src/frontend/.gitignore b/src/frontend/.gitignore index 9dfae2bb0..a6dee659a 100644 --- a/src/frontend/.gitignore +++ b/src/frontend/.gitignore @@ -24,3 +24,7 @@ yarn-error.log* /test-results/ /playwright-report/*/ /playwright/.cache/ +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/src/frontend/harFiles/backend_12112023.har b/src/frontend/harFiles/backend_12112023.har deleted file mode 100644 index 63dbde94a..000000000 --- a/src/frontend/harFiles/backend_12112023.har +++ /dev/null @@ -1,599 +0,0 @@ -{ - "log": { - "version": "1.2", - "creator": { - "name": "Playwright", - "version": "1.39.0" - }, - "browser": { - "name": "chromium", - "version": "119.0.6045.9" - }, - "entries": [ - { - "startedDateTime": "2023-12-11T18:54:58.349Z", - "time": 1.142, - "request": { - "method": "GET", - "url": "http://localhost:3000/api/v1/store/check/", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Accept", "value": "application/json, text/plain, */*" }, - { "name": "Accept-Encoding", "value": "gzip, deflate, br" }, - { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, - { "name": "Connection", "value": "keep-alive" }, - { "name": "Host", "value": "localhost:3000" }, - { "name": "Referer", "value": "http://localhost:3000/" }, - { "name": "Sec-Fetch-Dest", "value": "empty" }, - { "name": "Sec-Fetch-Mode", "value": "cors" }, - { "name": "Sec-Fetch-Site", "value": "same-origin" }, - { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" }, - { "name": "sec-ch-ua", "value": "\"Chromium\";v=\"119\", \"Not?A_Brand\";v=\"24\"" }, - { "name": "sec-ch-ua-mobile", "value": "?0" }, - { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } - ], - "queryString": [], - "headersSize": -1, - "bodySize": -1 - }, - "response": { - "status": 200, - "statusText": "OK", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Access-Control-Allow-Origin", "value": "*" }, - { "name": "connection", "value": "close" }, - { "name": "content-length", "value": "16" }, - { "name": "content-type", "value": "application/json" }, - { "name": "date", "value": "Mon, 11 Dec 2023 18:54:57 GMT" }, - { "name": "server", "value": "uvicorn" } - ], - "content": { - "size": -1, - "mimeType": "application/json", - "text": "{\"enabled\":true}" - }, - "headersSize": -1, - "bodySize": -1, - "redirectURL": "" - }, - "cache": {}, - "timings": { "send": -1, "wait": -1, "receive": 1.142 } - }, - { - "startedDateTime": "2023-12-11T18:54:58.349Z", - "time": 0.484, - "request": { - "method": "GET", - "url": "http://localhost:3000/api/v1/store/check/api_key", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Accept", "value": "application/json, text/plain, */*" }, - { "name": "Accept-Encoding", "value": "gzip, deflate, br" }, - { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, - { "name": "Connection", "value": "keep-alive" }, - { "name": "Host", "value": "localhost:3000" }, - { "name": "Referer", "value": "http://localhost:3000/" }, - { "name": "Sec-Fetch-Dest", "value": "empty" }, - { "name": "Sec-Fetch-Mode", "value": "cors" }, - { "name": "Sec-Fetch-Site", "value": "same-origin" }, - { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" }, - { "name": "sec-ch-ua", "value": "\"Chromium\";v=\"119\", \"Not?A_Brand\";v=\"24\"" }, - { "name": "sec-ch-ua-mobile", "value": "?0" }, - { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } - ], - "queryString": [], - "headersSize": -1, - "bodySize": -1 - }, - "response": { - "status": 403, - "statusText": "Forbidden", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Access-Control-Allow-Origin", "value": "*" }, - { "name": "connection", "value": "close" }, - { "name": "content-length", "value": "73" }, - { "name": "content-type", "value": "application/json" }, - { "name": "date", "value": "Mon, 11 Dec 2023 18:54:57 GMT" }, - { "name": "server", "value": "uvicorn" } - ], - "content": { - "size": -1, - "mimeType": "application/json", - "text": "{\"detail\":\"An API key as query or header, or a JWT token must be passed\"}" - }, - "headersSize": -1, - "bodySize": -1, - "redirectURL": "" - }, - "cache": {}, - "timings": { "send": -1, "wait": -1, "receive": 0.484 } - }, - { - "startedDateTime": "2023-12-11T18:54:58.349Z", - "time": 0.476, - "request": { - "method": "GET", - "url": "http://localhost:3000/api/v1/version", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Accept", "value": "application/json, text/plain, */*" }, - { "name": "Accept-Encoding", "value": "gzip, deflate, br" }, - { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, - { "name": "Connection", "value": "keep-alive" }, - { "name": "Host", "value": "localhost:3000" }, - { "name": "Referer", "value": "http://localhost:3000/" }, - { "name": "Sec-Fetch-Dest", "value": "empty" }, - { "name": "Sec-Fetch-Mode", "value": "cors" }, - { "name": "Sec-Fetch-Site", "value": "same-origin" }, - { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" }, - { "name": "sec-ch-ua", "value": "\"Chromium\";v=\"119\", \"Not?A_Brand\";v=\"24\"" }, - { "name": "sec-ch-ua-mobile", "value": "?0" }, - { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } - ], - "queryString": [], - "headersSize": -1, - "bodySize": -1 - }, - "response": { - "status": 200, - "statusText": "OK", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Access-Control-Allow-Origin", "value": "*" }, - { "name": "connection", "value": "close" }, - { "name": "content-length", "value": "22" }, - { "name": "content-type", "value": "application/json" }, - { "name": "date", "value": "Mon, 11 Dec 2023 18:54:57 GMT" }, - { "name": "server", "value": "uvicorn" } - ], - "content": { - "size": -1, - "mimeType": "application/json", - "text": "{\"version\":\"0.6.0rc1\"}" - }, - "headersSize": -1, - "bodySize": -1, - "redirectURL": "" - }, - "cache": {}, - "timings": { "send": -1, "wait": -1, "receive": 0.476 } - }, - { - "startedDateTime": "2023-12-11T18:54:58.349Z", - "time": 0.59, - "request": { - "method": "GET", - "url": "http://localhost:3000/api/v1/auto_login", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Accept", "value": "application/json, text/plain, */*" }, - { "name": "Accept-Encoding", "value": "gzip, deflate, br" }, - { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, - { "name": "Connection", "value": "keep-alive" }, - { "name": "Host", "value": "localhost:3000" }, - { "name": "Referer", "value": "http://localhost:3000/" }, - { "name": "Sec-Fetch-Dest", "value": "empty" }, - { "name": "Sec-Fetch-Mode", "value": "cors" }, - { "name": "Sec-Fetch-Site", "value": "same-origin" }, - { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" }, - { "name": "sec-ch-ua", "value": "\"Chromium\";v=\"119\", \"Not?A_Brand\";v=\"24\"" }, - { "name": "sec-ch-ua-mobile", "value": "?0" }, - { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } - ], - "queryString": [], - "headersSize": -1, - "bodySize": -1 - }, - "response": { - "status": 200, - "statusText": "OK", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Access-Control-Allow-Origin", "value": "*" }, - { "name": "connection", "value": "close" }, - { "name": "content-length", "value": "227" }, - { "name": "content-type", "value": "application/json" }, - { "name": "date", "value": "Mon, 11 Dec 2023 18:54:57 GMT" }, - { "name": "server", "value": "uvicorn" } - ], - "content": { - "size": -1, - "mimeType": "application/json", - "text": "{\"access_token\":\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20\",\"refresh_token\":null,\"token_type\":\"bearer\"}" - }, - "headersSize": -1, - "bodySize": -1, - "redirectURL": "" - }, - "cache": {}, - "timings": { "send": -1, "wait": -1, "receive": 0.59 } - }, - { - "startedDateTime": "2023-12-11T18:54:58.380Z", - "time": 0.762, - "request": { - "method": "GET", - "url": "http://localhost:3000/api/v1/store/check/api_key", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Accept", "value": "application/json, text/plain, */*" }, - { "name": "Accept-Encoding", "value": "gzip, deflate, br" }, - { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, - { "name": "Connection", "value": "keep-alive" }, - { "name": "Host", "value": "localhost:3000" }, - { "name": "Referer", "value": "http://localhost:3000/" }, - { "name": "Sec-Fetch-Dest", "value": "empty" }, - { "name": "Sec-Fetch-Mode", "value": "cors" }, - { "name": "Sec-Fetch-Site", "value": "same-origin" }, - { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" }, - { "name": "sec-ch-ua", "value": "\"Chromium\";v=\"119\", \"Not?A_Brand\";v=\"24\"" }, - { "name": "sec-ch-ua-mobile", "value": "?0" }, - { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } - ], - "queryString": [], - "headersSize": -1, - "bodySize": -1 - }, - "response": { - "status": 403, - "statusText": "Forbidden", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Access-Control-Allow-Origin", "value": "*" }, - { "name": "connection", "value": "close" }, - { "name": "content-length", "value": "73" }, - { "name": "content-type", "value": "application/json" }, - { "name": "date", "value": "Mon, 11 Dec 2023 18:54:58 GMT" }, - { "name": "server", "value": "uvicorn" } - ], - "content": { - "size": -1, - "mimeType": "application/json", - "text": "{\"detail\":\"An API key as query or header, or a JWT token must be passed\"}" - }, - "headersSize": -1, - "bodySize": -1, - "redirectURL": "" - }, - "cache": {}, - "timings": { "send": -1, "wait": -1, "receive": 0.762 } - }, - { - "startedDateTime": "2023-12-11T18:54:58.423Z", - "time": 1.03, - "request": { - "method": "GET", - "url": "http://localhost:3000/api/v1/flows/", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Accept", "value": "application/json, text/plain, */*" }, - { "name": "Accept-Encoding", "value": "gzip, deflate, br" }, - { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, - { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20" }, - { "name": "Connection", "value": "keep-alive" }, - { "name": "Cookie", "value": "access_token_lf=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20; refresh_tkn_lflw=auto" }, - { "name": "Host", "value": "localhost:3000" }, - { "name": "Referer", "value": "http://localhost:3000/flows" }, - { "name": "Sec-Fetch-Dest", "value": "empty" }, - { "name": "Sec-Fetch-Mode", "value": "cors" }, - { "name": "Sec-Fetch-Site", "value": "same-origin" }, - { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" }, - { "name": "sec-ch-ua", "value": "\"Chromium\";v=\"119\", \"Not?A_Brand\";v=\"24\"" }, - { "name": "sec-ch-ua-mobile", "value": "?0" }, - { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } - ], - "queryString": [], - "headersSize": -1, - "bodySize": -1 - }, - "response": { - "status": 200, - "statusText": "OK", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Access-Control-Allow-Origin", "value": "*" }, - { "name": "connection", "value": "close" }, - { "name": "content-length", "value": "375696" }, - { "name": "content-type", "value": "application/json" }, - { "name": "date", "value": "Mon, 11 Dec 2023 18:54:58 GMT" }, - { "name": "server", "value": "uvicorn" } - ], - "content": { - "size": -1, - "mimeType": "application/json", - "text": "[{\"name\":\"Awesome Euclid\",\"description\":\"Language Models, Mapped and Mastered.\",\"data\":{\"nodes\":[{\"width\":384,\"height\":374,\"id\":\"PromptTemplate-m2yFu\",\"type\":\"genericNode\",\"position\":{\"x\":462.6456058272081,\"y\":1033.9314297130313},\"data\":{\"type\":\"PromptTemplate\",\"node\":{\"template\":{\"output_parser\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"BaseOutputParser\",\"list\":false},\"input_types\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_types\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"input_variables\":{\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":true,\"value\":[\"transcription\"]},\"partial_variables\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"partial_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"template\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"password\":false,\"name\":\"template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"prompt\",\"list\":false,\"value\":\"create an image prompt based on the song's lyrics to be used as the album cover of this song:\\n\\nlyrics:\\n{transcription}\"},\"template_format\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"f-string\",\"password\":false,\"name\":\"template_format\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":false},\"validate_template\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"validate_template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"PromptTemplate\",\"transcription\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"transcription\",\"display_name\":\"transcription\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"A prompt template for a language model.\",\"base_classes\":[\"PromptTemplate\",\"StringPromptTemplate\",\"BasePromptTemplate\"],\"name\":\"\",\"display_name\":\"PromptTemplate\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/\",\"custom_fields\":{\"\":[\"transcription\"],\"template\":[\"transcription\",\"question\"]},\"output_types\":[],\"full_path\":null,\"field_formatters\":{},\"beta\":false,\"error\":null},\"id\":\"PromptTemplate-m2yFu\"},\"selected\":false,\"positionAbsolute\":{\"x\":462.6456058272081,\"y\":1033.9314297130313},\"dragging\":false},{\"width\":384,\"height\":626,\"id\":\"ChatOpenAI-urapv\",\"type\":\"genericNode\",\"position\":{\"x\":189.94856095084924,\"y\":-85.06556385338186},\"data\":{\"type\":\"ChatOpenAI\",\"node\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"list\":true},\"async_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"async_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"default_headers\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"default_query\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_query\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"http_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"http_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":2,\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"max_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"max_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false,\"value\":\"\"},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"gpt-4-1106-preview\",\"password\":false,\"options\":[\"gpt-4-1106-preview\",\"gpt-4\",\"gpt-4-32k\",\"gpt-3.5-turbo\",\"gpt-3.5-turbo-16k\"],\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"n\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"n\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":false,\"dynamic\":false,\"info\":\"\\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\\n\",\"type\":\"str\",\"list\":false},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":0.7,\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ChatOpenAI\"},\"description\":\"`OpenAI` Chat large language models API.\",\"base_classes\":[\"ChatOpenAI\",\"BaseChatModel\",\"BaseLanguageModel\",\"BaseLLM\"],\"display_name\":\"ChatOpenAI\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai\",\"beta\":false,\"error\":null},\"id\":\"ChatOpenAI-urapv\"},\"selected\":false,\"positionAbsolute\":{\"x\":189.94856095084924,\"y\":-85.06556385338186},\"dragging\":false},{\"width\":384,\"height\":806,\"id\":\"CustomComponent-IEIUl\",\"type\":\"genericNode\",\"position\":{\"x\":2364.865919667005,\"y\":88.43094097025096},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nfrom platformdirs import user_cache_dir\\nimport base64\\nfrom PIL import Image\\nfrom io import BytesIO\\nfrom openai import OpenAI\\nfrom pathlib import Path\\n\\nclass Component(CustomComponent):\\n display_name: str = \\\"Image generator\\\"\\n description: str = \\\"generate images using Dall-E\\\"\\n documentation: str = \\\"http://docs.langflow.org/components/custom\\\"\\n\\n def build_config(self):\\n return {\\\"prompt\\\": {\\\"display_name\\\": \\\"Prompt\\\",\\\"input_types\\\":[\\\"str\\\"]},\\n \\\"api_key\\\":{\\\"display_name\\\":\\\"OpenAI API key\\\",\\\"password\\\":True},\\n \\\"model\\\":{\\\"display_name\\\":\\\"Model name\\\",\\\"advanced\\\":True,\\\"options\\\":[\\\"dall-e-2\\\",\\\"dall-e-3\\\"], \\\"value\\\":\\\"dall-e-3\\\"},\\n \\\"file_name\\\":{\\\"display_name\\\":\\\"File Name\\\"},\\n \\\"output_format\\\":{\\\"display_name\\\":\\\"Output format\\\",\\\"options\\\":[\\\"jpeg\\\",\\\"png\\\"],\\\"value\\\":\\\"jpeg\\\"},\\n \\\"width\\\":{\\\"display_name\\\":\\\"Width\\\" ,\\\"value\\\":1024},\\n \\\"height\\\":{\\\"display_name\\\":\\\"Height\\\", \\\"value\\\":1024}\\n }\\n\\n def build(self, prompt:str,api_key:str,model:str,file_name:str,output_format:str,width:int,height:int):\\n client = OpenAI(api_key=api_key)\\n cache_dir = Path(user_cache_dir(\\\"langflow\\\"))\\n images_dir = cache_dir / \\\"images\\\"\\n images_dir.mkdir(parents=True, exist_ok=True)\\n image_path = images_dir / f\\\"{file_name}.{output_format}\\\"\\n response = client.images.generate(\\n model=model,\\n prompt=prompt,\\n size=f\\\"{height}x{width}\\\",\\n response_format=\\\"b64_json\\\",\\n n=1,\\n )\\n # Decode base64-encoded image string\\n binary_data = base64.b64decode(response.data[0].b64_json)\\n # Create PIL Image object from binary image data\\n image_pil = Image.open(BytesIO(binary_data))\\n image_pil.save(image_path, format=output_format.upper())\\n return \\\"\\\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"api_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"api_key\",\"display_name\":\"OpenAI API key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"},\"file_name\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"file_name\",\"display_name\":\"File Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"album\"},\"height\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":1024,\"password\":false,\"name\":\"height\",\"display_name\":\"Height\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"model\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"dall-e-3\",\"password\":false,\"options\":[\"dall-e-2\",\"dall-e-3\"],\"name\":\"model\",\"display_name\":\"Model name\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"output_format\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"jpeg\",\"password\":false,\"options\":[\"jpeg\",\"png\"],\"name\":\"output_format\",\"display_name\":\"Output format\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"prompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"prompt\",\"display_name\":\"Prompt\",\"advanced\":false,\"input_types\":[\"str\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"},\"width\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":1024,\"password\":false,\"name\":\"width\",\"display_name\":\"Width\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false}},\"description\":\"generate images using Dall-E\",\"base_classes\":[\"Data\"],\"display_name\":\"Image generator\",\"custom_fields\":{\"api_key\":null,\"file_name\":null,\"height\":null,\"model\":null,\"output_format\":null,\"prompt\":null,\"width\":null},\"output_types\":[\"Data\"],\"documentation\":\"http://docs.langflow.org/components/custom\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-IEIUl\"},\"selected\":false,\"positionAbsolute\":{\"x\":2364.865919667005,\"y\":88.43094097025096}},{\"width\":384,\"height\":338,\"id\":\"LLMChain-KlJb3\",\"type\":\"genericNode\",\"position\":{\"x\":1242.9851164540805,\"y\":-139.74634696823108},\"data\":{\"type\":\"LLMChain\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Callable, Optional, Union\\n\\nfrom langchain.chains import LLMChain\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import (\\n BaseLanguageModel,\\n BaseMemory,\\n BasePromptTemplate,\\n Chain,\\n)\\n\\n\\nclass LLMChainComponent(CustomComponent):\\n display_name = \\\"LLMChain\\\"\\n description = \\\"Chain to run queries against LLMs\\\"\\n\\n def build_config(self):\\n return {\\n \\\"prompt\\\": {\\\"display_name\\\": \\\"Prompt\\\"},\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"memory\\\": {\\\"display_name\\\": \\\"Memory\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n prompt: BasePromptTemplate,\\n llm: BaseLanguageModel,\\n memory: Optional[BaseMemory] = None,\\n ) -> Union[Chain, Callable]:\\n return LLMChain(prompt=prompt, llm=llm, memory=memory)\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"display_name\":\"code\"},\"_type\":\"CustomComponent\",\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseMemory\",\"list\":false},\"prompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"prompt\",\"display_name\":\"Prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BasePromptTemplate\",\"list\":false}},\"description\":\"Chain to run queries against LLMs\",\"base_classes\":[\"Chain\",\"Callable\"],\"display_name\":\"LLMChain\",\"custom_fields\":{\"llm\":null,\"memory\":null,\"prompt\":null},\"output_types\":[\"LLMChain\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"LLMChain-KlJb3\"},\"selected\":false,\"positionAbsolute\":{\"x\":1242.9851164540805,\"y\":-139.74634696823108},\"dragging\":false},{\"width\":384,\"height\":328,\"id\":\"CustomComponent-bCuc0\",\"type\":\"genericNode\",\"position\":{\"x\":1747.8107777342625,\"y\":319.13729017446667},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\n\\n\\nclass Component(CustomComponent):\\n display_name: str = \\\"Custom Component\\\"\\n description: str = \\\"Create any custom component you want!\\\"\\n documentation: str = \\\"http://docs.langflow.org/components/custom\\\"\\n\\n def build_config(self):\\n return {\\\"param\\\": {\\\"display_name\\\": \\\"Parameter\\\"}}\\n\\n def build(self, param: Chain) -> str:\\n result = param.run({})\\n self.status = result\\n return result\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"param\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"param\",\"display_name\":\"Parameter\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Chain\",\"list\":false}},\"description\":\"Create any custom component you want!\",\"base_classes\":[\"str\"],\"display_name\":\"Custom Component\",\"custom_fields\":{\"param\":null},\"output_types\":[\"str\"],\"documentation\":\"http://docs.langflow.org/components/custom\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-bCuc0\"},\"selected\":false,\"positionAbsolute\":{\"x\":1747.8107777342625,\"y\":319.13729017446667}}],\"edges\":[{\"source\":\"LLMChain-KlJb3\",\"target\":\"CustomComponent-bCuc0\",\"sourceHandle\":\"{œbaseClassesœ:[œChainœ,œCallableœ],œdataTypeœ:œLLMChainœ,œidœ:œLLMChain-KlJb3œ}\",\"targetHandle\":\"{œfieldNameœ:œparamœ,œidœ:œCustomComponent-bCuc0œ,œinputTypesœ:null,œtypeœ:œChainœ}\",\"id\":\"reactflow__edge-LLMChain-KlJb3{œbaseClassesœ:[œChainœ,œCallableœ],œdataTypeœ:œLLMChainœ,œidœ:œLLMChain-KlJb3œ}-CustomComponent-bCuc0{œfieldNameœ:œparamœ,œidœ:œCustomComponent-bCuc0œ,œinputTypesœ:null,œtypeœ:œChainœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"param\",\"id\":\"CustomComponent-bCuc0\",\"inputTypes\":null,\"type\":\"Chain\"},\"sourceHandle\":{\"baseClasses\":[\"Chain\",\"Callable\"],\"dataType\":\"LLMChain\",\"id\":\"LLMChain-KlJb3\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"selected\":false},{\"source\":\"ChatOpenAI-urapv\",\"target\":\"LLMChain-KlJb3\",\"sourceHandle\":\"{œbaseClassesœ:[œChatOpenAIœ,œBaseChatModelœ,œBaseLanguageModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-urapvœ}\",\"targetHandle\":\"{œfieldNameœ:œllmœ,œidœ:œLLMChain-KlJb3œ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\",\"id\":\"reactflow__edge-ChatOpenAI-urapv{œbaseClassesœ:[œChatOpenAIœ,œBaseChatModelœ,œBaseLanguageModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-urapvœ}-LLMChain-KlJb3{œfieldNameœ:œllmœ,œidœ:œLLMChain-KlJb3œ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"llm\",\"id\":\"LLMChain-KlJb3\",\"inputTypes\":null,\"type\":\"BaseLanguageModel\"},\"sourceHandle\":{\"baseClasses\":[\"ChatOpenAI\",\"BaseChatModel\",\"BaseLanguageModel\",\"BaseLLM\"],\"dataType\":\"ChatOpenAI\",\"id\":\"ChatOpenAI-urapv\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"selected\":false},{\"source\":\"PromptTemplate-m2yFu\",\"target\":\"LLMChain-KlJb3\",\"sourceHandle\":\"{œbaseClassesœ:[œPromptTemplateœ,œStringPromptTemplateœ,œBasePromptTemplateœ],œdataTypeœ:œPromptTemplateœ,œidœ:œPromptTemplate-m2yFuœ}\",\"targetHandle\":\"{œfieldNameœ:œpromptœ,œidœ:œLLMChain-KlJb3œ,œinputTypesœ:null,œtypeœ:œBasePromptTemplateœ}\",\"id\":\"reactflow__edge-PromptTemplate-m2yFu{œbaseClassesœ:[œPromptTemplateœ,œStringPromptTemplateœ,œBasePromptTemplateœ],œdataTypeœ:œPromptTemplateœ,œidœ:œPromptTemplate-m2yFuœ}-LLMChain-KlJb3{œfieldNameœ:œpromptœ,œidœ:œLLMChain-KlJb3œ,œinputTypesœ:null,œtypeœ:œBasePromptTemplateœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"prompt\",\"id\":\"LLMChain-KlJb3\",\"inputTypes\":null,\"type\":\"BasePromptTemplate\"},\"sourceHandle\":{\"baseClasses\":[\"PromptTemplate\",\"StringPromptTemplate\",\"BasePromptTemplate\"],\"dataType\":\"PromptTemplate\",\"id\":\"PromptTemplate-m2yFu\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"selected\":false},{\"source\":\"CustomComponent-bCuc0\",\"target\":\"CustomComponent-IEIUl\",\"sourceHandle\":\"{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-bCuc0œ}\",\"targetHandle\":\"{œfieldNameœ:œpromptœ,œidœ:œCustomComponent-IEIUlœ,œinputTypesœ:[œstrœ],œtypeœ:œstrœ}\",\"id\":\"reactflow__edge-CustomComponent-bCuc0{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-bCuc0œ}-CustomComponent-IEIUl{œfieldNameœ:œpromptœ,œidœ:œCustomComponent-IEIUlœ,œinputTypesœ:[œstrœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"prompt\",\"id\":\"CustomComponent-IEIUl\",\"inputTypes\":[\"str\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"str\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-bCuc0\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"selected\":false}],\"viewport\":{\"x\":92.23454077990459,\"y\":183.8125619056221,\"zoom\":0.6070974421975234}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:33:18.503954\",\"folder\":null,\"id\":\"fe142ce5-32dc-4955-b186-672ced662f13\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Goofy Darwin\",\"description\":\"Conversation Catalyst Engine.\",\"data\":{\"nodes\":[{\"width\":384,\"height\":626,\"id\":\"OpenAI-3ZVDh\",\"type\":\"genericNode\",\"position\":{\"x\":-4.0041891741949485,\"y\":-114.02615182719649},\"data\":{\"type\":\"OpenAI\",\"node\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"list\":true},\"allowed_special\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":[],\"password\":false,\"name\":\"allowed_special\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"async_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"async_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"batch_size\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":20,\"password\":false,\"name\":\"batch_size\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"best_of\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"best_of\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"default_headers\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"default_query\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_query\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"disallowed_special\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"all\",\"password\":false,\"name\":\"disallowed_special\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"frequency_penalty\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":0,\"password\":false,\"name\":\"frequency_penalty\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"http_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"http_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"logit_bias\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"logit_bias\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":2,\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"max_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":256,\"password\":true,\"name\":\"max_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"text-davinci-003\",\"password\":false,\"options\":[\"text-davinci-003\",\"text-davinci-002\",\"text-curie-001\",\"text-babbage-001\",\"text-ada-001\"],\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"n\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"n\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":false,\"dynamic\":false,\"info\":\"\\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\\n\",\"type\":\"str\",\"list\":false},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"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\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"presence_penalty\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":0,\"password\":false,\"name\":\"presence_penalty\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":0.7,\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"top_p\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"top_p\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"OpenAI\"},\"description\":\"OpenAI large language models.\",\"base_classes\":[\"OpenAI\",\"BaseLLM\",\"BaseOpenAI\",\"BaseLanguageModel\"],\"display_name\":\"OpenAI\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/openai\",\"beta\":false,\"error\":null},\"id\":\"OpenAI-3ZVDh\"},\"selected\":true,\"positionAbsolute\":{\"x\":-4.0041891741949485,\"y\":-114.02615182719649},\"dragging\":false},{\"width\":384,\"height\":338,\"id\":\"LLMChain-RFYXY\",\"type\":\"genericNode\",\"position\":{\"x\":586.672100458868,\"y\":10.967049167706678},\"data\":{\"type\":\"LLMChain\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Callable, Optional, Union\\n\\nfrom langchain.chains import LLMChain\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import (\\n BaseLanguageModel,\\n BaseMemory,\\n BasePromptTemplate,\\n Chain,\\n)\\n\\n\\nclass LLMChainComponent(CustomComponent):\\n display_name = \\\"LLMChain\\\"\\n description = \\\"Chain to run queries against LLMs\\\"\\n\\n def build_config(self):\\n return {\\n \\\"prompt\\\": {\\\"display_name\\\": \\\"Prompt\\\"},\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"memory\\\": {\\\"display_name\\\": \\\"Memory\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n prompt: BasePromptTemplate,\\n llm: BaseLanguageModel,\\n memory: Optional[BaseMemory] = None,\\n ) -> Union[Chain, Callable]:\\n return LLMChain(prompt=prompt, llm=llm, memory=memory)\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseMemory\",\"list\":false},\"prompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"prompt\",\"display_name\":\"Prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BasePromptTemplate\",\"list\":false}},\"description\":\"Chain to run queries against LLMs\",\"base_classes\":[\"Chain\",\"Callable\"],\"display_name\":\"LLMChain\",\"custom_fields\":{\"llm\":null,\"memory\":null,\"prompt\":null},\"output_types\":[\"LLMChain\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"LLMChain-RFYXY\"},\"positionAbsolute\":{\"x\":586.672100458868,\"y\":10.967049167706678}},{\"width\":384,\"height\":242,\"id\":\"ChatPromptTemplate-ce1sg\",\"type\":\"genericNode\",\"position\":{\"x\":395.598984452791,\"y\":612.188491773035},\"data\":{\"type\":\"ChatPromptTemplate\",\"node\":{\"template\":{\"messages\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"messages\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"BaseMessagePromptTemplate\",\"list\":true},\"output_parser\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"BaseOutputParser\",\"list\":false},\"input_types\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_types\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"input_variables\":{\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":true},\"partial_variables\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"partial_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"validate_template\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"validate_template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ChatPromptTemplate\"},\"description\":\"A prompt template for chat models.\",\"base_classes\":[\"ChatPromptTemplate\",\"BaseChatPromptTemplate\",\"BasePromptTemplate\"],\"display_name\":\"ChatPromptTemplate\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/how_to/prompts\",\"beta\":false,\"error\":null},\"id\":\"ChatPromptTemplate-ce1sg\"},\"selected\":false,\"positionAbsolute\":{\"x\":395.598984452791,\"y\":612.188491773035},\"dragging\":false}],\"edges\":[{\"source\":\"OpenAI-3ZVDh\",\"sourceHandle\":\"{œbaseClassesœ:[œOpenAIœ,œBaseLLMœ,œBaseOpenAIœ,œBaseLanguageModelœ],œdataTypeœ:œOpenAIœ,œidœ:œOpenAI-3ZVDhœ}\",\"target\":\"LLMChain-RFYXY\",\"targetHandle\":\"{œfieldNameœ:œllmœ,œidœ:œLLMChain-RFYXYœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"llm\",\"id\":\"LLMChain-RFYXY\",\"inputTypes\":null,\"type\":\"BaseLanguageModel\"},\"sourceHandle\":{\"baseClasses\":[\"OpenAI\",\"BaseLLM\",\"BaseOpenAI\",\"BaseLanguageModel\"],\"dataType\":\"OpenAI\",\"id\":\"OpenAI-3ZVDh\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-OpenAI-3ZVDh{œbaseClassesœ:[œOpenAIœ,œBaseLLMœ,œBaseOpenAIœ,œBaseLanguageModelœ],œdataTypeœ:œOpenAIœ,œidœ:œOpenAI-3ZVDhœ}-LLMChain-RFYXY{œfieldNameœ:œllmœ,œidœ:œLLMChain-RFYXYœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\"},{\"source\":\"ChatPromptTemplate-ce1sg\",\"sourceHandle\":\"{œbaseClassesœ:[œChatPromptTemplateœ,œBaseChatPromptTemplateœ,œBasePromptTemplateœ],œdataTypeœ:œChatPromptTemplateœ,œidœ:œChatPromptTemplate-ce1sgœ}\",\"target\":\"LLMChain-RFYXY\",\"targetHandle\":\"{œfieldNameœ:œpromptœ,œidœ:œLLMChain-RFYXYœ,œinputTypesœ:null,œtypeœ:œBasePromptTemplateœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"prompt\",\"id\":\"LLMChain-RFYXY\",\"inputTypes\":null,\"type\":\"BasePromptTemplate\"},\"sourceHandle\":{\"baseClasses\":[\"ChatPromptTemplate\",\"BaseChatPromptTemplate\",\"BasePromptTemplate\"],\"dataType\":\"ChatPromptTemplate\",\"id\":\"ChatPromptTemplate-ce1sg\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-ChatPromptTemplate-ce1sg{œbaseClassesœ:[œChatPromptTemplateœ,œBaseChatPromptTemplateœ,œBasePromptTemplateœ],œdataTypeœ:œChatPromptTemplateœ,œidœ:œChatPromptTemplate-ce1sgœ}-LLMChain-RFYXY{œfieldNameœ:œpromptœ,œidœ:œLLMChain-RFYXYœ,œinputTypesœ:null,œtypeœ:œBasePromptTemplateœ}\"}],\"viewport\":{\"x\":8.832868402772647,\"y\":189.85443326477025,\"zoom\":0.6070974421975235}},\"is_component\":false,\"updated_at\":\"2023-12-04T22:50:19.584160\",\"folder\":null,\"id\":\"103766f0-1f50-427a-9ba7-2ab73343c524\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Perky Easley\",\"description\":\"Your Toolkit for Text Generation.\",\"data\":{\"nodes\":[{\"width\":384,\"height\":626,\"id\":\"ChatOpenAI-VPh47\",\"type\":\"genericNode\",\"position\":{\"x\":-328.5742193020408,\"y\":-420.1025929438987},\"data\":{\"type\":\"ChatOpenAI\",\"node\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"list\":true},\"async_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"async_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"default_headers\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"default_query\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_query\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"http_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"http_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":2,\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"max_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"max_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"gpt-3.5-turbo\",\"password\":false,\"options\":[\"gpt-4-1106-preview\",\"gpt-4\",\"gpt-4-32k\",\"gpt-3.5-turbo\",\"gpt-3.5-turbo-16k\"],\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"n\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"n\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":false,\"dynamic\":false,\"info\":\"\\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\\n\",\"type\":\"str\",\"list\":false},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"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\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":0.7,\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ChatOpenAI\"},\"description\":\"`OpenAI` Chat large language models API.\",\"base_classes\":[\"BaseChatModel\",\"ChatOpenAI\",\"BaseLanguageModel\",\"BaseLLM\"],\"display_name\":\"ChatOpenAI\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai\",\"beta\":false,\"error\":null},\"id\":\"ChatOpenAI-VPh47\"},\"selected\":false,\"positionAbsolute\":{\"x\":-328.5742193020408,\"y\":-420.1025929438987},\"dragging\":false},{\"width\":384,\"height\":338,\"id\":\"LLMChain-NgFyo\",\"type\":\"genericNode\",\"position\":{\"x\":225.3113389084088,\"y\":-193.3520019494289},\"data\":{\"type\":\"LLMChain\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Callable, Optional, Union\\n\\nfrom langchain.chains import LLMChain\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import (\\n BaseLanguageModel,\\n BaseMemory,\\n BasePromptTemplate,\\n Chain,\\n)\\n\\n\\nclass LLMChainComponent(CustomComponent):\\n display_name = \\\"LLMChain\\\"\\n description = \\\"Chain to run queries against LLMs\\\"\\n\\n def build_config(self):\\n return {\\n \\\"prompt\\\": {\\\"display_name\\\": \\\"Prompt\\\"},\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"memory\\\": {\\\"display_name\\\": \\\"Memory\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n prompt: BasePromptTemplate,\\n llm: BaseLanguageModel,\\n memory: Optional[BaseMemory] = None,\\n ) -> Union[Chain, Callable]:\\n return LLMChain(prompt=prompt, llm=llm, memory=memory)\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseMemory\",\"list\":false},\"prompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"prompt\",\"display_name\":\"Prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BasePromptTemplate\",\"list\":false}},\"description\":\"Chain to run queries against LLMs\",\"base_classes\":[\"Chain\",\"Callable\"],\"display_name\":\"LLMChain\",\"custom_fields\":{\"llm\":null,\"memory\":null,\"prompt\":null},\"output_types\":[\"LLMChain\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"LLMChain-NgFyo\"},\"selected\":false,\"positionAbsolute\":{\"x\":225.3113389084088,\"y\":-193.3520019494289},\"dragging\":false},{\"width\":384,\"height\":374,\"id\":\"PromptTemplate-oAFjh\",\"type\":\"genericNode\",\"position\":{\"x\":-342.62522294052764,\"y\":391.20629510686103},\"data\":{\"type\":\"PromptTemplate\",\"node\":{\"template\":{\"output_parser\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"BaseOutputParser\",\"list\":false},\"input_types\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_types\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"input_variables\":{\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":true,\"value\":[\"links\"]},\"partial_variables\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"partial_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"template\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"password\":false,\"name\":\"template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"prompt\",\"list\":false,\"value\":\"Answer everything with links\\n{links}\"},\"template_format\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"f-string\",\"password\":false,\"name\":\"template_format\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":false},\"validate_template\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"validate_template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"PromptTemplate\",\"links\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"links\",\"display_name\":\"links\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"A prompt template for a language model.\",\"base_classes\":[\"BasePromptTemplate\",\"StringPromptTemplate\",\"PromptTemplate\"],\"name\":\"\",\"display_name\":\"PromptTemplate\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/\",\"custom_fields\":{\"\":[\"links\"]},\"output_types\":[],\"full_path\":null,\"field_formatters\":{},\"beta\":false,\"error\":null},\"id\":\"PromptTemplate-oAFjh\"},\"selected\":true,\"dragging\":false,\"positionAbsolute\":{\"x\":-342.62522294052764,\"y\":391.20629510686103}}],\"edges\":[{\"source\":\"ChatOpenAI-VPh47\",\"sourceHandle\":\"{œbaseClassesœ:[œBaseChatModelœ,œChatOpenAIœ,œBaseLanguageModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-VPh47œ}\",\"target\":\"LLMChain-NgFyo\",\"targetHandle\":\"{œfieldNameœ:œllmœ,œidœ:œLLMChain-NgFyoœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"llm\",\"id\":\"LLMChain-NgFyo\",\"inputTypes\":null,\"type\":\"BaseLanguageModel\"},\"sourceHandle\":{\"baseClasses\":[\"BaseChatModel\",\"ChatOpenAI\",\"BaseLanguageModel\",\"BaseLLM\"],\"dataType\":\"ChatOpenAI\",\"id\":\"ChatOpenAI-VPh47\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-ChatOpenAI-VPh47{œbaseClassesœ:[œBaseChatModelœ,œChatOpenAIœ,œBaseLanguageModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-VPh47œ}-LLMChain-NgFyo{œfieldNameœ:œllmœ,œidœ:œLLMChain-NgFyoœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\"},{\"source\":\"PromptTemplate-oAFjh\",\"sourceHandle\":\"{œbaseClassesœ:[œBasePromptTemplateœ,œStringPromptTemplateœ,œPromptTemplateœ],œdataTypeœ:œPromptTemplateœ,œidœ:œPromptTemplate-oAFjhœ}\",\"target\":\"LLMChain-NgFyo\",\"targetHandle\":\"{œfieldNameœ:œpromptœ,œidœ:œLLMChain-NgFyoœ,œinputTypesœ:null,œtypeœ:œBasePromptTemplateœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"prompt\",\"id\":\"LLMChain-NgFyo\",\"inputTypes\":null,\"type\":\"BasePromptTemplate\"},\"sourceHandle\":{\"baseClasses\":[\"BasePromptTemplate\",\"StringPromptTemplate\",\"PromptTemplate\"],\"dataType\":\"PromptTemplate\",\"id\":\"PromptTemplate-oAFjh\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-PromptTemplate-oAFjh{œbaseClassesœ:[œBasePromptTemplateœ,œStringPromptTemplateœ,œPromptTemplateœ],œdataTypeœ:œPromptTemplateœ,œidœ:œPromptTemplate-oAFjhœ}-LLMChain-NgFyo{œfieldNameœ:œpromptœ,œidœ:œLLMChain-NgFyoœ,œinputTypesœ:null,œtypeœ:œBasePromptTemplateœ}\"}],\"viewport\":{\"x\":338.6546182690814,\"y\":53.026340800283265,\"zoom\":0.7169776240079143}},\"is_component\":false,\"updated_at\":\"2023-12-04T22:53:25.148460\",\"folder\":null,\"id\":\"a794fc48-5e9b-42a3-924f-7fe610500035\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"(D) Basic Chat (1) (4)\",\"description\":\"Simplest possible chat model\",\"data\":{\"nodes\":[{\"width\":384,\"height\":626,\"id\":\"ChatOpenAI-fBcfh\",\"type\":\"genericNode\",\"position\":{\"x\":228.87326389541306,\"y\":465.8628482073749},\"data\":{\"type\":\"ChatOpenAI\",\"node\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":true},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":6,\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"max_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"max_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"gpt-3.5-turbo\",\"password\":false,\"options\":[\"gpt-3.5-turbo-0613\",\"gpt-3.5-turbo\",\"gpt-3.5-turbo-16k-0613\",\"gpt-3.5-turbo-16k\",\"gpt-4-0613\",\"gpt-4-32k-0613\",\"gpt-4\",\"gpt-4-32k\"],\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"n\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"n\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":false,\"dynamic\":false,\"info\":\"\\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\\n\",\"type\":\"str\",\"list\":false},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"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\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false,\"value\":60},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":0.7,\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ChatOpenAI\"},\"description\":\"`OpenAI` Chat large language models API.\",\"base_classes\":[\"BaseChatModel\",\"BaseLanguageModel\",\"ChatOpenAI\",\"BaseLLM\"],\"display_name\":\"ChatOpenAI\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai\"},\"id\":\"ChatOpenAI-fBcfh\",\"value\":null},\"selected\":false,\"dragging\":false,\"positionAbsolute\":{\"x\":228.87326389541306,\"y\":465.8628482073749}},{\"width\":384,\"height\":310,\"id\":\"ConversationChain-bVNex\",\"type\":\"genericNode\",\"position\":{\"x\":806,\"y\":554},\"data\":{\"type\":\"ConversationChain\",\"node\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":true},\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseMemory\",\"list\":false},\"output_parser\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":{\"_type\":\"default\"},\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLLMOutputParser\",\"list\":false},\"prompt\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":{\"input_variables\":[\"history\",\"input\"],\"output_parser\":null,\"partial_variables\":{},\"template\":\"The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\\n\\nCurrent conversation:\\n{history}\\nHuman: {input}\\nAI:\",\"template_format\":\"f-string\",\"validate_template\":true,\"_type\":\"prompt\"},\"password\":false,\"name\":\"prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BasePromptTemplate\",\"list\":false},\"input_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"input\",\"password\":false,\"name\":\"input_key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"llm_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"llm_kwargs\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"output_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"response\",\"password\":false,\"name\":\"output_key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"return_final_only\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":true,\"password\":false,\"name\":\"return_final_only\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ConversationChain\"},\"description\":\"Chain to have a conversation and load context from memory.\",\"base_classes\":[\"ConversationChain\",\"Chain\",\"LLMChain\",\"function\"],\"display_name\":\"ConversationChain\",\"documentation\":\"\"},\"id\":\"ConversationChain-bVNex\",\"value\":null},\"selected\":false,\"dragging\":false,\"positionAbsolute\":{\"x\":806,\"y\":554}}],\"edges\":[{\"source\":\"ChatOpenAI-fBcfh\",\"sourceHandle\":\"{œbaseClassesœ:[œBaseChatModelœ,œBaseLanguageModelœ,œChatOpenAIœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-fBcfhœ}\",\"target\":\"ConversationChain-bVNex\",\"targetHandle\":\"{œfieldNameœ:œllmœ,œidœ:œConversationChain-bVNexœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\",\"className\":\"stroke-gray-900 stroke-connection\",\"id\":\"reactflow__edge-ChatOpenAI-fBcfh{œbaseClassesœ:[œBaseChatModelœ,œBaseLanguageModelœ,œChatOpenAIœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-fBcfhœ}-ConversationChain-bVNex{œfieldNameœ:œllmœ,œidœ:œConversationChain-bVNexœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\",\"data\":{\"sourceHandle\":{\"baseClasses\":[\"BaseChatModel\",\"BaseLanguageModel\",\"ChatOpenAI\",\"BaseLLM\"],\"dataType\":\"ChatOpenAI\",\"id\":\"ChatOpenAI-fBcfh\"},\"targetHandle\":{\"fieldName\":\"llm\",\"id\":\"ConversationChain-bVNex\",\"inputTypes\":null,\"type\":\"BaseLanguageModel\"}},\"style\":{\"stroke\":\"#555\"},\"animated\":false}],\"viewport\":{\"x\":-118.21416568593895,\"y\":-240.64815770363373,\"zoom\":0.7642485855675408}},\"is_component\":false,\"updated_at\":\"2023-12-04T22:57:55.879806\",\"folder\":null,\"id\":\"bddebeea-b80a-4b28-8895-c4425687dcce\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Directory Loader\",\"description\":\"Generic File Loader\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"import os\\n\\nfrom langchain.schema import Document\\nfrom langflow import CustomComponent\\nimport glob\\n\\nclass DirectoryLoaderComponent(CustomComponent):\\n display_name: str = \\\"Directory Loader\\\"\\n description: str = \\\"Generic File Loader\\\"\\n beta = True\\n loaders_info = [\\n {\\n \\\"loader\\\": \\\"AirbyteJSONLoader\\\",\\n \\\"name\\\": \\\"Airbyte JSON (.jsonl)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.AirbyteJSONLoader\\\",\\n \\\"defaultFor\\\": [\\\"jsonl\\\"],\\n \\\"allowdTypes\\\": [\\\"jsonl\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"JSONLoader\\\",\\n \\\"name\\\": \\\"JSON (.json)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.JSONLoader\\\",\\n \\\"defaultFor\\\": [\\\"json\\\"],\\n \\\"allowdTypes\\\": [\\\"json\\\"],\\n \\\"kwargs\\\": {\\\"jq_schema\\\": \\\".\\\", \\\"text_content\\\": False}\\n },\\n {\\n \\\"loader\\\": \\\"BSHTMLLoader\\\",\\n \\\"name\\\": \\\"BeautifulSoup4 HTML (.html, .htm)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.BSHTMLLoader\\\",\\n \\\"allowdTypes\\\": [\\\"html\\\", \\\"htm\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"CSVLoader\\\",\\n \\\"name\\\": \\\"CSV (.csv)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.CSVLoader\\\",\\n \\\"defaultFor\\\": [\\\"csv\\\"],\\n \\\"allowdTypes\\\": [\\\"csv\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"CoNLLULoader\\\",\\n \\\"name\\\": \\\"CoNLL-U (.conllu)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.CoNLLULoader\\\",\\n \\\"defaultFor\\\": [\\\"conllu\\\"],\\n \\\"allowdTypes\\\": [\\\"conllu\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"EverNoteLoader\\\",\\n \\\"name\\\": \\\"EverNote (.enex)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.EverNoteLoader\\\",\\n \\\"defaultFor\\\": [\\\"enex\\\"],\\n \\\"allowdTypes\\\": [\\\"enex\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"FacebookChatLoader\\\",\\n \\\"name\\\": \\\"Facebook Chat (.json)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.FacebookChatLoader\\\",\\n \\\"allowdTypes\\\": [\\\"json\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"OutlookMessageLoader\\\",\\n \\\"name\\\": \\\"Outlook Message (.msg)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.OutlookMessageLoader\\\",\\n \\\"defaultFor\\\": [\\\"msg\\\"],\\n \\\"allowdTypes\\\": [\\\"msg\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"PyPDFLoader\\\",\\n \\\"name\\\": \\\"PyPDF (.pdf)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.PyPDFLoader\\\",\\n \\\"defaultFor\\\": [\\\"pdf\\\"],\\n \\\"allowdTypes\\\": [\\\"pdf\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"STRLoader\\\",\\n \\\"name\\\": \\\"Subtitle (.str)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.STRLoader\\\",\\n \\\"defaultFor\\\": [\\\"str\\\"],\\n \\\"allowdTypes\\\": [\\\"str\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"TextLoader\\\",\\n \\\"name\\\": \\\"Text (.txt)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.TextLoader\\\",\\n \\\"defaultFor\\\": [\\\"txt\\\"],\\n \\\"allowdTypes\\\": [\\\"txt\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"UnstructuredEmailLoader\\\",\\n \\\"name\\\": \\\"Unstructured Email (.eml)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.UnstructuredEmailLoader\\\",\\n \\\"defaultFor\\\": [\\\"eml\\\"],\\n \\\"allowdTypes\\\": [\\\"eml\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"UnstructuredHTMLLoader\\\",\\n \\\"name\\\": \\\"Unstructured HTML (.html, .htm)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.UnstructuredHTMLLoader\\\",\\n \\\"defaultFor\\\": [\\\"html\\\", \\\"htm\\\"],\\n \\\"allowdTypes\\\": [\\\"html\\\", \\\"htm\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"UnstructuredMarkdownLoader\\\",\\n \\\"name\\\": \\\"Unstructured Markdown (.md)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.UnstructuredMarkdownLoader\\\",\\n \\\"defaultFor\\\": [\\\"md\\\"],\\n \\\"allowdTypes\\\": [\\\"md\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"UnstructuredPowerPointLoader\\\",\\n \\\"name\\\": \\\"Unstructured PowerPoint (.pptx)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.UnstructuredPowerPointLoader\\\",\\n \\\"defaultFor\\\": [\\\"pptx\\\"],\\n \\\"allowdTypes\\\": [\\\"pptx\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"UnstructuredWordLoader\\\",\\n \\\"name\\\": \\\"Unstructured Word (.docx)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.UnstructuredWordLoader\\\",\\n \\\"defaultFor\\\": [\\\"docx\\\"],\\n \\\"allowdTypes\\\": [\\\"docx\\\"],\\n },\\n]\\n\\n\\n def build_config(self):\\n loader_options = [\\\"Automatic\\\"] + [\\n loader_info[\\\"name\\\"] for loader_info in self.loaders_info\\n ]\\n\\n file_types = []\\n suffixes = []\\n\\n for loader_info in self.loaders_info:\\n if \\\"allowedTypes\\\" in loader_info:\\n file_types.extend(loader_info[\\\"allowedTypes\\\"])\\n suffixes.extend([f\\\".{ext}\\\" for ext in loader_info[\\\"allowedTypes\\\"]])\\n\\n return {\\n \\\"directory_path\\\": {\\n \\\"display_name\\\": \\\"Directory Path\\\",\\n \\\"required\\\": True,\\n },\\n \\\"loader\\\": {\\n \\\"display_name\\\": \\\"Loader\\\",\\n \\\"is_list\\\": True,\\n \\\"required\\\": True,\\n \\\"options\\\": loader_options,\\n \\\"value\\\": \\\"Automatic\\\",\\n },\\n }\\n\\n def build(self, directory_path: str, loader: str) -> Document:\\n # Verifique se o diretório existe\\n if not os.path.exists(directory_path):\\n raise ValueError(f\\\"Directory not found: {directory_path}\\\")\\n\\n files = glob.glob(directory_path + \\\"/*.*\\\")\\n\\n\\n loader_info = None\\n if loader == \\\"Automatic\\\":\\n for file in files:\\n file_type = file.split(\\\".\\\")[-1]\\n\\n\\n for info in self.loaders_info:\\n if \\\"defaultFor\\\" in info:\\n if file_type in info[\\\"defaultFor\\\"]:\\n loader_info = info\\n break\\n if loader_info:\\n break\\n\\n if not loader_info:\\n raise ValueError(\\n \\\"No default loader found for any file in the directory\\\"\\n )\\n\\n else:\\n for info in self.loaders_info:\\n if info[\\\"name\\\"] == loader:\\n loader_info = info\\n break\\n\\n if not loader_info:\\n raise ValueError(f\\\"Loader {loader} not found in the loader info list\\\")\\n\\n loader_import = loader_info[\\\"import\\\"]\\n module_name, class_name = loader_import.rsplit(\\\".\\\", 1)\\n\\n try:\\n # Importe o loader dinamicamente\\n loader_module = __import__(module_name, fromlist=[class_name])\\n loader_instance = getattr(loader_module, class_name)\\n except ImportError as e:\\n raise ValueError(\\n f\\\"Loader {loader} could not be imported\\\\nLoader info:\\\\n{loader_info}\\\"\\n ) from e\\n\\n results = []\\n for file in files:\\n file_path = os.path.join(directory_path, file)\\n kwargs = loader_info.get(\\\"kwargs\\\", {})\\n result = loader_instance(file_path=file_path, **kwargs).load()\\n results.append(result)\\n self.status = results\\n return results\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"directory_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"directory_path\",\"display_name\":\"Directory Path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"/Users/ogabrielluiz/Projects/langflow2/docs\"},\"loader\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"Automatic\",\"password\":false,\"options\":[\"Automatic\",\"Airbyte JSON (.jsonl)\",\"JSON (.json)\",\"BeautifulSoup4 HTML (.html, .htm)\",\"CSV (.csv)\",\"CoNLL-U (.conllu)\",\"EverNote (.enex)\",\"Facebook Chat (.json)\",\"Outlook Message (.msg)\",\"PyPDF (.pdf)\",\"Subtitle (.str)\",\"Text (.txt)\",\"Unstructured Email (.eml)\",\"Unstructured HTML (.html, .htm)\",\"Unstructured Markdown (.md)\",\"Unstructured PowerPoint (.pptx)\",\"Unstructured Word (.docx)\"],\"name\":\"loader\",\"display_name\":\"Loader\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true}},\"description\":\"Generic File Loader\",\"base_classes\":[\"Document\"],\"display_name\":\"Directory Loader\",\"custom_fields\":{\"directory_path\":null,\"loader\":null},\"output_types\":[\"Document\"],\"documentation\":\"\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"CustomComponent-Ip6tG\"},\"id\":\"CustomComponent-Ip6tG\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-04T22:58:38.570303\",\"folder\":null,\"id\":\"5fe4debc-b6a7-45d4-a694-c02d8aa93b08\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Whisper Transcriber\",\"description\":\"Converts audio to text using OpenAI's Whisper.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom typing import Optional, List, Dict, Union\\nfrom langflow.field_typing import (\\n AgentExecutor,\\n BaseChatMemory,\\n BaseLanguageModel,\\n BaseLLM,\\n BaseLoader,\\n BaseMemory,\\n BaseOutputParser,\\n BasePromptTemplate,\\n BaseRetriever,\\n Callable,\\n Chain,\\n ChatPromptTemplate,\\n Data,\\n Document,\\n Embeddings,\\n NestedDict,\\n Object,\\n PromptTemplate,\\n TextSplitter,\\n Tool,\\n VectorStore,\\n)\\n\\nfrom openai import OpenAI\\nclass Component(CustomComponent):\\n display_name: str = \\\"Whisper Transcriber\\\"\\n description: str = \\\"Converts audio to text using OpenAI's Whisper.\\\"\\n\\n def build_config(self):\\n return {\\\"audio\\\":{\\\"field_type\\\":\\\"file\\\",\\\"suffixes\\\":[\\\".mp3\\\", \\\".mp4\\\", \\\".m4a\\\"]},\\\"OpenAIKey\\\":{\\\"field_type\\\":\\\"str\\\",\\\"password\\\":True}}\\n\\n def build(self, audio:str, OpenAIKey:str) -> str:\\n \\n # TODO: if output path, persist & load it instead\\n \\n client = OpenAI(api_key=OpenAIKey)\\n \\n audio_file= open(audio, \\\"rb\\\")\\n transcript = client.audio.transcriptions.create(\\n model=\\\"whisper-1\\\", \\n file=audio_file,\\n response_format=\\\"text\\\"\\n )\\n \\n \\n self.status = transcript\\n return transcript\\n\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"OpenAIKey\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"OpenAIKey\",\"display_name\":\"OpenAIKey\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"},\"audio\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"suffixes\":[\".mp3\",\".mp4\",\".m4a\"],\"password\":false,\"name\":\"audio\",\"display_name\":\"audio\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"file_path\":\"/Users/rodrigonader/Library/Caches/langflow/19b3e1c9-90bf-405f-898a-e982f47adf76/a3308ce7e9b10088fcd985aabb6d17b012c6b6e81ff8806356574474c9d10229.m4a\",\"value\":\"Audio Recording 2023-11-29 at 12.12.04.m4a\"}},\"description\":\"Converts audio to text using OpenAI's Whisper.\",\"base_classes\":[\"str\"],\"display_name\":\"Whisper Transcriber\",\"custom_fields\":{\"OpenAIKey\":null,\"audio\":null},\"output_types\":[\"str\"],\"documentation\":\"\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"CustomComponent-GJRrs\"},\"id\":\"CustomComponent-GJRrs\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-04T22:58:39.710502\",\"folder\":null,\"id\":\"bd9e911d-46bd-429f-aa75-dd740430695e\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Youtube Conversation\",\"description\":\"Craft Meaningful Interactions, Generate Value.\",\"data\":{\"nodes\":[{\"width\":384,\"height\":589,\"id\":\"CustomComponent-h0NSI\",\"type\":\"genericNode\",\"position\":{\"x\":714.9531293402755,\"y\":0.4994374160582993},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"import requests\\nfrom langflow import CustomComponent\\nfrom langchain.llms.base import BaseLLM\\nfrom langchain.schema import Document\\nfrom langchain.document_loaders import YoutubeLoader\\n\\n# Example usage:\\n\\nclass YourComponent(CustomComponent):\\n display_name: str = \\\"YouTube Transcript\\\"\\n description: str = \\\"YouTube transcripts refer to the written text versions of the spoken content in a video uploaded to the YouTube platform.\\\"\\n\\n def build_config(self):\\n return {\\\"url\\\": {\\\"multiline\\\": True, \\\"required\\\": True}}\\n\\n def build(self, url: str, llm: BaseLLM, dependencies: Document, language: str = \\\"en\\\") -> Document:\\n dependencies\\n response = requests.get(url)\\n loader = YoutubeLoader.from_youtube_url(url, add_video_info=True, language=[language])\\n result = loader.load()\\n self.repr_value = str(result)\\n return result\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"dependencies\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"dependencies\",\"display_name\":\"dependencies\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Document\",\"list\":false},\"language\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"en\",\"password\":false,\"name\":\"language\",\"display_name\":\"language\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLLM\",\"list\":false},\"url\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"password\":false,\"name\":\"url\",\"display_name\":\"url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"YouTube transcripts refer to the written text versions of the spoken content in a video uploaded to the YouTube platform.\",\"base_classes\":[\"Document\"],\"display_name\":\"YouTube Transcript\",\"custom_fields\":{\"dependencies\":null,\"language\":null,\"llm\":null,\"url\":null},\"output_types\":[\"Document\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-h0NSI\"},\"selected\":false,\"dragging\":false,\"positionAbsolute\":{\"x\":714.9531293402755,\"y\":0.4994374160582993}},{\"width\":384,\"height\":629,\"id\":\"ChatOpenAI-q61Y2\",\"type\":\"genericNode\",\"position\":{\"x\":18,\"y\":625.5521045590924},\"data\":{\"type\":\"ChatOpenAI\",\"node\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":true},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":6,\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"max_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"max_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false,\"value\":\"\"},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"gpt-3.5-turbo-16k\",\"password\":false,\"options\":[\"gpt-3.5-turbo-0613\",\"gpt-3.5-turbo\",\"gpt-3.5-turbo-16k-0613\",\"gpt-3.5-turbo-16k\",\"gpt-4-0613\",\"gpt-4-32k-0613\",\"gpt-4\",\"gpt-4-32k\"],\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"n\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"n\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":false,\"dynamic\":false,\"info\":\"\\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\\n\",\"type\":\"str\",\"list\":false},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":0.7,\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ChatOpenAI\"},\"description\":\"`OpenAI` Chat large language models API.\",\"base_classes\":[\"ChatOpenAI\",\"BaseChatModel\",\"BaseLanguageModel\",\"BaseLLM\"],\"display_name\":\"ChatOpenAI\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai\",\"beta\":false,\"error\":null},\"id\":\"ChatOpenAI-q61Y2\"},\"selected\":false,\"positionAbsolute\":{\"x\":18,\"y\":625.5521045590924},\"dragging\":false},{\"width\":384,\"height\":539,\"id\":\"Chroma-gVhy7\",\"type\":\"genericNode\",\"position\":{\"x\":2110.365967257855,\"y\":805.0149521868784},\"data\":{\"type\":\"Chroma\",\"node\":{\"template\":{\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"chromadb.Client\",\"list\":false},\"client_settings\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client_settings\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"chromadb.config.Setting\",\"list\":true},\"documents\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Document\",\"list\":true},\"embedding\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Embeddings\",\"list\":false},\"chroma_server_cors_allow_origins\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"chroma_server_cors_allow_origins\",\"display_name\":\"Chroma Server CORS Allow Origins\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"chroma_server_grpc_port\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"chroma_server_grpc_port\",\"display_name\":\"Chroma Server GRPC Port\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"chroma_server_host\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"chroma_server_host\",\"display_name\":\"Chroma Server Host\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"chroma_server_http_port\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"chroma_server_http_port\",\"display_name\":\"Chroma Server HTTP Port\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"chroma_server_ssl_enabled\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"chroma_server_ssl_enabled\",\"display_name\":\"Chroma Server SSL Enabled\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"collection_metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"collection_metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"collection_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"langchain\",\"password\":false,\"name\":\"collection_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"ids\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"ids\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"metadatas\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadatas\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":true},\"persist\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"persist\",\"display_name\":\"Persist\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"persist_directory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"persist_directory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"search_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"{}\",\"password\":false,\"name\":\"search_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"NestedDict\",\"list\":false},\"_type\":\"Chroma\"},\"description\":\"Create a Chroma vectorstore from a raw documents.\",\"base_classes\":[\"VectorStore\",\"Chroma\",\"BaseRetriever\",\"VectorStoreRetriever\"],\"display_name\":\"Chroma\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/chroma\",\"beta\":false,\"error\":null},\"id\":\"Chroma-gVhy7\"},\"selected\":false,\"positionAbsolute\":{\"x\":2110.365967257855,\"y\":805.0149521868784},\"dragging\":false},{\"width\":384,\"height\":501,\"id\":\"RecursiveCharacterTextSplitter-1eaOX\",\"type\":\"genericNode\",\"position\":{\"x\":1409.2872773444874,\"y\":19.45456141103284},\"data\":{\"type\":\"RecursiveCharacterTextSplitter\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Optional\\nfrom langflow import CustomComponent\\nfrom langchain.schema import Document\\nfrom langflow.utils.util import build_loader_repr_from_documents\\n\\n\\nclass RecursiveCharacterTextSplitterComponent(CustomComponent):\\n display_name: str = \\\"Recursive Character Text Splitter\\\"\\n description: str = \\\"Split text into chunks of a specified length.\\\"\\n documentation: str = \\\"https://docs.langflow.org/components/text-splitters#recursivecharactertextsplitter\\\"\\n\\n def build_config(self):\\n return {\\n \\\"documents\\\": {\\n \\\"display_name\\\": \\\"Documents\\\",\\n \\\"info\\\": \\\"The documents to split.\\\",\\n },\\n \\\"separators\\\": {\\n \\\"display_name\\\": \\\"Separators\\\",\\n \\\"info\\\": 'The characters to split on.\\\\nIf left empty defaults to [\\\"\\\\\\\\n\\\\\\\\n\\\", \\\"\\\\\\\\n\\\", \\\" \\\", \\\"\\\"].',\\n \\\"is_list\\\": True,\\n },\\n \\\"chunk_size\\\": {\\n \\\"display_name\\\": \\\"Chunk Size\\\",\\n \\\"info\\\": \\\"The maximum length of each chunk.\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"value\\\": 1000,\\n },\\n \\\"chunk_overlap\\\": {\\n \\\"display_name\\\": \\\"Chunk Overlap\\\",\\n \\\"info\\\": \\\"The amount of overlap between chunks.\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"value\\\": 200,\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n documents: list[Document],\\n separators: Optional[list[str]] = None,\\n chunk_size: Optional[int] = 1000,\\n chunk_overlap: Optional[int] = 200,\\n ) -> list[Document]:\\n \\\"\\\"\\\"\\n Split text into chunks of a specified length.\\n\\n Args:\\n separators (list[str]): The characters to split on.\\n chunk_size (int): The maximum length of each chunk.\\n chunk_overlap (int): The amount of overlap between chunks.\\n length_function (function): The function to use to calculate the length of the text.\\n\\n Returns:\\n list[str]: The chunks of text.\\n \\\"\\\"\\\"\\n from langchain.text_splitter import RecursiveCharacterTextSplitter\\n\\n if separators == \\\"\\\":\\n separators = None\\n elif separators:\\n # check if the separators list has escaped characters\\n # if there are escaped characters, unescape them\\n separators = [x.encode().decode(\\\"unicode-escape\\\") for x in separators]\\n\\n # Make sure chunk_size and chunk_overlap are ints\\n if isinstance(chunk_size, str):\\n chunk_size = int(chunk_size)\\n if isinstance(chunk_overlap, str):\\n chunk_overlap = int(chunk_overlap)\\n splitter = RecursiveCharacterTextSplitter(\\n separators=separators,\\n chunk_size=chunk_size,\\n chunk_overlap=chunk_overlap,\\n )\\n\\n docs = splitter.split_documents(documents)\\n self.repr_value = build_loader_repr_from_documents(docs)\\n return docs\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"chunk_overlap\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"50\",\"password\":false,\"name\":\"chunk_overlap\",\"display_name\":\"Chunk Overlap\",\"advanced\":false,\"dynamic\":false,\"info\":\"The amount of overlap between chunks.\",\"type\":\"int\",\"list\":false},\"chunk_size\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"400\",\"password\":false,\"name\":\"chunk_size\",\"display_name\":\"Chunk Size\",\"advanced\":false,\"dynamic\":false,\"info\":\"The maximum length of each chunk.\",\"type\":\"int\",\"list\":false},\"documents\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"The documents to split.\",\"type\":\"Document\",\"list\":true},\"separators\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"separators\",\"display_name\":\"Separators\",\"advanced\":false,\"dynamic\":false,\"info\":\"The characters to split on.\\nIf left empty defaults to [\\\"\\\\n\\\\n\\\", \\\"\\\\n\\\", \\\" \\\", \\\"\\\"].\",\"type\":\"str\",\"list\":true,\"value\":[\" \"]}},\"description\":\"Split text into chunks of a specified length.\",\"base_classes\":[\"Document\"],\"display_name\":\"Recursive Character Text Splitter\",\"custom_fields\":{\"chunk_overlap\":null,\"chunk_size\":null,\"documents\":null,\"separators\":null},\"output_types\":[\"RecursiveCharacterTextSplitter\"],\"documentation\":\"https://docs.langflow.org/components/text-splitters#recursivecharactertextsplitter\",\"beta\":true,\"error\":null},\"id\":\"RecursiveCharacterTextSplitter-1eaOX\"},\"selected\":false,\"positionAbsolute\":{\"x\":1409.2872773444874,\"y\":19.45456141103284},\"dragging\":false},{\"width\":384,\"height\":367,\"id\":\"OpenAIEmbeddings-cduOO\",\"type\":\"genericNode\",\"position\":{\"x\":1405.1176670984544,\"y\":1029.459061269321},\"data\":{\"type\":\"OpenAIEmbeddings\",\"node\":{\"template\":{\"allowed_special\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[],\"password\":false,\"name\":\"allowed_special\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Literal'all'\",\"list\":true},\"disallowed_special\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"all\",\"password\":false,\"name\":\"disallowed_special\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Literal'all'\",\"list\":true},\"chunk_size\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":1000,\"password\":false,\"name\":\"chunk_size\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"deployment\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"text-embedding-ada-002\",\"password\":false,\"name\":\"deployment\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"embedding_ctx_length\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":8191,\"password\":false,\"name\":\"embedding_ctx_length\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"headers\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"{'Authorization': 'Bearer '}\",\"password\":false,\"name\":\"headers\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":6,\"password\":false,\"name\":\"max_retries\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"model\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"text-embedding-ada-002\",\"password\":false,\"name\":\"model\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_api_type\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"openai_api_type\",\"display_name\":\"OpenAI API Type\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"},\"openai_api_version\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"openai_api_version\",\"display_name\":\"OpenAI API Version\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"show_progress_bar\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"show_progress_bar\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"skip_empty\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"skip_empty\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"},\"_type\":\"OpenAIEmbeddings\"},\"description\":\"OpenAI embedding models.\",\"base_classes\":[\"Embeddings\",\"OpenAIEmbeddings\"],\"display_name\":\"OpenAIEmbeddings\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/openai\",\"beta\":false,\"error\":null},\"id\":\"OpenAIEmbeddings-cduOO\"},\"selected\":false,\"positionAbsolute\":{\"x\":1405.1176670984544,\"y\":1029.459061269321}},{\"width\":384,\"height\":339,\"id\":\"RetrievalQA-4PmTB\",\"type\":\"genericNode\",\"position\":{\"x\":2711.7786966415715,\"y\":709.4450828605463},\"data\":{\"type\":\"RetrievalQA\",\"node\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":true},\"combine_documents_chain\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"combine_documents_chain\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseCombineDocumentsChain\",\"list\":false},\"memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseMemory\",\"list\":false},\"retriever\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"retriever\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseRetriever\",\"list\":false},\"input_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"query\",\"password\":false,\"name\":\"input_key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"output_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"result\",\"password\":false,\"name\":\"output_key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"return_source_documents\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":true,\"password\":false,\"name\":\"return_source_documents\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"RetrievalQA\"},\"description\":\"Chain for question-answering against an index.\",\"base_classes\":[\"RetrievalQA\",\"Chain\",\"BaseRetrievalQA\",\"function\"],\"display_name\":\"RetrievalQA\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/chains/popular/vector_db_qa\",\"beta\":false,\"error\":null},\"id\":\"RetrievalQA-4PmTB\"},\"selected\":false,\"positionAbsolute\":{\"x\":2711.7786966415715,\"y\":709.4450828605463}},{\"width\":384,\"height\":333,\"id\":\"CombineDocsChain-yk0JF\",\"type\":\"genericNode\",\"position\":{\"x\":2125.6202053356537,\"y\":199.07708924409633},\"data\":{\"type\":\"CombineDocsChain\",\"node\":{\"template\":{\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"chain_type\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"stuff\",\"password\":false,\"options\":[\"stuff\",\"map_reduce\",\"map_rerank\",\"refine\"],\"name\":\"chain_type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"_type\":\"load_qa_chain\"},\"description\":\"Load question answering chain.\",\"base_classes\":[\"BaseCombineDocumentsChain\",\"function\"],\"display_name\":\"CombineDocsChain\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"id\":\"CombineDocsChain-yk0JF\"},\"selected\":false,\"positionAbsolute\":{\"x\":2125.6202053356537,\"y\":199.07708924409633},\"dragging\":false},{\"width\":384,\"height\":417,\"id\":\"CustomComponent-y6Wg0\",\"type\":\"genericNode\",\"position\":{\"x\":39.400034102832365,\"y\":-499.03551482195707},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\n\\nimport subprocess\\n\\nfrom langchain.llms.base import BaseLLM\\nfrom langchain.chains import LLMChain\\nfrom langchain.prompts import PromptTemplate\\nfrom langchain.schema import Document\\n\\nfrom typing import List\\n\\n\\nclass YourComponent(CustomComponent):\\n display_name: str = \\\"PIP Install\\\"\\n description: str = \\\"Create any custom component you want!\\\"\\n\\n def build(self, libs: List[str]) -> Document:\\n def install_package(package_name):\\n subprocess.check_call([\\\"pip\\\", \\\"install\\\", package_name])\\n for lib in libs:\\n install_package(lib)\\n return \\\"\\\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"libs\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"libs\",\"display_name\":\"libs\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true,\"value\":[\"requests\",\"pytube\"]}},\"description\":\"Create any custom component you want!\",\"base_classes\":[\"Document\"],\"display_name\":\"PIP Install\",\"custom_fields\":{\"libs\":null},\"output_types\":[],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-y6Wg0\"},\"selected\":false,\"dragging\":false,\"positionAbsolute\":{\"x\":39.400034102832365,\"y\":-499.03551482195707}}],\"edges\":[{\"source\":\"ChatOpenAI-q61Y2\",\"sourceHandle\":\"{œbaseClassesœ:[œChatOpenAIœ,œBaseChatModelœ,œBaseLanguageModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-q61Y2œ}\",\"target\":\"CustomComponent-h0NSI\",\"targetHandle\":\"{œfieldNameœ:œllmœ,œidœ:œCustomComponent-h0NSIœ,œinputTypesœ:null,œtypeœ:œBaseLLMœ}\",\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-ChatOpenAI-q61Y2{œbaseClassesœ:[œChatOpenAIœ,œBaseChatModelœ,œBaseLanguageModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-q61Y2œ}-CustomComponent-h0NSI{œfieldNameœ:œllmœ,œidœ:œCustomComponent-h0NSIœ,œinputTypesœ:null,œtypeœ:œBaseLLMœ}\",\"data\":{\"sourceHandle\":{\"baseClasses\":[\"ChatOpenAI\",\"BaseChatModel\",\"BaseLanguageModel\",\"BaseLLM\"],\"dataType\":\"ChatOpenAI\",\"id\":\"ChatOpenAI-q61Y2\"},\"targetHandle\":{\"fieldName\":\"llm\",\"id\":\"CustomComponent-h0NSI\",\"inputTypes\":null,\"type\":\"BaseLLM\"}}},{\"source\":\"CustomComponent-y6Wg0\",\"sourceHandle\":\"{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-y6Wg0œ}\",\"target\":\"CustomComponent-h0NSI\",\"targetHandle\":\"{œfieldNameœ:œdependenciesœ,œidœ:œCustomComponent-h0NSIœ,œinputTypesœ:null,œtypeœ:œDocumentœ}\",\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-y6Wg0{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-y6Wg0œ}-CustomComponent-h0NSI{œfieldNameœ:œdependenciesœ,œidœ:œCustomComponent-h0NSIœ,œinputTypesœ:null,œtypeœ:œDocumentœ}\",\"data\":{\"sourceHandle\":{\"baseClasses\":[\"Document\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-y6Wg0\"},\"targetHandle\":{\"fieldName\":\"dependencies\",\"id\":\"CustomComponent-h0NSI\",\"inputTypes\":null,\"type\":\"Document\"}}},{\"source\":\"CustomComponent-h0NSI\",\"sourceHandle\":\"{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-h0NSIœ}\",\"target\":\"RecursiveCharacterTextSplitter-1eaOX\",\"targetHandle\":\"{œfieldNameœ:œdocumentsœ,œidœ:œRecursiveCharacterTextSplitter-1eaOXœ,œinputTypesœ:null,œtypeœ:œDocumentœ}\",\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-h0NSI{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-h0NSIœ}-RecursiveCharacterTextSplitter-1eaOX{œfieldNameœ:œdocumentsœ,œidœ:œRecursiveCharacterTextSplitter-1eaOXœ,œinputTypesœ:null,œtypeœ:œDocumentœ}\",\"data\":{\"sourceHandle\":{\"baseClasses\":[\"Document\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-h0NSI\"},\"targetHandle\":{\"fieldName\":\"documents\",\"id\":\"RecursiveCharacterTextSplitter-1eaOX\",\"inputTypes\":null,\"type\":\"Document\"}},\"selected\":false},{\"source\":\"OpenAIEmbeddings-cduOO\",\"sourceHandle\":\"{œbaseClassesœ:[œEmbeddingsœ,œOpenAIEmbeddingsœ],œdataTypeœ:œOpenAIEmbeddingsœ,œidœ:œOpenAIEmbeddings-cduOOœ}\",\"target\":\"Chroma-gVhy7\",\"targetHandle\":\"{œfieldNameœ:œembeddingœ,œidœ:œChroma-gVhy7œ,œinputTypesœ:null,œtypeœ:œEmbeddingsœ}\",\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-OpenAIEmbeddings-cduOO{œbaseClassesœ:[œEmbeddingsœ,œOpenAIEmbeddingsœ],œdataTypeœ:œOpenAIEmbeddingsœ,œidœ:œOpenAIEmbeddings-cduOOœ}-Chroma-gVhy7{œfieldNameœ:œembeddingœ,œidœ:œChroma-gVhy7œ,œinputTypesœ:null,œtypeœ:œEmbeddingsœ}\",\"data\":{\"sourceHandle\":{\"baseClasses\":[\"Embeddings\",\"OpenAIEmbeddings\"],\"dataType\":\"OpenAIEmbeddings\",\"id\":\"OpenAIEmbeddings-cduOO\"},\"targetHandle\":{\"fieldName\":\"embedding\",\"id\":\"Chroma-gVhy7\",\"inputTypes\":null,\"type\":\"Embeddings\"}}},{\"source\":\"RecursiveCharacterTextSplitter-1eaOX\",\"sourceHandle\":\"{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œRecursiveCharacterTextSplitterœ,œidœ:œRecursiveCharacterTextSplitter-1eaOXœ}\",\"target\":\"Chroma-gVhy7\",\"targetHandle\":\"{œfieldNameœ:œdocumentsœ,œidœ:œChroma-gVhy7œ,œinputTypesœ:null,œtypeœ:œDocumentœ}\",\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-RecursiveCharacterTextSplitter-1eaOX{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œRecursiveCharacterTextSplitterœ,œidœ:œRecursiveCharacterTextSplitter-1eaOXœ}-Chroma-gVhy7{œfieldNameœ:œdocumentsœ,œidœ:œChroma-gVhy7œ,œinputTypesœ:null,œtypeœ:œDocumentœ}\",\"data\":{\"sourceHandle\":{\"baseClasses\":[\"Document\"],\"dataType\":\"RecursiveCharacterTextSplitter\",\"id\":\"RecursiveCharacterTextSplitter-1eaOX\"},\"targetHandle\":{\"fieldName\":\"documents\",\"id\":\"Chroma-gVhy7\",\"inputTypes\":null,\"type\":\"Document\"}}},{\"source\":\"ChatOpenAI-q61Y2\",\"sourceHandle\":\"{œbaseClassesœ:[œChatOpenAIœ,œBaseChatModelœ,œBaseLanguageModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-q61Y2œ}\",\"target\":\"CombineDocsChain-yk0JF\",\"targetHandle\":\"{œfieldNameœ:œllmœ,œidœ:œCombineDocsChain-yk0JFœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\",\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-ChatOpenAI-q61Y2{œbaseClassesœ:[œChatOpenAIœ,œBaseChatModelœ,œBaseLanguageModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-q61Y2œ}-CombineDocsChain-yk0JF{œfieldNameœ:œllmœ,œidœ:œCombineDocsChain-yk0JFœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\",\"data\":{\"sourceHandle\":{\"baseClasses\":[\"ChatOpenAI\",\"BaseChatModel\",\"BaseLanguageModel\",\"BaseLLM\"],\"dataType\":\"ChatOpenAI\",\"id\":\"ChatOpenAI-q61Y2\"},\"targetHandle\":{\"fieldName\":\"llm\",\"id\":\"CombineDocsChain-yk0JF\",\"inputTypes\":null,\"type\":\"BaseLanguageModel\"}}},{\"source\":\"CombineDocsChain-yk0JF\",\"sourceHandle\":\"{œbaseClassesœ:[œBaseCombineDocumentsChainœ,œfunctionœ],œdataTypeœ:œCombineDocsChainœ,œidœ:œCombineDocsChain-yk0JFœ}\",\"target\":\"RetrievalQA-4PmTB\",\"targetHandle\":\"{œfieldNameœ:œcombine_documents_chainœ,œidœ:œRetrievalQA-4PmTBœ,œinputTypesœ:null,œtypeœ:œBaseCombineDocumentsChainœ}\",\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CombineDocsChain-yk0JF{œbaseClassesœ:[œBaseCombineDocumentsChainœ,œfunctionœ],œdataTypeœ:œCombineDocsChainœ,œidœ:œCombineDocsChain-yk0JFœ}-RetrievalQA-4PmTB{œfieldNameœ:œcombine_documents_chainœ,œidœ:œRetrievalQA-4PmTBœ,œinputTypesœ:null,œtypeœ:œBaseCombineDocumentsChainœ}\",\"data\":{\"sourceHandle\":{\"baseClasses\":[\"BaseCombineDocumentsChain\",\"function\"],\"dataType\":\"CombineDocsChain\",\"id\":\"CombineDocsChain-yk0JF\"},\"targetHandle\":{\"fieldName\":\"combine_documents_chain\",\"id\":\"RetrievalQA-4PmTB\",\"inputTypes\":null,\"type\":\"BaseCombineDocumentsChain\"}}},{\"source\":\"Chroma-gVhy7\",\"sourceHandle\":\"{œbaseClassesœ:[œVectorStoreœ,œChromaœ,œBaseRetrieverœ,œVectorStoreRetrieverœ],œdataTypeœ:œChromaœ,œidœ:œChroma-gVhy7œ}\",\"target\":\"RetrievalQA-4PmTB\",\"targetHandle\":\"{œfieldNameœ:œretrieverœ,œidœ:œRetrievalQA-4PmTBœ,œinputTypesœ:null,œtypeœ:œBaseRetrieverœ}\",\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-Chroma-gVhy7{œbaseClassesœ:[œVectorStoreœ,œChromaœ,œBaseRetrieverœ,œVectorStoreRetrieverœ],œdataTypeœ:œChromaœ,œidœ:œChroma-gVhy7œ}-RetrievalQA-4PmTB{œfieldNameœ:œretrieverœ,œidœ:œRetrievalQA-4PmTBœ,œinputTypesœ:null,œtypeœ:œBaseRetrieverœ}\",\"data\":{\"sourceHandle\":{\"baseClasses\":[\"VectorStore\",\"Chroma\",\"BaseRetriever\",\"VectorStoreRetriever\"],\"dataType\":\"Chroma\",\"id\":\"Chroma-gVhy7\"},\"targetHandle\":{\"fieldName\":\"retriever\",\"id\":\"RetrievalQA-4PmTB\",\"inputTypes\":null,\"type\":\"BaseRetriever\"}}}],\"viewport\":{\"x\":189.54413265004274,\"y\":259.89949657174975,\"zoom\":0.291027508374689}},\"is_component\":false,\"updated_at\":\"2023-12-04T22:59:08.830269\",\"folder\":null,\"id\":\"bc7eb94b-6fc6-49cb-9b19-35347ba51afa\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Web Scraper - Content & Links\",\"description\":\"Fetch and parse text and links from a given URL.\",\"data\":{\"nodes\":[{\"width\":384,\"height\":338,\"id\":\"LLMChain-H7PBy\",\"type\":\"genericNode\",\"position\":{\"x\":1682.494010974207,\"y\":275.5701585623092},\"data\":{\"type\":\"LLMChain\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Callable, Optional, Union\\n\\nfrom langchain.chains import LLMChain\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import (\\n BaseLanguageModel,\\n BaseMemory,\\n BasePromptTemplate,\\n Chain,\\n)\\n\\n\\nclass LLMChainComponent(CustomComponent):\\n display_name = \\\"LLMChain\\\"\\n description = \\\"Chain to run queries against LLMs\\\"\\n\\n def build_config(self):\\n return {\\n \\\"prompt\\\": {\\\"display_name\\\": \\\"Prompt\\\"},\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"memory\\\": {\\\"display_name\\\": \\\"Memory\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n prompt: BasePromptTemplate,\\n llm: BaseLanguageModel,\\n memory: Optional[BaseMemory] = None,\\n ) -> Union[Chain, Callable]:\\n return LLMChain(prompt=prompt, llm=llm, memory=memory)\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseMemory\",\"list\":false},\"prompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"prompt\",\"display_name\":\"Prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BasePromptTemplate\",\"list\":false}},\"description\":\"Chain to run queries against LLMs\",\"base_classes\":[\"Chain\",\"Callable\"],\"display_name\":\"LLMChain\",\"custom_fields\":{\"llm\":null,\"memory\":null,\"prompt\":null},\"output_types\":[\"LLMChain\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"LLMChain-H7PBy\"},\"selected\":false,\"positionAbsolute\":{\"x\":1682.494010974207,\"y\":275.5701585623092},\"dragging\":false},{\"width\":384,\"height\":626,\"id\":\"ChatOpenAI-VSAdc\",\"type\":\"genericNode\",\"position\":{\"x\":1002.4263147022411,\"y\":-198.2305006886859},\"data\":{\"type\":\"ChatOpenAI\",\"node\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"list\":true},\"async_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"async_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"default_headers\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"default_query\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_query\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"http_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"http_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":2,\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"max_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"max_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false,\"value\":\"\"},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"gpt-4-1106-preview\",\"password\":false,\"options\":[\"gpt-4-1106-preview\",\"gpt-4\",\"gpt-4-32k\",\"gpt-3.5-turbo\",\"gpt-3.5-turbo-16k\"],\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"n\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"n\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":false,\"dynamic\":false,\"info\":\"\\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\\n\",\"type\":\"str\",\"list\":false},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"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\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"0.1\",\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ChatOpenAI\"},\"description\":\"`OpenAI` Chat large language models API.\",\"base_classes\":[\"BaseLanguageModel\",\"ChatOpenAI\",\"BaseChatModel\",\"BaseLLM\"],\"display_name\":\"ChatOpenAI\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai\",\"beta\":false,\"error\":null},\"id\":\"ChatOpenAI-VSAdc\"},\"selected\":false,\"dragging\":false,\"positionAbsolute\":{\"x\":1002.4263147022411,\"y\":-198.2305006886859}},{\"width\":384,\"height\":374,\"data\":{\"id\":\"GroupNode-WXPMk\",\"type\":\"PromptTemplate\",\"node\":{\"output_types\":[],\"display_name\":\"Web Scraper\",\"documentation\":\"\",\"base_classes\":[\"StringPromptTemplate\",\"BasePromptTemplate\",\"PromptTemplate\"],\"description\":\"Fetch and parse text and links from a given URL.\",\"template\":{\"code_CustomComponent-f6nOg\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport html2text\\n\\nclass ConvertHTMLToMarkdown(CustomComponent):\\n display_name: str = \\\"HTML to Markdown\\\"\\n description: str = \\\"Converts HTML content to Markdown format.\\\"\\n\\n def build(self, html_content: Data, ignore_links: bool = False) -> str:\\n converter = html2text.HTML2Text()\\n converter.ignore_links = ignore_links\\n markdown_text = converter.handle(html_content)\\n self.status = markdown_text\\n return markdown_text\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-f6nOg\",\"field\":\"code\"},\"display_name\":\"Code\"},\"ignore_links_CustomComponent-f6nOg\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"ignore_links\",\"display_name\":\"ignore_links\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-f6nOg\",\"field\":\"ignore_links\"}},\"code_CustomComponent-FGzJJ\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport requests\\n\\nclass FetchHTMLContent(CustomComponent):\\n display_name: str = \\\"Fetch HTML\\\"\\n description: str = \\\"Fetches HTML content from a specified URL.\\\"\\n \\n def build_config(self):\\n return {\\\"url\\\": {\\\"input_types\\\": [\\\"Data\\\", \\\"str\\\"]}} \\n\\n def build(self, url: str) -> Data:\\n response = requests.get(url)\\n self.status = str(response) + \\\"\\\\n\\\\n\\\" + response.text\\n return response.text\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-FGzJJ\",\"field\":\"code\"},\"display_name\":\"Code\"},\"code_CustomComponent-0XtUN\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from bs4 import BeautifulSoup\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Data\\n\\nclass ParseHTMLContent(CustomComponent):\\n display_name: str = \\\"Parse HTML\\\"\\n description: str = \\\"Parses HTML content using Beautiful Soup.\\\"\\n\\n def build(self, html_content: Data) -> Data:\\n soup = BeautifulSoup(html_content, 'html.parser')\\n self.status = soup\\n return soup\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-0XtUN\",\"field\":\"code\"},\"display_name\":\"Code\"},\"code_CustomComponent-ODIcp\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\n\\nclass ExtractHyperlinks(CustomComponent):\\n display_name: str = \\\"Extract Hyperlinks\\\"\\n description: str = \\\"Extracts hyperlinks from parsed HTML content.\\\"\\n\\n def build(self, soup: Data) -> list:\\n links = [link.get('href') for link in soup.find_all('a')]\\n self.status = links\\n return links\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-ODIcp\",\"field\":\"code\"},\"display_name\":\"Code\"},\"output_parser_PromptTemplate-H9Udy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"BaseOutputParser\",\"list\":false,\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"output_parser\"},\"display_name\":\"Output Parser\"},\"input_types_PromptTemplate-H9Udy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_types\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false,\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"input_types\"},\"display_name\":\"Input Types\"},\"input_variables_PromptTemplate-H9Udy\":{\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":true,\"value\":[\"url\",\"html_markdown\",\"html_links\",\"query\"],\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"input_variables\"},\"display_name\":\"Input Variables\"},\"partial_variables_PromptTemplate-H9Udy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"partial_variables\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false,\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"partial_variables\"},\"display_name\":\"Partial Variables\"},\"template_PromptTemplate-H9Udy\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"password\":false,\"name\":\"template\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"type\":\"prompt\",\"list\":false,\"value\":\"Below is the HTML content (as markdown) and hyperlinks extracted from {url}\\n\\n---\\n\\nContent:\\n\\n{html_markdown}\\n\\n---\\n\\nLinks:\\n\\n{html_links}\\n\\n---\\n\\nAnswer the user query as best as possible.\\n\\nUser query:\\n\\n{query}\\n\\nAnswer:\\n\",\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"template\"},\"display_name\":\"Template\"},\"template_format_PromptTemplate-H9Udy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"f-string\",\"password\":false,\"name\":\"template_format\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":false,\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"template_format\"},\"display_name\":\"Template Format\"},\"validate_template_PromptTemplate-H9Udy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"validate_template\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"type\":\"bool\",\"list\":false,\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"validate_template\"},\"display_name\":\"Validate Template\"},\"query_PromptTemplate-H9Udy\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"give me links\",\"password\":false,\"name\":\"query\",\"display_name\":\"query\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"query\"}},\"code_CustomComponent-OACE0\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport requests\\n\\nclass FetchHTMLContent(CustomComponent):\\n display_name: str = \\\"URL Input\\\"\\n\\n def build(self, url: str) -> str:\\n return url\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-OACE0\",\"field\":\"code\"},\"display_name\":\"Code\"},\"url_CustomComponent-OACE0\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"url\",\"display_name\":\"url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-OACE0\",\"field\":\"url\"},\"value\":\"https://paperswithcode.com/\"},\"code_CustomComponent-whsQ5\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\n\\nclass ListToMarkdownBullets(CustomComponent):\\n display_name: str = \\\"List to Bullets\\\"\\n description: str = \\\"Converts a Python list into Markdown bullet points.\\\"\\n\\n def build(self, items: list) -> str:\\n markdown_bullets = '\\\\n'.join(f'* {item}' for item in items)\\n return markdown_bullets\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-whsQ5\",\"field\":\"code\"},\"display_name\":\"Code\"}},\"flow\":{\"data\":{\"nodes\":[{\"width\":384,\"height\":405,\"id\":\"CustomComponent-f6nOg\",\"type\":\"genericNode\",\"position\":{\"x\":665.2835942536854,\"y\":-371.7823429271119},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport html2text\\n\\nclass ConvertHTMLToMarkdown(CustomComponent):\\n display_name: str = \\\"HTML to Markdown\\\"\\n description: str = \\\"Converts HTML content to Markdown format.\\\"\\n\\n def build(self, html_content: Data, ignore_links: bool = False) -> str:\\n converter = html2text.HTML2Text()\\n converter.ignore_links = ignore_links\\n markdown_text = converter.handle(html_content)\\n self.status = markdown_text\\n return markdown_text\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"html_content\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"html_content\",\"display_name\":\"html_content\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Data\",\"list\":false},\"ignore_links\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"ignore_links\",\"display_name\":\"ignore_links\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false}},\"description\":\"Converts HTML content to Markdown format.\",\"base_classes\":[\"str\"],\"display_name\":\"HTML to Markdown\",\"custom_fields\":{\"html_content\":null,\"ignore_links\":null},\"output_types\":[\"str\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-f6nOg\"},\"selected\":true,\"positionAbsolute\":{\"x\":665.2835942536854,\"y\":-371.7823429271119},\"dragging\":false},{\"width\":384,\"height\":375,\"id\":\"CustomComponent-FGzJJ\",\"type\":\"genericNode\",\"position\":{\"x\":-464.4553400967736,\"y\":-225.62715888255525},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport requests\\n\\nclass FetchHTMLContent(CustomComponent):\\n display_name: str = \\\"Fetch HTML\\\"\\n description: str = \\\"Fetches HTML content from a specified URL.\\\"\\n \\n def build_config(self):\\n return {\\\"url\\\": {\\\"input_types\\\": [\\\"Data\\\", \\\"str\\\"]}} \\n\\n def build(self, url: str) -> Data:\\n response = requests.get(url)\\n self.status = str(response) + \\\"\\\\n\\\\n\\\" + response.text\\n return response.text\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"url\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"url\",\"display_name\":\"url\",\"advanced\":false,\"input_types\":[\"Data\",\"str\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"}},\"description\":\"Fetches HTML content from a specified URL.\",\"base_classes\":[\"Data\"],\"display_name\":\"Fetch HTML\",\"custom_fields\":{\"url\":null},\"output_types\":[\"Data\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-FGzJJ\"},\"selected\":true,\"dragging\":false,\"positionAbsolute\":{\"x\":-464.4553400967736,\"y\":-225.62715888255525}},{\"width\":384,\"height\":329,\"id\":\"CustomComponent-0XtUN\",\"type\":\"genericNode\",\"position\":{\"x\":214.00059169497604,\"y\":177.27071061129823},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from bs4 import BeautifulSoup\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Data\\n\\nclass ParseHTMLContent(CustomComponent):\\n display_name: str = \\\"Parse HTML\\\"\\n description: str = \\\"Parses HTML content using Beautiful Soup.\\\"\\n\\n def build(self, html_content: Data) -> Data:\\n soup = BeautifulSoup(html_content, 'html.parser')\\n self.status = soup\\n return soup\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"html_content\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"html_content\",\"display_name\":\"html_content\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Data\",\"list\":false}},\"description\":\"Parses HTML content using Beautiful Soup.\",\"base_classes\":[\"Data\"],\"display_name\":\"Parse HTML\",\"custom_fields\":{\"html_content\":null},\"output_types\":[\"Data\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-0XtUN\"},\"selected\":true,\"dragging\":false,\"positionAbsolute\":{\"x\":214.00059169497604,\"y\":177.27071061129823}},{\"width\":384,\"height\":329,\"id\":\"CustomComponent-ODIcp\",\"type\":\"genericNode\",\"position\":{\"x\":845.0502195222412,\"y\":366.54344452019404},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\n\\nclass ExtractHyperlinks(CustomComponent):\\n display_name: str = \\\"Extract Hyperlinks\\\"\\n description: str = \\\"Extracts hyperlinks from parsed HTML content.\\\"\\n\\n def build(self, soup: Data) -> list:\\n links = [link.get('href') for link in soup.find_all('a')]\\n self.status = links\\n return links\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"soup\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"soup\",\"display_name\":\"soup\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Data\",\"list\":false}},\"description\":\"Extracts hyperlinks from parsed HTML content.\",\"base_classes\":[\"list\"],\"display_name\":\"Extract Hyperlinks\",\"custom_fields\":{\"soup\":null},\"output_types\":[\"list\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-ODIcp\"},\"selected\":true,\"positionAbsolute\":{\"x\":845.0502195222412,\"y\":366.54344452019404},\"dragging\":false},{\"width\":384,\"height\":657,\"id\":\"PromptTemplate-H9Udy\",\"type\":\"genericNode\",\"position\":{\"x\":2230.389721706283,\"y\":584.4905083765256},\"data\":{\"type\":\"PromptTemplate\",\"node\":{\"template\":{\"output_parser\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"BaseOutputParser\",\"list\":false},\"input_types\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_types\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"input_variables\":{\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":true,\"value\":[\"url\",\"html_markdown\",\"html_links\",\"query\"]},\"partial_variables\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"partial_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"template\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"password\":false,\"name\":\"template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"prompt\",\"list\":false,\"value\":\"Below is the HTML content (as markdown) and hyperlinks extracted from {url}\\n\\n---\\n\\nContent:\\n\\n{html_markdown}\\n\\n---\\n\\nLinks:\\n\\n{html_links}\\n\\n---\\n\\nAnswer the user query as best as possible.\\n\\nUser query:\\n\\n{query}\\n\\nAnswer:\\n\"},\"template_format\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"f-string\",\"password\":false,\"name\":\"template_format\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":false},\"validate_template\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"validate_template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"PromptTemplate\",\"url\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"url\",\"display_name\":\"url\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"html_markdown\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"html_markdown\",\"display_name\":\"html_markdown\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"html_links\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"html_links\",\"display_name\":\"html_links\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"query\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"query\",\"display_name\":\"query\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"A prompt template for a language model.\",\"base_classes\":[\"StringPromptTemplate\",\"BasePromptTemplate\",\"PromptTemplate\"],\"name\":\"\",\"display_name\":\"PromptTemplate\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/\",\"custom_fields\":{\"\":[\"url\",\"html_markdown\",\"html_links\",\"query\"]},\"output_types\":[],\"full_path\":null,\"field_formatters\":{},\"beta\":false,\"error\":null},\"id\":\"PromptTemplate-H9Udy\"},\"selected\":true,\"positionAbsolute\":{\"x\":2230.389721706283,\"y\":584.4905083765256},\"dragging\":false},{\"width\":384,\"height\":347,\"id\":\"CustomComponent-OACE0\",\"type\":\"genericNode\",\"position\":{\"x\":-1155.9497945157625,\"y\":198.13583204151553},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport requests\\n\\nclass FetchHTMLContent(CustomComponent):\\n display_name: str = \\\"URL Input\\\"\\n\\n def build(self, url: str) -> str:\\n return url\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"url\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"url\",\"display_name\":\"url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":null,\"base_classes\":[\"str\"],\"display_name\":\"URL Input\",\"custom_fields\":{\"url\":null},\"output_types\":[\"str\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-OACE0\"},\"selected\":true,\"positionAbsolute\":{\"x\":-1155.9497945157625,\"y\":198.13583204151553},\"dragging\":false},{\"width\":384,\"height\":329,\"id\":\"CustomComponent-whsQ5\",\"type\":\"genericNode\",\"position\":{\"x\":1396.5574076376327,\"y\":694.8308714574463},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\n\\nclass ListToMarkdownBullets(CustomComponent):\\n display_name: str = \\\"List to Bullets\\\"\\n description: str = \\\"Converts a Python list into Markdown bullet points.\\\"\\n\\n def build(self, items: list) -> str:\\n markdown_bullets = '\\\\n'.join(f'* {item}' for item in items)\\n return markdown_bullets\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"items\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"items\",\"display_name\":\"items\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"list\",\"list\":true}},\"description\":\"Converts a Python list into Markdown bullet points.\",\"base_classes\":[\"str\"],\"display_name\":\"List to Bullets\",\"custom_fields\":{\"items\":null},\"output_types\":[\"str\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-whsQ5\"},\"selected\":true,\"positionAbsolute\":{\"x\":1396.5574076376327,\"y\":694.8308714574463},\"dragging\":false}],\"edges\":[{\"source\":\"CustomComponent-FGzJJ\",\"sourceHandle\":\"{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-FGzJJœ}\",\"target\":\"CustomComponent-f6nOg\",\"targetHandle\":\"{œfieldNameœ:œhtml_contentœ,œidœ:œCustomComponent-f6nOgœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"html_content\",\"id\":\"CustomComponent-f6nOg\",\"inputTypes\":null,\"type\":\"Data\"},\"sourceHandle\":{\"baseClasses\":[\"Data\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-FGzJJ\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-FGzJJ{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-FGzJJœ}-CustomComponent-f6nOg{œfieldNameœ:œhtml_contentœ,œidœ:œCustomComponent-f6nOgœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"selected\":true},{\"source\":\"CustomComponent-FGzJJ\",\"sourceHandle\":\"{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-FGzJJœ}\",\"target\":\"CustomComponent-0XtUN\",\"targetHandle\":\"{œfieldNameœ:œhtml_contentœ,œidœ:œCustomComponent-0XtUNœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"html_content\",\"id\":\"CustomComponent-0XtUN\",\"inputTypes\":null,\"type\":\"Data\"},\"sourceHandle\":{\"baseClasses\":[\"Data\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-FGzJJ\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-FGzJJ{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-FGzJJœ}-CustomComponent-0XtUN{œfieldNameœ:œhtml_contentœ,œidœ:œCustomComponent-0XtUNœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"selected\":true},{\"source\":\"CustomComponent-0XtUN\",\"sourceHandle\":\"{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-0XtUNœ}\",\"target\":\"CustomComponent-ODIcp\",\"targetHandle\":\"{œfieldNameœ:œsoupœ,œidœ:œCustomComponent-ODIcpœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"soup\",\"id\":\"CustomComponent-ODIcp\",\"inputTypes\":null,\"type\":\"Data\"},\"sourceHandle\":{\"baseClasses\":[\"Data\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-0XtUN\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-0XtUN{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-0XtUNœ}-CustomComponent-ODIcp{œfieldNameœ:œsoupœ,œidœ:œCustomComponent-ODIcpœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"selected\":true},{\"source\":\"CustomComponent-OACE0\",\"sourceHandle\":\"{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-OACE0œ}\",\"target\":\"CustomComponent-FGzJJ\",\"targetHandle\":\"{œfieldNameœ:œurlœ,œidœ:œCustomComponent-FGzJJœ,œinputTypesœ:[œDataœ,œstrœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"url\",\"id\":\"CustomComponent-FGzJJ\",\"inputTypes\":[\"Data\",\"str\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"str\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-OACE0\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-OACE0{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-OACE0œ}-CustomComponent-FGzJJ{œfieldNameœ:œurlœ,œidœ:œCustomComponent-FGzJJœ,œinputTypesœ:[œDataœ,œstrœ],œtypeœ:œstrœ}\",\"selected\":true},{\"source\":\"CustomComponent-OACE0\",\"sourceHandle\":\"{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-OACE0œ}\",\"target\":\"PromptTemplate-H9Udy\",\"targetHandle\":\"{œfieldNameœ:œurlœ,œidœ:œPromptTemplate-H9Udyœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"url\",\"id\":\"PromptTemplate-H9Udy\",\"inputTypes\":[\"Document\",\"BaseOutputParser\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"str\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-OACE0\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-OACE0{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-OACE0œ}-PromptTemplate-H9Udy{œfieldNameœ:œurlœ,œidœ:œPromptTemplate-H9Udyœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"selected\":true},{\"source\":\"CustomComponent-ODIcp\",\"sourceHandle\":\"{œbaseClassesœ:[œlistœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-ODIcpœ}\",\"target\":\"CustomComponent-whsQ5\",\"targetHandle\":\"{œfieldNameœ:œitemsœ,œidœ:œCustomComponent-whsQ5œ,œinputTypesœ:null,œtypeœ:œlistœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"items\",\"id\":\"CustomComponent-whsQ5\",\"inputTypes\":null,\"type\":\"list\"},\"sourceHandle\":{\"baseClasses\":[\"list\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-ODIcp\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-ODIcp{œbaseClassesœ:[œlistœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-ODIcpœ}-CustomComponent-whsQ5{œfieldNameœ:œitemsœ,œidœ:œCustomComponent-whsQ5œ,œinputTypesœ:null,œtypeœ:œlistœ}\",\"selected\":true},{\"source\":\"CustomComponent-whsQ5\",\"sourceHandle\":\"{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-whsQ5œ}\",\"target\":\"PromptTemplate-H9Udy\",\"targetHandle\":\"{œfieldNameœ:œhtml_linksœ,œidœ:œPromptTemplate-H9Udyœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"html_links\",\"id\":\"PromptTemplate-H9Udy\",\"inputTypes\":[\"Document\",\"BaseOutputParser\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"str\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-whsQ5\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-whsQ5{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-whsQ5œ}-PromptTemplate-H9Udy{œfieldNameœ:œhtml_linksœ,œidœ:œPromptTemplate-H9Udyœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"selected\":true},{\"source\":\"CustomComponent-f6nOg\",\"sourceHandle\":\"{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-f6nOgœ}\",\"target\":\"PromptTemplate-H9Udy\",\"targetHandle\":\"{œfieldNameœ:œhtml_markdownœ,œidœ:œPromptTemplate-H9Udyœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"html_markdown\",\"id\":\"PromptTemplate-H9Udy\",\"inputTypes\":[\"Document\",\"BaseOutputParser\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"str\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-f6nOg\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-f6nOg{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-f6nOgœ}-PromptTemplate-H9Udy{œfieldNameœ:œhtml_markdownœ,œidœ:œPromptTemplate-H9Udyœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"selected\":true}],\"viewport\":{\"x\":343.0346131188585,\"y\":341.89843948642147,\"zoom\":0.24148408223121196}},\"is_component\":false,\"name\":\"Fluffy Ptolemy\",\"description\":\"\",\"id\":\"W5oNW\"}}},\"id\":\"GroupNode-WXPMk\",\"position\":{\"x\":873.0737834322758,\"y\":598.8401015776466},\"type\":\"genericNode\",\"selected\":true,\"dragging\":false,\"positionAbsolute\":{\"x\":873.0737834322758,\"y\":598.8401015776466}}],\"edges\":[{\"source\":\"ChatOpenAI-VSAdc\",\"sourceHandle\":\"{œbaseClassesœ:[œBaseLanguageModelœ,œChatOpenAIœ,œBaseChatModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-VSAdcœ}\",\"target\":\"LLMChain-H7PBy\",\"targetHandle\":\"{œfieldNameœ:œllmœ,œidœ:œLLMChain-H7PByœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"llm\",\"id\":\"LLMChain-H7PBy\",\"inputTypes\":null,\"type\":\"BaseLanguageModel\"},\"sourceHandle\":{\"baseClasses\":[\"BaseLanguageModel\",\"ChatOpenAI\",\"BaseChatModel\",\"BaseLLM\"],\"dataType\":\"ChatOpenAI\",\"id\":\"ChatOpenAI-VSAdc\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-ChatOpenAI-VSAdc{œbaseClassesœ:[œBaseLanguageModelœ,œChatOpenAIœ,œBaseChatModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-VSAdcœ}-LLMChain-H7PBy{œfieldNameœ:œllmœ,œidœ:œLLMChain-H7PByœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\"},{\"source\":\"GroupNode-WXPMk\",\"sourceHandle\":\"{œbaseClassesœ:[œStringPromptTemplateœ,œBasePromptTemplateœ,œPromptTemplateœ],œdataTypeœ:œPromptTemplateœ,œidœ:œGroupNode-WXPMkœ}\",\"target\":\"LLMChain-H7PBy\",\"targetHandle\":\"{œfieldNameœ:œpromptœ,œidœ:œLLMChain-H7PByœ,œinputTypesœ:null,œtypeœ:œBasePromptTemplateœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"prompt\",\"id\":\"LLMChain-H7PBy\",\"inputTypes\":null,\"type\":\"BasePromptTemplate\"},\"sourceHandle\":{\"baseClasses\":[\"StringPromptTemplate\",\"BasePromptTemplate\",\"PromptTemplate\"],\"dataType\":\"PromptTemplate\",\"id\":\"GroupNode-WXPMk\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-GroupNode-WXPMk{œbaseClassesœ:[œStringPromptTemplateœ,œBasePromptTemplateœ,œPromptTemplateœ],œdataTypeœ:œPromptTemplateœ,œidœ:œGroupNode-WXPMkœ}-LLMChain-H7PBy{œfieldNameœ:œpromptœ,œidœ:œLLMChain-H7PByœ,œinputTypesœ:null,œtypeœ:œBasePromptTemplateœ}\"}],\"viewport\":{\"x\":-348.6161822813733,\"y\":121.40545291211492,\"zoom\":0.6801854262029781}},\"is_component\":false,\"updated_at\":\"2023-12-04T23:22:27.784647\",\"folder\":null,\"id\":\"efc3bf27-3cf1-4561-9a83-3df347572440\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Sad Joliot\",\"description\":\"Navigate the Networks of Conversation.\",\"data\":{\"nodes\":[{\"width\":384,\"height\":338,\"id\":\"LLMChain-RQsU1\",\"type\":\"genericNode\",\"position\":{\"x\":514.4440482813261,\"y\":528.164086188516},\"data\":{\"type\":\"LLMChain\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Callable, Optional, Union\\n\\nfrom langchain.chains import LLMChain\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import (\\n BaseLanguageModel,\\n BaseMemory,\\n BasePromptTemplate,\\n Chain,\\n)\\n\\n\\nclass LLMChainComponent(CustomComponent):\\n display_name = \\\"LLMChain\\\"\\n description = \\\"Chain to run queries against LLMs\\\"\\n\\n def build_config(self):\\n return {\\n \\\"prompt\\\": {\\\"display_name\\\": \\\"Prompt\\\"},\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"memory\\\": {\\\"display_name\\\": \\\"Memory\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n prompt: BasePromptTemplate,\\n llm: BaseLanguageModel,\\n memory: Optional[BaseMemory] = None,\\n ) -> Union[Chain, Callable]:\\n return LLMChain(prompt=prompt, llm=llm, memory=memory)\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseMemory\",\"list\":false},\"prompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"prompt\",\"display_name\":\"Prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BasePromptTemplate\",\"list\":false}},\"description\":\"Chain to run queries against LLMs\",\"base_classes\":[\"Chain\",\"Callable\"],\"display_name\":\"LLMChain\",\"custom_fields\":{\"llm\":null,\"memory\":null,\"prompt\":null},\"output_types\":[\"LLMChain\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"LLMChain-RQsU1\"},\"selected\":false,\"positionAbsolute\":{\"x\":514.4440482813261,\"y\":528.164086188516}},{\"width\":384,\"height\":626,\"id\":\"ChatOpenAI-NTTcv\",\"type\":\"genericNode\",\"position\":{\"x\":-221.33853765781578,\"y\":-35.48749923706055},\"data\":{\"type\":\"ChatOpenAI\",\"node\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"list\":true},\"async_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"async_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"default_headers\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"default_query\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_query\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"http_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"http_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":2,\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"max_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"max_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"gpt-4-1106-preview\",\"password\":false,\"options\":[\"gpt-4-1106-preview\",\"gpt-4\",\"gpt-4-32k\",\"gpt-3.5-turbo\",\"gpt-3.5-turbo-16k\"],\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"n\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"n\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":false,\"dynamic\":false,\"info\":\"\\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\\n\",\"type\":\"str\",\"list\":false},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"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\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"0.1\",\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ChatOpenAI\"},\"description\":\"`OpenAI` Chat large language models API.\",\"base_classes\":[\"BaseLanguageModel\",\"ChatOpenAI\",\"BaseChatModel\",\"BaseLLM\"],\"display_name\":\"ChatOpenAI\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai\",\"beta\":false,\"error\":null},\"id\":\"ChatOpenAI-NTTcv\"},\"selected\":false,\"positionAbsolute\":{\"x\":-221.33853765781578,\"y\":-35.48749923706055}},{\"width\":384,\"height\":374,\"id\":\"PromptTemplate-VELMV\",\"type\":\"genericNode\",\"position\":{\"x\":-222,\"y\":682.560723386973},\"data\":{\"id\":\"PromptTemplate-VELMV\",\"type\":\"PromptTemplate\",\"node\":{\"output_types\":[],\"display_name\":\"Web Scraper\",\"documentation\":\"\",\"base_classes\":[\"StringPromptTemplate\",\"BasePromptTemplate\",\"PromptTemplate\"],\"description\":\"Fetch and parse text and links from a given URL.\",\"template\":{\"code_CustomComponent-f6nOg\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport html2text\\n\\nclass ConvertHTMLToMarkdown(CustomComponent):\\n display_name: str = \\\"HTML to Markdown\\\"\\n description: str = \\\"Converts HTML content to Markdown format.\\\"\\n\\n def build(self, html_content: Data, ignore_links: bool = False) -> str:\\n converter = html2text.HTML2Text()\\n converter.ignore_links = ignore_links\\n markdown_text = converter.handle(html_content)\\n self.status = markdown_text\\n return markdown_text\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-f6nOg\",\"field\":\"code\"},\"display_name\":\"Code\"},\"ignore_links_CustomComponent-f6nOg\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"ignore_links\",\"display_name\":\"ignore_links\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-f6nOg\",\"field\":\"ignore_links\"}},\"code_CustomComponent-FGzJJ\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport requests\\n\\nclass FetchHTMLContent(CustomComponent):\\n display_name: str = \\\"Fetch HTML\\\"\\n description: str = \\\"Fetches HTML content from a specified URL.\\\"\\n \\n def build_config(self):\\n return {\\\"url\\\": {\\\"input_types\\\": [\\\"Data\\\", \\\"str\\\"]}} \\n\\n def build(self, url: str) -> Data:\\n response = requests.get(url)\\n self.status = str(response) + \\\"\\\\n\\\\n\\\" + response.text\\n return response.text\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-FGzJJ\",\"field\":\"code\"},\"display_name\":\"Code\"},\"code_CustomComponent-0XtUN\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from bs4 import BeautifulSoup\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Data\\n\\nclass ParseHTMLContent(CustomComponent):\\n display_name: str = \\\"Parse HTML\\\"\\n description: str = \\\"Parses HTML content using Beautiful Soup.\\\"\\n\\n def build(self, html_content: Data) -> Data:\\n soup = BeautifulSoup(html_content, 'html.parser')\\n self.status = soup\\n return soup\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-0XtUN\",\"field\":\"code\"},\"display_name\":\"Code\"},\"code_CustomComponent-ODIcp\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\n\\nclass ExtractHyperlinks(CustomComponent):\\n display_name: str = \\\"Extract Hyperlinks\\\"\\n description: str = \\\"Extracts hyperlinks from parsed HTML content.\\\"\\n\\n def build(self, soup: Data) -> list:\\n links = [link.get('href') for link in soup.find_all('a')]\\n self.status = links\\n return links\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-ODIcp\",\"field\":\"code\"},\"display_name\":\"Code\"},\"output_parser_PromptTemplate-H9Udy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"BaseOutputParser\",\"list\":false,\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"output_parser\"},\"display_name\":\"Output Parser\"},\"input_types_PromptTemplate-H9Udy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_types\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false,\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"input_types\"},\"display_name\":\"Input Types\"},\"input_variables_PromptTemplate-H9Udy\":{\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":true,\"value\":[\"url\",\"html_markdown\",\"html_links\",\"query\"],\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"input_variables\"},\"display_name\":\"Input Variables\"},\"partial_variables_PromptTemplate-H9Udy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"partial_variables\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false,\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"partial_variables\"},\"display_name\":\"Partial Variables\"},\"template_PromptTemplate-H9Udy\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"password\":false,\"name\":\"template\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"type\":\"prompt\",\"list\":false,\"value\":\"Below is the HTML content (as markdown) and hyperlinks extracted from {url}\\n\\n---\\n\\nContent:\\n\\n{html_markdown}\\n\\n---\\n\\nLinks:\\n\\n{html_links}\\n\\n---\\n\\nAnswer the user query as best as possible.\\n\\nUser query:\\n\\n{query}\\n\\nAnswer:\\n\",\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"template\"},\"display_name\":\"Template\"},\"template_format_PromptTemplate-H9Udy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"f-string\",\"password\":false,\"name\":\"template_format\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":false,\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"template_format\"},\"display_name\":\"Template Format\"},\"validate_template_PromptTemplate-H9Udy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"validate_template\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"type\":\"bool\",\"list\":false,\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"validate_template\"},\"display_name\":\"Validate Template\"},\"query_PromptTemplate-H9Udy\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"query\",\"display_name\":\"query\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"query\"}},\"code_CustomComponent-OACE0\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport requests\\n\\nclass FetchHTMLContent(CustomComponent):\\n display_name: str = \\\"URL Input\\\"\\n\\n def build(self, url: str) -> str:\\n return url\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-OACE0\",\"field\":\"code\"},\"display_name\":\"Code\"},\"url_CustomComponent-OACE0\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"url\",\"display_name\":\"url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-OACE0\",\"field\":\"url\"},\"value\":\"https://paperswithcode.com/\"},\"code_CustomComponent-whsQ5\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\n\\nclass ListToMarkdownBullets(CustomComponent):\\n display_name: str = \\\"List to Bullets\\\"\\n description: str = \\\"Converts a Python list into Markdown bullet points.\\\"\\n\\n def build(self, items: list) -> str:\\n markdown_bullets = '\\\\n'.join(f'* {item}' for item in items)\\n return markdown_bullets\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-whsQ5\",\"field\":\"code\"},\"display_name\":\"Code\"}},\"flow\":{\"data\":{\"nodes\":[{\"width\":384,\"height\":405,\"id\":\"CustomComponent-f6nOg\",\"type\":\"genericNode\",\"position\":{\"x\":665.2835942536854,\"y\":-371.7823429271119},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport html2text\\n\\nclass ConvertHTMLToMarkdown(CustomComponent):\\n display_name: str = \\\"HTML to Markdown\\\"\\n description: str = \\\"Converts HTML content to Markdown format.\\\"\\n\\n def build(self, html_content: Data, ignore_links: bool = False) -> str:\\n converter = html2text.HTML2Text()\\n converter.ignore_links = ignore_links\\n markdown_text = converter.handle(html_content)\\n self.status = markdown_text\\n return markdown_text\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"html_content\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"html_content\",\"display_name\":\"html_content\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Data\",\"list\":false},\"ignore_links\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"ignore_links\",\"display_name\":\"ignore_links\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false}},\"description\":\"Converts HTML content to Markdown format.\",\"base_classes\":[\"str\"],\"display_name\":\"HTML to Markdown\",\"custom_fields\":{\"html_content\":null,\"ignore_links\":null},\"output_types\":[\"str\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-f6nOg\"},\"selected\":true,\"positionAbsolute\":{\"x\":665.2835942536854,\"y\":-371.7823429271119},\"dragging\":false},{\"width\":384,\"height\":375,\"id\":\"CustomComponent-FGzJJ\",\"type\":\"genericNode\",\"position\":{\"x\":-464.4553400967736,\"y\":-225.62715888255525},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport requests\\n\\nclass FetchHTMLContent(CustomComponent):\\n display_name: str = \\\"Fetch HTML\\\"\\n description: str = \\\"Fetches HTML content from a specified URL.\\\"\\n \\n def build_config(self):\\n return {\\\"url\\\": {\\\"input_types\\\": [\\\"Data\\\", \\\"str\\\"]}} \\n\\n def build(self, url: str) -> Data:\\n response = requests.get(url)\\n self.status = str(response) + \\\"\\\\n\\\\n\\\" + response.text\\n return response.text\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"url\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"url\",\"display_name\":\"url\",\"advanced\":false,\"input_types\":[\"Data\",\"str\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"}},\"description\":\"Fetches HTML content from a specified URL.\",\"base_classes\":[\"Data\"],\"display_name\":\"Fetch HTML\",\"custom_fields\":{\"url\":null},\"output_types\":[\"Data\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-FGzJJ\"},\"selected\":true,\"dragging\":false,\"positionAbsolute\":{\"x\":-464.4553400967736,\"y\":-225.62715888255525}},{\"width\":384,\"height\":329,\"id\":\"CustomComponent-0XtUN\",\"type\":\"genericNode\",\"position\":{\"x\":214.00059169497604,\"y\":177.27071061129823},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from bs4 import BeautifulSoup\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Data\\n\\nclass ParseHTMLContent(CustomComponent):\\n display_name: str = \\\"Parse HTML\\\"\\n description: str = \\\"Parses HTML content using Beautiful Soup.\\\"\\n\\n def build(self, html_content: Data) -> Data:\\n soup = BeautifulSoup(html_content, 'html.parser')\\n self.status = soup\\n return soup\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"html_content\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"html_content\",\"display_name\":\"html_content\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Data\",\"list\":false}},\"description\":\"Parses HTML content using Beautiful Soup.\",\"base_classes\":[\"Data\"],\"display_name\":\"Parse HTML\",\"custom_fields\":{\"html_content\":null},\"output_types\":[\"Data\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-0XtUN\"},\"selected\":true,\"dragging\":false,\"positionAbsolute\":{\"x\":214.00059169497604,\"y\":177.27071061129823}},{\"width\":384,\"height\":329,\"id\":\"CustomComponent-ODIcp\",\"type\":\"genericNode\",\"position\":{\"x\":845.0502195222412,\"y\":366.54344452019404},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\n\\nclass ExtractHyperlinks(CustomComponent):\\n display_name: str = \\\"Extract Hyperlinks\\\"\\n description: str = \\\"Extracts hyperlinks from parsed HTML content.\\\"\\n\\n def build(self, soup: Data) -> list:\\n links = [link.get('href') for link in soup.find_all('a')]\\n self.status = links\\n return links\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"soup\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"soup\",\"display_name\":\"soup\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Data\",\"list\":false}},\"description\":\"Extracts hyperlinks from parsed HTML content.\",\"base_classes\":[\"list\"],\"display_name\":\"Extract Hyperlinks\",\"custom_fields\":{\"soup\":null},\"output_types\":[\"list\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-ODIcp\"},\"selected\":true,\"positionAbsolute\":{\"x\":845.0502195222412,\"y\":366.54344452019404},\"dragging\":false},{\"width\":384,\"height\":657,\"id\":\"PromptTemplate-H9Udy\",\"type\":\"genericNode\",\"position\":{\"x\":2230.389721706283,\"y\":584.4905083765256},\"data\":{\"type\":\"PromptTemplate\",\"node\":{\"template\":{\"output_parser\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"BaseOutputParser\",\"list\":false},\"input_types\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_types\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"input_variables\":{\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":true,\"value\":[\"url\",\"html_markdown\",\"html_links\",\"query\"]},\"partial_variables\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"partial_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"template\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"password\":false,\"name\":\"template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"prompt\",\"list\":false,\"value\":\"Below is the HTML content (as markdown) and hyperlinks extracted from {url}\\n\\n---\\n\\nContent:\\n\\n{html_markdown}\\n\\n---\\n\\nLinks:\\n\\n{html_links}\\n\\n---\\n\\nAnswer the user query as best as possible.\\n\\nUser query:\\n\\n{query}\\n\\nAnswer:\\n\"},\"template_format\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"f-string\",\"password\":false,\"name\":\"template_format\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":false},\"validate_template\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"validate_template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"PromptTemplate\",\"url\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"url\",\"display_name\":\"url\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"html_markdown\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"html_markdown\",\"display_name\":\"html_markdown\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"html_links\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"html_links\",\"display_name\":\"html_links\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"query\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"query\",\"display_name\":\"query\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"A prompt template for a language model.\",\"base_classes\":[\"StringPromptTemplate\",\"BasePromptTemplate\",\"PromptTemplate\"],\"name\":\"\",\"display_name\":\"PromptTemplate\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/\",\"custom_fields\":{\"\":[\"url\",\"html_markdown\",\"html_links\",\"query\"]},\"output_types\":[],\"full_path\":null,\"field_formatters\":{},\"beta\":false,\"error\":null},\"id\":\"PromptTemplate-H9Udy\"},\"selected\":true,\"positionAbsolute\":{\"x\":2230.389721706283,\"y\":584.4905083765256},\"dragging\":false},{\"width\":384,\"height\":347,\"id\":\"CustomComponent-OACE0\",\"type\":\"genericNode\",\"position\":{\"x\":-1155.9497945157625,\"y\":198.13583204151553},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport requests\\n\\nclass FetchHTMLContent(CustomComponent):\\n display_name: str = \\\"URL Input\\\"\\n\\n def build(self, url: str) -> str:\\n return url\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"url\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"url\",\"display_name\":\"url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":null,\"base_classes\":[\"str\"],\"display_name\":\"URL Input\",\"custom_fields\":{\"url\":null},\"output_types\":[\"str\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-OACE0\"},\"selected\":true,\"positionAbsolute\":{\"x\":-1155.9497945157625,\"y\":198.13583204151553},\"dragging\":false},{\"width\":384,\"height\":329,\"id\":\"CustomComponent-whsQ5\",\"type\":\"genericNode\",\"position\":{\"x\":1396.5574076376327,\"y\":694.8308714574463},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\n\\nclass ListToMarkdownBullets(CustomComponent):\\n display_name: str = \\\"List to Bullets\\\"\\n description: str = \\\"Converts a Python list into Markdown bullet points.\\\"\\n\\n def build(self, items: list) -> str:\\n markdown_bullets = '\\\\n'.join(f'* {item}' for item in items)\\n return markdown_bullets\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"items\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"items\",\"display_name\":\"items\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"list\",\"list\":true}},\"description\":\"Converts a Python list into Markdown bullet points.\",\"base_classes\":[\"str\"],\"display_name\":\"List to Bullets\",\"custom_fields\":{\"items\":null},\"output_types\":[\"str\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-whsQ5\"},\"selected\":true,\"positionAbsolute\":{\"x\":1396.5574076376327,\"y\":694.8308714574463},\"dragging\":false}],\"edges\":[{\"source\":\"CustomComponent-FGzJJ\",\"sourceHandle\":\"{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-FGzJJœ}\",\"target\":\"CustomComponent-f6nOg\",\"targetHandle\":\"{œfieldNameœ:œhtml_contentœ,œidœ:œCustomComponent-f6nOgœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"html_content\",\"id\":\"CustomComponent-f6nOg\",\"inputTypes\":null,\"type\":\"Data\"},\"sourceHandle\":{\"baseClasses\":[\"Data\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-FGzJJ\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-FGzJJ{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-FGzJJœ}-CustomComponent-f6nOg{œfieldNameœ:œhtml_contentœ,œidœ:œCustomComponent-f6nOgœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"selected\":true},{\"source\":\"CustomComponent-FGzJJ\",\"sourceHandle\":\"{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-FGzJJœ}\",\"target\":\"CustomComponent-0XtUN\",\"targetHandle\":\"{œfieldNameœ:œhtml_contentœ,œidœ:œCustomComponent-0XtUNœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"html_content\",\"id\":\"CustomComponent-0XtUN\",\"inputTypes\":null,\"type\":\"Data\"},\"sourceHandle\":{\"baseClasses\":[\"Data\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-FGzJJ\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-FGzJJ{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-FGzJJœ}-CustomComponent-0XtUN{œfieldNameœ:œhtml_contentœ,œidœ:œCustomComponent-0XtUNœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"selected\":true},{\"source\":\"CustomComponent-0XtUN\",\"sourceHandle\":\"{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-0XtUNœ}\",\"target\":\"CustomComponent-ODIcp\",\"targetHandle\":\"{œfieldNameœ:œsoupœ,œidœ:œCustomComponent-ODIcpœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"soup\",\"id\":\"CustomComponent-ODIcp\",\"inputTypes\":null,\"type\":\"Data\"},\"sourceHandle\":{\"baseClasses\":[\"Data\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-0XtUN\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-0XtUN{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-0XtUNœ}-CustomComponent-ODIcp{œfieldNameœ:œsoupœ,œidœ:œCustomComponent-ODIcpœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"selected\":true},{\"source\":\"CustomComponent-OACE0\",\"sourceHandle\":\"{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-OACE0œ}\",\"target\":\"CustomComponent-FGzJJ\",\"targetHandle\":\"{œfieldNameœ:œurlœ,œidœ:œCustomComponent-FGzJJœ,œinputTypesœ:[œDataœ,œstrœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"url\",\"id\":\"CustomComponent-FGzJJ\",\"inputTypes\":[\"Data\",\"str\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"str\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-OACE0\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-OACE0{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-OACE0œ}-CustomComponent-FGzJJ{œfieldNameœ:œurlœ,œidœ:œCustomComponent-FGzJJœ,œinputTypesœ:[œDataœ,œstrœ],œtypeœ:œstrœ}\",\"selected\":true},{\"source\":\"CustomComponent-OACE0\",\"sourceHandle\":\"{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-OACE0œ}\",\"target\":\"PromptTemplate-H9Udy\",\"targetHandle\":\"{œfieldNameœ:œurlœ,œidœ:œPromptTemplate-H9Udyœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"url\",\"id\":\"PromptTemplate-H9Udy\",\"inputTypes\":[\"Document\",\"BaseOutputParser\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"str\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-OACE0\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-OACE0{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-OACE0œ}-PromptTemplate-H9Udy{œfieldNameœ:œurlœ,œidœ:œPromptTemplate-H9Udyœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"selected\":true},{\"source\":\"CustomComponent-ODIcp\",\"sourceHandle\":\"{œbaseClassesœ:[œlistœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-ODIcpœ}\",\"target\":\"CustomComponent-whsQ5\",\"targetHandle\":\"{œfieldNameœ:œitemsœ,œidœ:œCustomComponent-whsQ5œ,œinputTypesœ:null,œtypeœ:œlistœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"items\",\"id\":\"CustomComponent-whsQ5\",\"inputTypes\":null,\"type\":\"list\"},\"sourceHandle\":{\"baseClasses\":[\"list\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-ODIcp\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-ODIcp{œbaseClassesœ:[œlistœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-ODIcpœ}-CustomComponent-whsQ5{œfieldNameœ:œitemsœ,œidœ:œCustomComponent-whsQ5œ,œinputTypesœ:null,œtypeœ:œlistœ}\",\"selected\":true},{\"source\":\"CustomComponent-whsQ5\",\"sourceHandle\":\"{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-whsQ5œ}\",\"target\":\"PromptTemplate-H9Udy\",\"targetHandle\":\"{œfieldNameœ:œhtml_linksœ,œidœ:œPromptTemplate-H9Udyœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"html_links\",\"id\":\"PromptTemplate-H9Udy\",\"inputTypes\":[\"Document\",\"BaseOutputParser\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"str\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-whsQ5\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-whsQ5{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-whsQ5œ}-PromptTemplate-H9Udy{œfieldNameœ:œhtml_linksœ,œidœ:œPromptTemplate-H9Udyœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"selected\":true},{\"source\":\"CustomComponent-f6nOg\",\"sourceHandle\":\"{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-f6nOgœ}\",\"target\":\"PromptTemplate-H9Udy\",\"targetHandle\":\"{œfieldNameœ:œhtml_markdownœ,œidœ:œPromptTemplate-H9Udyœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"html_markdown\",\"id\":\"PromptTemplate-H9Udy\",\"inputTypes\":[\"Document\",\"BaseOutputParser\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"str\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-f6nOg\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-f6nOg{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-f6nOgœ}-PromptTemplate-H9Udy{œfieldNameœ:œhtml_markdownœ,œidœ:œPromptTemplate-H9Udyœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"selected\":true}],\"viewport\":{\"x\":343.0346131188585,\"y\":341.89843948642147,\"zoom\":0.24148408223121196}},\"is_component\":false,\"name\":\"Fluffy Ptolemy\",\"description\":\"\",\"id\":\"W5oNW\"}}},\"selected\":false,\"positionAbsolute\":{\"x\":-222,\"y\":682.560723386973}}],\"edges\":[{\"source\":\"ChatOpenAI-NTTcv\",\"target\":\"LLMChain-RQsU1\",\"sourceHandle\":\"{œbaseClassesœ:[œBaseLanguageModelœ,œChatOpenAIœ,œBaseChatModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-NTTcvœ}\",\"targetHandle\":\"{œfieldNameœ:œllmœ,œidœ:œLLMChain-RQsU1œ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\",\"id\":\"reactflow__edge-ChatOpenAI-NTTcv{œbaseClassesœ:[œBaseLanguageModelœ,œChatOpenAIœ,œBaseChatModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-NTTcvœ}-LLMChain-RQsU1{œfieldNameœ:œllmœ,œidœ:œLLMChain-RQsU1œ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"llm\",\"id\":\"LLMChain-RQsU1\",\"inputTypes\":null,\"type\":\"BaseLanguageModel\"},\"sourceHandle\":{\"baseClasses\":[\"BaseLanguageModel\",\"ChatOpenAI\",\"BaseChatModel\",\"BaseLLM\"],\"dataType\":\"ChatOpenAI\",\"id\":\"ChatOpenAI-NTTcv\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 \",\"animated\":false,\"selected\":false},{\"source\":\"PromptTemplate-VELMV\",\"target\":\"LLMChain-RQsU1\",\"sourceHandle\":\"{œbaseClassesœ:[œStringPromptTemplateœ,œBasePromptTemplateœ,œPromptTemplateœ],œdataTypeœ:œPromptTemplateœ,œidœ:œPromptTemplate-VELMVœ}\",\"targetHandle\":\"{œfieldNameœ:œpromptœ,œidœ:œLLMChain-RQsU1œ,œinputTypesœ:null,œtypeœ:œBasePromptTemplateœ}\",\"id\":\"reactflow__edge-PromptTemplate-VELMV{œbaseClassesœ:[œStringPromptTemplateœ,œBasePromptTemplateœ,œPromptTemplateœ],œdataTypeœ:œPromptTemplateœ,œidœ:œPromptTemplate-VELMVœ}-LLMChain-RQsU1{œfieldNameœ:œpromptœ,œidœ:œLLMChain-RQsU1œ,œinputTypesœ:null,œtypeœ:œBasePromptTemplateœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"prompt\",\"id\":\"LLMChain-RQsU1\",\"inputTypes\":null,\"type\":\"BasePromptTemplate\"},\"sourceHandle\":{\"baseClasses\":[\"StringPromptTemplate\",\"BasePromptTemplate\",\"PromptTemplate\"],\"dataType\":\"PromptTemplate\",\"id\":\"PromptTemplate-VELMV\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 \",\"animated\":false,\"selected\":false}],\"viewport\":{\"x\":298.29888454238517,\"y\":96.95765543775741,\"zoom\":0.5140569133280332}},\"is_component\":false,\"updated_at\":\"2023-12-04T23:23:08.584967\",\"folder\":null,\"id\":\"5df79f1d-f592-4d59-8c0f-9f3c2f6465b1\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Silly Pasteur\",\"description\":\"Nurture NLP Nodes Here.\",\"data\":{\"nodes\":[{\"width\":384,\"height\":338,\"id\":\"LLMChain-cHel8\",\"type\":\"genericNode\",\"position\":{\"x\":547.3876889720291,\"y\":299.2057833881307},\"data\":{\"type\":\"LLMChain\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Callable, Optional, Union\\n\\nfrom langchain.chains import LLMChain\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import (\\n BaseLanguageModel,\\n BaseMemory,\\n BasePromptTemplate,\\n Chain,\\n)\\n\\n\\nclass LLMChainComponent(CustomComponent):\\n display_name = \\\"LLMChain\\\"\\n description = \\\"Chain to run queries against LLMs\\\"\\n\\n def build_config(self):\\n return {\\n \\\"prompt\\\": {\\\"display_name\\\": \\\"Prompt\\\"},\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"memory\\\": {\\\"display_name\\\": \\\"Memory\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n prompt: BasePromptTemplate,\\n llm: BaseLanguageModel,\\n memory: Optional[BaseMemory] = None,\\n ) -> Union[Chain, Callable]:\\n return LLMChain(prompt=prompt, llm=llm, memory=memory)\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseMemory\",\"list\":false},\"prompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"prompt\",\"display_name\":\"Prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BasePromptTemplate\",\"list\":false}},\"description\":\"Chain to run queries against LLMs\",\"base_classes\":[\"Chain\",\"Callable\"],\"display_name\":\"LLMChain\",\"custom_fields\":{\"llm\":null,\"memory\":null,\"prompt\":null},\"output_types\":[\"LLMChain\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"LLMChain-cHel8\"},\"selected\":false,\"positionAbsolute\":{\"x\":547.3876889720291,\"y\":299.2057833881307},\"dragging\":false},{\"width\":384,\"height\":626,\"id\":\"ChatOpenAI-LA6y0\",\"type\":\"genericNode\",\"position\":{\"x\":-272.94405331278074,\"y\":-603.148171441675},\"data\":{\"type\":\"ChatOpenAI\",\"node\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"list\":true},\"async_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"async_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"default_headers\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"default_query\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_query\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"http_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"http_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":2,\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"max_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"max_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"gpt-4-1106-preview\",\"password\":false,\"options\":[\"gpt-4-1106-preview\",\"gpt-4\",\"gpt-4-32k\",\"gpt-3.5-turbo\",\"gpt-3.5-turbo-16k\"],\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"n\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"n\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":false,\"dynamic\":false,\"info\":\"\\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\\n\",\"type\":\"str\",\"list\":false},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"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\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"0.1\",\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ChatOpenAI\"},\"description\":\"`OpenAI` Chat large language models API.\",\"base_classes\":[\"BaseLanguageModel\",\"ChatOpenAI\",\"BaseChatModel\",\"BaseLLM\"],\"display_name\":\"ChatOpenAI\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai\",\"beta\":false,\"error\":null},\"id\":\"ChatOpenAI-LA6y0\"},\"selected\":false,\"dragging\":false,\"positionAbsolute\":{\"x\":-272.94405331278074,\"y\":-603.148171441675}},{\"width\":384,\"height\":404,\"id\":\"CustomComponent-ZNoRM\",\"type\":\"genericNode\",\"position\":{\"x\":-103.65741264289085,\"y\":134.62332404764658},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport html2text\\n\\nclass ConvertHTMLToMarkdown(CustomComponent):\\n display_name: str = \\\"HTML to Markdown\\\"\\n description: str = \\\"Converts HTML content to Markdown format.\\\"\\n\\n def build(self, html_content: Data, ignore_links: bool = False) -> str:\\n converter = html2text.HTML2Text()\\n converter.ignore_links = ignore_links\\n markdown_text = converter.handle(html_content)\\n self.status = markdown_text\\n return markdown_text\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"display_name\":\"code\"},\"_type\":\"CustomComponent\",\"html_content\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"html_content\",\"display_name\":\"html_content\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Data\",\"list\":false},\"ignore_links\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"ignore_links\",\"display_name\":\"ignore_links\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false}},\"description\":\"Converts HTML content to Markdown format.\",\"base_classes\":[\"str\"],\"display_name\":\"HTML to Markdown\",\"custom_fields\":{\"html_content\":null,\"ignore_links\":null},\"output_types\":[\"str\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-ZNoRM\"},\"selected\":false,\"positionAbsolute\":{\"x\":-103.65741264289085,\"y\":134.62332404764658},\"dragging\":false},{\"width\":384,\"height\":374,\"id\":\"CustomComponent-zNSTv\",\"type\":\"genericNode\",\"position\":{\"x\":-1233.3963469933499,\"y\":280.77850809220325},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport requests\\n\\nclass FetchHTMLContent(CustomComponent):\\n display_name: str = \\\"Fetch HTML\\\"\\n description: str = \\\"Fetches HTML content from a specified URL.\\\"\\n \\n def build_config(self):\\n return {\\\"url\\\": {\\\"input_types\\\": [\\\"Data\\\", \\\"str\\\"]}} \\n\\n def build(self, url: str) -> Data:\\n response = requests.get(url)\\n self.status = str(response) + \\\"\\\\n\\\\n\\\" + response.text\\n return response.text\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"display_name\":\"code\"},\"_type\":\"CustomComponent\",\"url\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"url\",\"display_name\":\"url\",\"advanced\":false,\"input_types\":[\"Data\",\"str\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"}},\"description\":\"Fetches HTML content from a specified URL.\",\"base_classes\":[\"Data\"],\"display_name\":\"Fetch HTML\",\"custom_fields\":{\"url\":null},\"output_types\":[\"Data\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-zNSTv\"},\"selected\":false,\"dragging\":false,\"positionAbsolute\":{\"x\":-1233.3963469933499,\"y\":280.77850809220325}},{\"width\":384,\"height\":328,\"id\":\"CustomComponent-Ihm2o\",\"type\":\"genericNode\",\"position\":{\"x\":-554.9404152016002,\"y\":683.6763775860567},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from bs4 import BeautifulSoup\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Data\\n\\nclass ParseHTMLContent(CustomComponent):\\n display_name: str = \\\"Parse HTML\\\"\\n description: str = \\\"Parses HTML content using Beautiful Soup.\\\"\\n\\n def build(self, html_content: Data) -> Data:\\n soup = BeautifulSoup(html_content, 'html.parser')\\n self.status = soup\\n return soup\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"display_name\":\"code\"},\"_type\":\"CustomComponent\",\"html_content\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"html_content\",\"display_name\":\"html_content\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Data\",\"list\":false}},\"description\":\"Parses HTML content using Beautiful Soup.\",\"base_classes\":[\"Data\"],\"display_name\":\"Parse HTML\",\"custom_fields\":{\"html_content\":null},\"output_types\":[\"Data\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-Ihm2o\"},\"selected\":false,\"dragging\":false,\"positionAbsolute\":{\"x\":-554.9404152016002,\"y\":683.6763775860567}},{\"width\":384,\"height\":328,\"id\":\"CustomComponent-6ST9l\",\"type\":\"genericNode\",\"position\":{\"x\":76.10921262566495,\"y\":872.9491114949525},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\n\\nclass ExtractHyperlinks(CustomComponent):\\n display_name: str = \\\"Extract Hyperlinks\\\"\\n description: str = \\\"Extracts hyperlinks from parsed HTML content.\\\"\\n\\n def build(self, soup: Data) -> list:\\n links = [link.get('href') for link in soup.find_all('a')]\\n self.status = links\\n return links\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"display_name\":\"code\"},\"_type\":\"CustomComponent\",\"soup\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"soup\",\"display_name\":\"soup\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Data\",\"list\":false}},\"description\":\"Extracts hyperlinks from parsed HTML content.\",\"base_classes\":[\"list\"],\"display_name\":\"Extract Hyperlinks\",\"custom_fields\":{\"soup\":null},\"output_types\":[\"list\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-6ST9l\"},\"selected\":false,\"positionAbsolute\":{\"x\":76.10921262566495,\"y\":872.9491114949525},\"dragging\":false},{\"width\":384,\"height\":654,\"id\":\"PromptTemplate-l35W1\",\"type\":\"genericNode\",\"position\":{\"x\":1461.4487148097069,\"y\":1090.896175351284},\"data\":{\"type\":\"PromptTemplate\",\"node\":{\"template\":{\"output_parser\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"BaseOutputParser\",\"list\":false,\"display_name\":\"output_parser\"},\"input_types\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_types\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false,\"display_name\":\"input_types\"},\"input_variables\":{\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":true,\"value\":[\"url\",\"html_markdown\",\"html_links\",\"query\"],\"display_name\":\"input_variables\"},\"partial_variables\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"partial_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false,\"display_name\":\"partial_variables\"},\"template\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"password\":false,\"name\":\"template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"prompt\",\"list\":false,\"value\":\"Below is the HTML content (as markdown) and hyperlinks extracted from {url}\\n\\n---\\n\\nContent:\\n\\n{html_markdown}\\n\\n---\\n\\nLinks:\\n\\n{html_links}\\n\\n---\\n\\nAnswer the user query as best as possible.\\n\\nUser query:\\n\\n{query}\\n\\nAnswer:\\n\",\"display_name\":\"template\"},\"template_format\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"f-string\",\"password\":false,\"name\":\"template_format\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":false,\"display_name\":\"template_format\"},\"validate_template\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"validate_template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"bool\",\"list\":false,\"display_name\":\"validate_template\"},\"_type\":\"PromptTemplate\",\"url\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"url\",\"display_name\":\"url\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"html_markdown\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"html_markdown\",\"display_name\":\"html_markdown\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"html_links\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"html_links\",\"display_name\":\"html_links\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"query\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"query\",\"display_name\":\"query\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"A prompt template for a language model.\",\"base_classes\":[\"StringPromptTemplate\",\"BasePromptTemplate\",\"PromptTemplate\"],\"name\":\"\",\"display_name\":\"PromptTemplate\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/\",\"custom_fields\":{\"\":[\"url\",\"html_markdown\",\"html_links\",\"query\"]},\"output_types\":[],\"full_path\":null,\"field_formatters\":{},\"beta\":false,\"error\":null},\"id\":\"PromptTemplate-l35W1\"},\"selected\":false,\"positionAbsolute\":{\"x\":1461.4487148097069,\"y\":1090.896175351284},\"dragging\":false},{\"width\":384,\"height\":346,\"id\":\"CustomComponent-iTLf4\",\"type\":\"genericNode\",\"position\":{\"x\":-1924.8908014123388,\"y\":704.5414990162741},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport requests\\n\\nclass FetchHTMLContent(CustomComponent):\\n display_name: str = \\\"URL Input\\\"\\n\\n def build(self, url: str) -> str:\\n return url\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"display_name\":\"code\"},\"_type\":\"CustomComponent\",\"url\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"url\",\"display_name\":\"url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"https://paperswithcode.com/\"}},\"description\":null,\"base_classes\":[\"str\"],\"display_name\":\"URL Input\",\"custom_fields\":{\"url\":null},\"output_types\":[\"str\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-iTLf4\"},\"selected\":false,\"positionAbsolute\":{\"x\":-1924.8908014123388,\"y\":704.5414990162741},\"dragging\":false},{\"width\":384,\"height\":328,\"id\":\"CustomComponent-jWLUz\",\"type\":\"genericNode\",\"position\":{\"x\":627.6164007410564,\"y\":1201.2365384322047},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\n\\nclass ListToMarkdownBullets(CustomComponent):\\n display_name: str = \\\"List to Bullets\\\"\\n description: str = \\\"Converts a Python list into Markdown bullet points.\\\"\\n\\n def build(self, items: list) -> str:\\n markdown_bullets = '\\\\n'.join(f'* {item}' for item in items)\\n return markdown_bullets\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"display_name\":\"code\"},\"_type\":\"CustomComponent\",\"items\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"items\",\"display_name\":\"items\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"list\",\"list\":true}},\"description\":\"Converts a Python list into Markdown bullet points.\",\"base_classes\":[\"str\"],\"display_name\":\"List to Bullets\",\"custom_fields\":{\"items\":null},\"output_types\":[\"str\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-jWLUz\"},\"selected\":false,\"positionAbsolute\":{\"x\":627.6164007410564,\"y\":1201.2365384322047},\"dragging\":false}],\"edges\":[{\"source\":\"ChatOpenAI-LA6y0\",\"target\":\"LLMChain-cHel8\",\"sourceHandle\":\"{œbaseClassesœ:[œBaseLanguageModelœ,œChatOpenAIœ,œBaseChatModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-LA6y0œ}\",\"targetHandle\":\"{œfieldNameœ:œllmœ,œidœ:œLLMChain-cHel8œ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\",\"id\":\"reactflow__edge-ChatOpenAI-LA6y0{œbaseClassesœ:[œBaseLanguageModelœ,œChatOpenAIœ,œBaseChatModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-LA6y0œ}-LLMChain-cHel8{œfieldNameœ:œllmœ,œidœ:œLLMChain-cHel8œ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"llm\",\"id\":\"LLMChain-cHel8\",\"inputTypes\":null,\"type\":\"BaseLanguageModel\"},\"sourceHandle\":{\"baseClasses\":[\"BaseLanguageModel\",\"ChatOpenAI\",\"BaseChatModel\",\"BaseLLM\"],\"dataType\":\"ChatOpenAI\",\"id\":\"ChatOpenAI-LA6y0\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"selected\":false},{\"source\":\"CustomComponent-zNSTv\",\"sourceHandle\":\"{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-zNSTvœ}\",\"target\":\"CustomComponent-ZNoRM\",\"targetHandle\":\"{œfieldNameœ:œhtml_contentœ,œidœ:œCustomComponent-ZNoRMœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"html_content\",\"id\":\"CustomComponent-ZNoRM\",\"inputTypes\":null,\"type\":\"Data\"},\"sourceHandle\":{\"baseClasses\":[\"Data\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-zNSTv\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-zNSTv{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-zNSTvœ}-CustomComponent-ZNoRM{œfieldNameœ:œhtml_contentœ,œidœ:œCustomComponent-ZNoRMœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"selected\":false},{\"source\":\"CustomComponent-zNSTv\",\"sourceHandle\":\"{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-zNSTvœ}\",\"target\":\"CustomComponent-Ihm2o\",\"targetHandle\":\"{œfieldNameœ:œhtml_contentœ,œidœ:œCustomComponent-Ihm2oœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"html_content\",\"id\":\"CustomComponent-Ihm2o\",\"inputTypes\":null,\"type\":\"Data\"},\"sourceHandle\":{\"baseClasses\":[\"Data\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-zNSTv\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-zNSTv{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-zNSTvœ}-CustomComponent-Ihm2o{œfieldNameœ:œhtml_contentœ,œidœ:œCustomComponent-Ihm2oœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"selected\":false},{\"source\":\"CustomComponent-Ihm2o\",\"sourceHandle\":\"{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-Ihm2oœ}\",\"target\":\"CustomComponent-6ST9l\",\"targetHandle\":\"{œfieldNameœ:œsoupœ,œidœ:œCustomComponent-6ST9lœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"soup\",\"id\":\"CustomComponent-6ST9l\",\"inputTypes\":null,\"type\":\"Data\"},\"sourceHandle\":{\"baseClasses\":[\"Data\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-Ihm2o\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-Ihm2o{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-Ihm2oœ}-CustomComponent-6ST9l{œfieldNameœ:œsoupœ,œidœ:œCustomComponent-6ST9lœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"selected\":false},{\"source\":\"CustomComponent-iTLf4\",\"sourceHandle\":\"{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-iTLf4œ}\",\"target\":\"CustomComponent-zNSTv\",\"targetHandle\":\"{œfieldNameœ:œurlœ,œidœ:œCustomComponent-zNSTvœ,œinputTypesœ:[œDataœ,œstrœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"url\",\"id\":\"CustomComponent-zNSTv\",\"inputTypes\":[\"Data\",\"str\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"str\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-iTLf4\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-iTLf4{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-iTLf4œ}-CustomComponent-zNSTv{œfieldNameœ:œurlœ,œidœ:œCustomComponent-zNSTvœ,œinputTypesœ:[œDataœ,œstrœ],œtypeœ:œstrœ}\",\"selected\":false},{\"source\":\"CustomComponent-iTLf4\",\"sourceHandle\":\"{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-iTLf4œ}\",\"target\":\"PromptTemplate-l35W1\",\"targetHandle\":\"{œfieldNameœ:œurlœ,œidœ:œPromptTemplate-l35W1œ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"url\",\"id\":\"PromptTemplate-l35W1\",\"inputTypes\":[\"Document\",\"BaseOutputParser\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"str\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-iTLf4\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-iTLf4{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-iTLf4œ}-PromptTemplate-l35W1{œfieldNameœ:œurlœ,œidœ:œPromptTemplate-l35W1œ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"selected\":false},{\"source\":\"CustomComponent-6ST9l\",\"sourceHandle\":\"{œbaseClassesœ:[œlistœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-6ST9lœ}\",\"target\":\"CustomComponent-jWLUz\",\"targetHandle\":\"{œfieldNameœ:œitemsœ,œidœ:œCustomComponent-jWLUzœ,œinputTypesœ:null,œtypeœ:œlistœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"items\",\"id\":\"CustomComponent-jWLUz\",\"inputTypes\":null,\"type\":\"list\"},\"sourceHandle\":{\"baseClasses\":[\"list\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-6ST9l\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-6ST9l{œbaseClassesœ:[œlistœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-6ST9lœ}-CustomComponent-jWLUz{œfieldNameœ:œitemsœ,œidœ:œCustomComponent-jWLUzœ,œinputTypesœ:null,œtypeœ:œlistœ}\",\"selected\":false},{\"source\":\"CustomComponent-jWLUz\",\"sourceHandle\":\"{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-jWLUzœ}\",\"target\":\"PromptTemplate-l35W1\",\"targetHandle\":\"{œfieldNameœ:œhtml_linksœ,œidœ:œPromptTemplate-l35W1œ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"html_links\",\"id\":\"PromptTemplate-l35W1\",\"inputTypes\":[\"Document\",\"BaseOutputParser\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"str\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-jWLUz\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-jWLUz{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-jWLUzœ}-PromptTemplate-l35W1{œfieldNameœ:œhtml_linksœ,œidœ:œPromptTemplate-l35W1œ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"selected\":false},{\"source\":\"CustomComponent-ZNoRM\",\"sourceHandle\":\"{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-ZNoRMœ}\",\"target\":\"PromptTemplate-l35W1\",\"targetHandle\":\"{œfieldNameœ:œhtml_markdownœ,œidœ:œPromptTemplate-l35W1œ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"html_markdown\",\"id\":\"PromptTemplate-l35W1\",\"inputTypes\":[\"Document\",\"BaseOutputParser\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"str\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-ZNoRM\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-ZNoRM{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-ZNoRMœ}-PromptTemplate-l35W1{œfieldNameœ:œhtml_markdownœ,œidœ:œPromptTemplate-l35W1œ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"selected\":false},{\"source\":\"PromptTemplate-l35W1\",\"sourceHandle\":\"{œbaseClassesœ:[œStringPromptTemplateœ,œBasePromptTemplateœ,œPromptTemplateœ],œdataTypeœ:œPromptTemplateœ,œidœ:œPromptTemplate-l35W1œ}\",\"target\":\"LLMChain-cHel8\",\"targetHandle\":\"{œfieldNameœ:œpromptœ,œidœ:œLLMChain-cHel8œ,œinputTypesœ:null,œtypeœ:œBasePromptTemplateœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"prompt\",\"id\":\"LLMChain-cHel8\",\"inputTypes\":null,\"type\":\"BasePromptTemplate\"},\"sourceHandle\":{\"baseClasses\":[\"StringPromptTemplate\",\"BasePromptTemplate\",\"PromptTemplate\"],\"dataType\":\"PromptTemplate\",\"id\":\"PromptTemplate-l35W1\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-PromptTemplate-mJqEg{œbaseClassesœ:[œStringPromptTemplateœ,œBasePromptTemplateœ,œPromptTemplateœ],œdataTypeœ:œPromptTemplateœ,œidœ:œPromptTemplate-mJqEgœ}-LLMChain-cHel8{œfieldNameœ:œpromptœ,œidœ:œLLMChain-cHel8œ,œinputTypesœ:null,œtypeœ:œBasePromptTemplateœ}\"}],\"viewport\":{\"x\":206.6159172940935,\"y\":79.94375811155385,\"zoom\":0.5140569133280333}},\"is_component\":false,\"updated_at\":\"2023-12-06T00:23:04.515144\",\"folder\":null,\"id\":\"ecfb377a-7e88-405d-8d66-7560735ce446\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Lonely Lovelace\",\"description\":\"Smart Chains, Smarter Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-04T23:43:25.925753\",\"folder\":null,\"id\":\"30e71767-6128-40e4-9a6d-b9197b679971\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Custom Component\",\"description\":\"Create any custom component you want!\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\n\\n\\nclass Component(CustomComponent):\\n display_name: str = \\\"Custom Component\\\"\\n description: str = \\\"Create any custom component you want!\\\"\\n documentation: str = \\\"http://docs.langflow.org/components/custom\\\"\\n\\n def build_config(self):\\n return {\\\"param\\\": {\\\"display_name\\\": \\\"Parameter\\\"}}\\n\\n def build(self, param: Data) -> Data:\\n return param\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"param\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"param\",\"display_name\":\"Parameter\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Data\",\"list\":false}},\"description\":\"Create any custom component you want!\",\"base_classes\":[\"Data\"],\"display_name\":\"Custom Component\",\"custom_fields\":{\"param\":null},\"output_types\":[\"CustomComponent\"],\"documentation\":\"http://docs.langflow.org/components/custom\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"CustomComponent-IxJqc\"},\"id\":\"CustomComponent-IxJqc\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-05T22:08:27.080204\",\"folder\":null,\"id\":\"f3c56abb-96d8-4a09-80d3-f60181661b3c\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Amazing Wilson\",\"description\":\"Unfolding Linguistic Possibilities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-05T23:49:58.272677\",\"folder\":null,\"id\":\"324499a6-17a6-49de-96b1-b88955ed2c3d\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Nauseous Kowalevski\",\"description\":\"Create, Curate, Communicate with Langflow.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:45:27.084387\",\"folder\":null,\"id\":\"e3168485-d31b-472a-907f-faf833bf7824\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Silly Fermi\",\"description\":\"Craft Meaningful Interactions, Generate Value.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:45:57.134463\",\"folder\":null,\"id\":\"d0ecea5d-bcf9-4b8e-88f0-3c243d309336\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Friendly Ardinghelli\",\"description\":\"Smart Chains, Smarter Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:45:57.138184\",\"folder\":null,\"id\":\"a406912d-b0e2-4954-bef3-ee80c29eca3c\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Gleeful Easley\",\"description\":\"Bridging Prompts for Brilliance.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:45:57.162908\",\"folder\":null,\"id\":\"57b32155-4c6e-4823-ad03-8dd09d8abc62\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Effervescent Varahamihira\",\"description\":\"Create, Chain, Communicate.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:45:57.135644\",\"folder\":null,\"id\":\"18daa0ff-2e5d-457a-95d7-710affec5c4d\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Jubilant Joliot\",\"description\":\"Language Architect at Work!\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:45:57.139496\",\"folder\":null,\"id\":\"9255e938-280e-4ce7-91cd-8622126a7d02\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Adoring Carroll\",\"description\":\"Nurture NLP Nodes Here.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:45:57.162240\",\"folder\":null,\"id\":\"a7a680b9-30b1-4438-ac24-da597de443aa\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Berserk Herschel\",\"description\":\"Your Hub for Text Generation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:46:02.593504\",\"folder\":null,\"id\":\"37a439b0-7b1d-45e3-b4fa-5c73669bae3b\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Distracted Joliot\",\"description\":\"Conversational Cartography Unlocked.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:47:04.845238\",\"folder\":null,\"id\":\"4d23fd0a-8ad5-46b9-bb99-eed4138e7426\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Happy Babbage\",\"description\":\"Flow into the Future of Language.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:47:41.899665\",\"folder\":null,\"id\":\"1c8ad5b9-5524-41fe-a762-52c75126b832\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Adoring Brown\",\"description\":\"Unlock the Power of AI in Your Business Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:47:42.702031\",\"folder\":null,\"id\":\"9d4c8e79-4904-4a51-a4bb-146c3d8db10e\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Focused Mahavira\",\"description\":\"Design, Develop, Dialogize.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:47:42.786331\",\"folder\":null,\"id\":\"4ba370d1-1f8e-4a23-99aa-99e2cd9b7cbf\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Mad Gates\",\"description\":\"Where Language Meets Logic.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:47:42.838989\",\"folder\":null,\"id\":\"992c3cd3-1d79-4986-8c04-88a34130fa30\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Serene Mcclintock\",\"description\":\"Unlock the Power of AI in Your Business Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:47:42.932723\",\"folder\":null,\"id\":\"a65bfd13-44df-4090-aca0-5057e21e9997\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Berserk Feynman\",\"description\":\"Text Generation Meets Business Transformation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:47:42.931359\",\"folder\":null,\"id\":\"7a05dac5-c005-411d-9994-19d61e71ce78\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Sprightly Perlman\",\"description\":\"Interactive Language Weaving.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:47:43.054687\",\"folder\":null,\"id\":\"6db24541-7211-48e6-a792-1a4a99a0ef90\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Jolly Colden\",\"description\":\"Flow into the Future of Language.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:47:43.078384\",\"folder\":null,\"id\":\"13ac42e8-9124-4bf4-9ea2-28671ef2d9a4\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Gleeful Kaku\",\"description\":\"The Power of Language at Your Fingertips.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:50:33.156776\",\"folder\":null,\"id\":\"79262d75-5c62-4b14-b067-f4297f5c912f\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Jovial Khayyam\",\"description\":\"Empowering Communication, Enabling Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:51:13.295375\",\"folder\":null,\"id\":\"3b397e74-d8be-4728-9d6c-05f7c78106a7\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Goofy Mccarthy\",\"description\":\"Building Powerful Solutions with Language Models.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:51:27.632685\",\"folder\":null,\"id\":\"13f4e1fd-45eb-4271-92fd-0d70a31c61d2\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Cocky Lalande\",\"description\":\"Building Intelligent Interactions.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:51:54.628983\",\"folder\":null,\"id\":\"9cfd60d8-9311-47b0-b71b-f488f1940bc7\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Romantic Mirzakhani\",\"description\":\"Innovation in Interaction with Langflow.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:52:52.622698\",\"folder\":null,\"id\":\"0d849403-0f75-455d-b4e4-0d622ee3305a\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Grinning Brown\",\"description\":\"Building Powerful Solutions with Language Models.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:53:06.056636\",\"folder\":null,\"id\":\"8643ba14-52d6-4d36-9981-5fd37de5dd76\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Kickass Watt\",\"description\":\"Transform Your Business with Smart Dialogues.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:53:23.338727\",\"folder\":null,\"id\":\"818d3066-bf08-4bf9-adcd-739f8abbfa5d\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Goofy Bose\",\"description\":\"Unravel the Art of Articulation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:53:41.218861\",\"folder\":null,\"id\":\"28eff43e-0ecf-47bf-9851-f1492589978e\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Optimistic Jennings\",\"description\":\"Create Powerful Connections, Boost Business Value.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:55:03.681106\",\"folder\":null,\"id\":\"68f59069-bc2a-464f-a983-4b61e32e01af\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Pedantic Mirzakhani\",\"description\":\"Language Chainlink Master.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:55:31.761949\",\"folder\":null,\"id\":\"5d981c0e-81b3-44cc-a5be-8f55b92bfed5\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Peppy Murdock\",\"description\":\"Create Powerful Connections, Boost Business Value.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:56:45.548598\",\"folder\":null,\"id\":\"e812ad47-47e8-422b-b94c-84fd0263c9c8\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Berserk Fermat\",\"description\":\"Maximize Impact with Intelligent Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:58:50.234270\",\"folder\":null,\"id\":\"82aaf449-e737-4699-9360-929ab6108dc7\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Tiny Albattani\",\"description\":\"Your Toolkit for Text Generation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:59:53.946035\",\"folder\":null,\"id\":\"097cb080-274b-40ca-8dde-7900a949568a\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Cranky Kirch\",\"description\":\"Sculpting Language with Precision.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T23:00:51.745350\",\"folder\":null,\"id\":\"837d7b5f-8495-46a9-b00e-ad1b7ebb52f4\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Effervescent Kowalevski\",\"description\":\"Empowering Language Engineering.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T23:02:53.336102\",\"folder\":null,\"id\":\"3ff079c2-d9f9-4da6-a22a-423fa35670ff\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Radiant Stallman\",\"description\":\"Navigate the Linguistic Landscape, Discover Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T23:03:28.268357\",\"folder\":null,\"id\":\"c8b204dd-3d57-4bc8-aa13-1d559672e75b\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Grinning Swirles\",\"description\":\"Unleashing Linguistic Creativity.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T23:03:51.194455\",\"folder\":null,\"id\":\"a097f083-5880-4cf7-986b-51898bc68e11\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Dreamy Williams\",\"description\":\"Interactive Language Weaving.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T23:04:36.678251\",\"folder\":null,\"id\":\"d9585f63-ce76-42ce-87bc-8e69601ea5c6\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Zany Hawking\",\"description\":\"Flow into the Future of Language.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T23:05:13.672479\",\"folder\":null,\"id\":\"612a01d5-8c8d-4cc1-8c54-35626b7f4a6d\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Amazing Kilby\",\"description\":\"Your Toolkit for Text Generation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T23:10:37.047955\",\"folder\":null,\"id\":\"2d05a598-3cdf-452a-bd5d-b0e569e562e3\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Insane Cori\",\"description\":\"Empowering Communication, Enabling Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T23:18:12.426578\",\"folder\":null,\"id\":\"d1769a4a-c1e9-4d74-9273-1e76cfcf21f3\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Compassionate Tesla\",\"description\":\"Graph Your Way to Great Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T23:18:52.806238\",\"folder\":null,\"id\":\"28c5d9dd-0466-4c80-9e58-b1e061cd358d\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Jubilant Goldstine\",\"description\":\"Harness the Power of Conversational AI.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T23:21:44.488510\",\"folder\":null,\"id\":\"b3c57e4f-28a1-4580-bf08-a9484bdd66e8\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Elegant Curie\",\"description\":\"Building Intelligent Interactions.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:23:47.610237\",\"folder\":null,\"id\":\"28fb024e-6ba1-4f5b-83b3-4742b3b8117c\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Twinkly Chandrasekhar\",\"description\":\"Maximize Impact with Intelligent Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:24:29.824530\",\"folder\":null,\"id\":\"d2b87cf7-9167-4030-8e9f-b8d9aa0cadee\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Pensive Nobel\",\"description\":\"Crafting Dialogues that Drive Business Success.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:26:51.210699\",\"folder\":null,\"id\":\"c2c9fbac-7d97-40c2-8055-dff608df9414\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Elated Edison\",\"description\":\"Advanced NLP for Groundbreaking Business Solutions.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:27:35.822482\",\"folder\":null,\"id\":\"a55561cd-4b25-473f-bde5-884cbabb0d24\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Dazzling Lichterman\",\"description\":\"Building Linguistic Labyrinths.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:29:09.259381\",\"folder\":null,\"id\":\"9c6fe6d4-8311-4fc6-8b02-2a816d7c059d\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Distracted Bhaskara\",\"description\":\"Navigate the Networks of Conversation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:31:36.053452\",\"folder\":null,\"id\":\"ef6fc1ab-aff8-45a1-8cd5-bc8e38565e4d\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Evil Watt\",\"description\":\"Building Intelligent Interactions.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:32:26.765250\",\"folder\":null,\"id\":\"499b5351-9c09-4934-9f9d-a24be2fd8b24\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Jolly Wien\",\"description\":\"Bridging Prompts for Brilliance.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:33:23.648859\",\"folder\":null,\"id\":\"a57eda91-7f6e-410d-9990-385fe0c724f3\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Nostalgic Spence\",\"description\":\"Mapping Meaningful Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:34:22.576407\",\"folder\":null,\"id\":\"685f685e-8a1b-4b7e-9e21-6cdd72163c91\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Comical Fermat\",\"description\":\"Create, Connect, Converse.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:35:44.920540\",\"folder\":null,\"id\":\"3e061766-b834-4fa4-ba9c-b060925d9703\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Grave Volta\",\"description\":\"Maximize Impact with Intelligent Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:36:33.001572\",\"folder\":null,\"id\":\"135f2fd9-e005-40bc-a9bf-c25107388415\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Gleeful Davinci\",\"description\":\"Create Powerful Connections, Boost Business Value.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:37:16.208823\",\"folder\":null,\"id\":\"167cdb24-7e1c-475b-893a-cca2f125426c\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Hilarious Sinoussi\",\"description\":\"Language Chainlink Master.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:38:07.215401\",\"folder\":null,\"id\":\"48113cab-2c04-493f-8c2e-c8d067826aa2\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Grave Sagan\",\"description\":\"Connect the Dots, Craft Language.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:39:19.479656\",\"folder\":null,\"id\":\"28d292dc-e094-4ffe-a657-178892933267\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Cranky Hoover\",\"description\":\"Crafting Dialogues that Drive Business Success.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:40:02.895859\",\"folder\":null,\"id\":\"0c9849b7-b2d6-4d0e-8334-abfb3ae183dd\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Evil Mendeleev\",\"description\":\"Unfolding Linguistic Possibilities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:40:27.867247\",\"folder\":null,\"id\":\"d78c52e9-1941-4555-9bb9-abd01f176705\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Effervescent Dubinsky\",\"description\":\"Where Language Meets Logic.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:41:23.177402\",\"folder\":null,\"id\":\"5277a04c-b5da-4597-aaa2-a6b66ea11d02\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Cocky Poitras\",\"description\":\"Where Language Meets Logic.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:42:08.731865\",\"folder\":null,\"id\":\"b0d0c8de-4eea-484a-a068-b13e63f7e71c\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Pedantic Ptolemy\",\"description\":\"Crafting Conversations, One Node at a Time.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:42:25.658996\",\"folder\":null,\"id\":\"b6f155e2-03eb-4232-9bab-145463382fe9\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Loving Cray\",\"description\":\"Maximize Impact with Intelligent Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:43:57.530112\",\"folder\":null,\"id\":\"b75c10ca-9ecb-432b-88ab-e1847e836e22\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Effervescent Pasteur\",\"description\":\"Language Models, Mapped and Mastered.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:44:58.979393\",\"folder\":null,\"id\":\"3710eccb-e7a7-41d5-9339-d9c301515d17\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Pensive Gates\",\"description\":\"The Power of Language at Your Fingertips.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:45:42.744174\",\"folder\":null,\"id\":\"fdd2271e-92f6-4349-8c01-2ec0e9e73f13\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Determined Khorana\",\"description\":\"Beyond Text Generation - Unleashing Business Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:46:10.084684\",\"folder\":null,\"id\":\"88b49a97-0888-4fea-8d9b-6ac2cc6d158e\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Lonely Booth\",\"description\":\"Design Dialogues with Langflow.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:46:41.577750\",\"folder\":null,\"id\":\"629afe54-8796-45be-a570-e3ac79c60792\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Jubilant Mendeleev\",\"description\":\"Chain the Words, Master Language!\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:47:22.631243\",\"folder\":null,\"id\":\"7bf481b0-73fe-4f5b-a3d4-1263d9d8e827\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Clever Varahamihira\",\"description\":\"Building Powerful Solutions with Language Models.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:49:51.026960\",\"folder\":null,\"id\":\"df9e86b6-56c9-4848-9010-102615314766\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Sleepy Stallman\",\"description\":\"Empowering Language Engineering.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:50:14.932236\",\"folder\":null,\"id\":\"3e66994c-9b7a-4b85-a917-65d1959d7352\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Modest Wozniak\",\"description\":\"Advanced NLP for Groundbreaking Business Solutions.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:51:13.811894\",\"folder\":null,\"id\":\"d10f924a-5780-4255-9f41-3e102ae03e84\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Hopeful Mirzakhani\",\"description\":\"Graph Your Way to Great Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:52:23.906908\",\"folder\":null,\"id\":\"f3378fa8-ccaf-4a3b-90d6-b8ab0c4e481f\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Awesome Joule\",\"description\":\"Design, Develop, Dialogize.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:52:43.863440\",\"folder\":null,\"id\":\"deaa50e7-a8b1-46b1-856c-334ee781e1c2\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Peppy Shockley\",\"description\":\"Generate, Innovate, Communicate.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:53:43.299699\",\"folder\":null,\"id\":\"c72eac2c-d924-40c6-a102-da524216d090\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Zany Dewey\",\"description\":\"Flow into the Future of Language.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:54:18.848827\",\"folder\":null,\"id\":\"d9425324-bb60-462e-b431-90a536f2bc76\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Gloomy Joliot\",\"description\":\"Language Engineering Excellence.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:58:12.348608\",\"folder\":null,\"id\":\"621ba134-3fac-487c-98cd-96941439f1be\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Backstabbing Franklin\",\"description\":\"Craft Language Connections Here.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:58:13.491824\",\"folder\":null,\"id\":\"86ca9773-c7b7-4a1a-859a-6cbe0ddff206\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Sharp Swartz\",\"description\":\"Beyond Text Generation - Unleashing Business Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:58:13.524414\",\"folder\":null,\"id\":\"da1c02b7-d608-4498-9946-7d02f55fa103\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Serene Volta\",\"description\":\"Connect the Dots, Craft Language.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:58:13.641432\",\"folder\":null,\"id\":\"8d5dd998-6b51-4f65-8331-086a7f3b11d7\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Focused Lichterman\",\"description\":\"Crafting Dialogues that Drive Business Success.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:58:13.746120\",\"folder\":null,\"id\":\"942027d3-e2ea-48c6-8279-0a41b54e8862\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Lively Einstein\",\"description\":\"Unleashing Linguistic Creativity.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:58:13.746904\",\"folder\":null,\"id\":\"9e9b6298-1073-4297-8ecc-3c620b432e70\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Cocky Planck\",\"description\":\"Empowering Language Engineering.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:58:13.747420\",\"folder\":null,\"id\":\"7cd60c83-b797-4e60-af6d-cbc540657943\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Suspicious Zobell\",\"description\":\"Innovation in Interaction, Revolution in Revenue.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:58:13.749951\",\"folder\":null,\"id\":\"dab08306-9521-4e15-aa11-e6a6a4e210f8\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Small Knuth\",\"description\":\"Nurture NLP Nodes Here.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:59:16.772119\",\"folder\":null,\"id\":\"c9149590-636a-44f5-aaae-45a4e78fe4df\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Evil Wright\",\"description\":\"Unfolding Linguistic Possibilities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:59:52.954568\",\"folder\":null,\"id\":\"6b23b2ad-c07c-46f6-b9ad-268783d1712e\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Vibrant Lalande\",\"description\":\"Language Models, Mapped and Mastered.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:59:53.656156\",\"folder\":null,\"id\":\"ece3bcf6-a147-4559-862e-cacff9db5f48\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Happy Gauss\",\"description\":\"The Pinnacle of Prompt Generation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:59:53.717991\",\"folder\":null,\"id\":\"252b6021-ecad-4eaf-9e2f-106c4c89c496\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Gigantic Rosalind\",\"description\":\"Building Powerful Solutions with Language Models.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:59:53.736261\",\"folder\":null,\"id\":\"b8cb6d8d-c0fb-4e8d-a46e-2c608dc8a714\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Adoring Hubble\",\"description\":\"Powerful Prompts, Perfectly Positioned.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:59:53.769546\",\"folder\":null,\"id\":\"553a67db-7225-474c-978e-8a40cde2bfb2\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Pensive Mclean\",\"description\":\"Unlock the Power of AI in Your Business Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:59:53.981063\",\"folder\":null,\"id\":\"e0865007-4d80-4edf-87ab-9e8d2892d719\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Trusting Murdock\",\"description\":\"Uncover Business Opportunities with NLP.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:59:53.982286\",\"folder\":null,\"id\":\"1021cd20-66e0-4b81-9c79-bfe729774d20\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Perky Riemann\",\"description\":\"Powerful Prompts, Perfectly Positioned.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:59:53.983216\",\"folder\":null,\"id\":\"089074d3-8a1e-4d85-a59d-b4717090e4d3\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Small Tesla\",\"description\":\"Language Models, Unleashed.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:00:35.704142\",\"folder\":null,\"id\":\"beb49d88-255e-4db4-931b-4ab4358f1097\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Effervescent Boyd\",\"description\":\"Smart Chains, Smarter Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:01:13.569507\",\"folder\":null,\"id\":\"75b5ab8d-e0c0-43cf-912b-8578550e198a\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Small Babbage\",\"description\":\"Interactive Language Weaving.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:01:27.944868\",\"folder\":null,\"id\":\"503edd55-8f70-43e5-87fb-2324eaf62336\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Lonely Bose\",\"description\":\"Crafting Dialogues that Drive Business Success.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:02:40.122079\",\"folder\":null,\"id\":\"ae4f2992-1a23-4a43-bec6-68b823935762\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Mirthful Coulomb\",\"description\":\"Craft Meaningful Interactions, Generate Value.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:03:15.263237\",\"folder\":null,\"id\":\"a2a464db-b02a-4440-ad9e-7b552ee6c027\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Drunk Newton\",\"description\":\"Craft Meaningful Interactions, Generate Value.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:03:15.883766\",\"folder\":null,\"id\":\"1a5d9af7-5a96-4035-a09c-e15741785828\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Jovial Pasteur\",\"description\":\"Your Hub for Text Generation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:03:15.933083\",\"folder\":null,\"id\":\"04b94873-0828-41dc-a850-fd4132c9b9f1\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Playful Spence\",\"description\":\"Connect the Dots, Craft Language.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:03:15.967685\",\"folder\":null,\"id\":\"47003dc2-7884-48a3-aa66-e4185079f4d9\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Cheerful Noyce\",\"description\":\"Your Passport to Linguistic Landscapes.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:03:15.983198\",\"folder\":null,\"id\":\"13769cb4-2e15-4d54-a28a-c97dc15db58c\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Awesome Edison\",\"description\":\"Unfolding Linguistic Possibilities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:03:16.018879\",\"folder\":null,\"id\":\"453dacde-6b10-406b-a5b3-f90f44be6899\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Upbeat Snyder\",\"description\":\"Powerful Prompts, Perfectly Positioned.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:03:16.205689\",\"folder\":null,\"id\":\"9544fac9-3002-47aa-86b9-102844fe9649\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Tender Khorana\",\"description\":\"Chain the Words, Master Language!\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:03:16.243434\",\"folder\":null,\"id\":\"90498ef6-34f9-45c8-8cd0-fe6a36a26f41\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Elated Albattani\",\"description\":\"Interactive Language Weaving.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:05:07.775497\",\"folder\":null,\"id\":\"9577c416-8ce8-48f6-ad6d-ab2e003bb415\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Charming Goodall\",\"description\":\"Maximize Impact with Intelligent Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:07:52.139318\",\"folder\":null,\"id\":\"f10dc08e-b9c7-44b3-8837-b95aee2f6dbb\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Hilarious Ramanujan\",\"description\":\"Harness the Power of Conversational AI.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:08:22.448480\",\"folder\":null,\"id\":\"c864bd8c-67cd-465f-bf7d-7a35c7df37f3\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Tender Mclean\",\"description\":\"Unleashing Linguistic Creativity.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:09:56.507826\",\"folder\":null,\"id\":\"f0c13b19-ae23-40e6-88d6-d135897ee100\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Grave Hawking\",\"description\":\"Building Intelligent Interactions.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:10:27.169757\",\"folder\":null,\"id\":\"0afb91b4-8f41-4270-900a-f5de647d45ad\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Gloomy Lovelace\",\"description\":\"Your Passport to Linguistic Landscapes.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:11:02.292233\",\"folder\":null,\"id\":\"0f1e5dcf-8769-4157-b495-5f215b490107\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Fervent Kilby\",\"description\":\"Empowering Enterprises with Intelligent Interactions.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:11:46.960966\",\"folder\":null,\"id\":\"310d03d9-dd50-4946-9a27-38ee06906212\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Admiring Almeida\",\"description\":\"Language Models, Mapped and Mastered.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:12:24.475101\",\"folder\":null,\"id\":\"3cbc8fc2-a86f-4177-9a1c-a833b2a24283\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Elated Roentgen\",\"description\":\"Empowering Enterprises with Intelligent Interactions.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:06.753571\",\"folder\":null,\"id\":\"c508e922-29e9-4234-84ae-505c5bdf41c1\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Perky Poitras\",\"description\":\"Chain the Words, Master Language!\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:07.754605\",\"folder\":null,\"id\":\"1431df05-1b6f-41af-a063-a18d26a946ef\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Tender Khayyam\",\"description\":\"Navigate the Linguistic Landscape, Discover Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:07.791627\",\"folder\":null,\"id\":\"344e03fb-fd49-4e87-be67-7dce04ba655b\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Zealous Mayer\",\"description\":\"Navigate the Linguistic Landscape, Discover Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:07.803889\",\"folder\":null,\"id\":\"8b3ff1cb-3a6c-46ee-b09a-0e9f9f13a8b9\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Tiny Ramanujan\",\"description\":\"Empowering Communication, Enabling Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:07.822583\",\"folder\":null,\"id\":\"18961e76-f4b1-4968-926a-fed22cb04f69\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Cheerful Franklin\",\"description\":\"Building Intelligent Interactions.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:07.854440\",\"folder\":null,\"id\":\"0e0ee854-ab46-4333-a848-2e1239a24334\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Serene Swirles\",\"description\":\"Maximize Impact with Intelligent Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:07.988932\",\"folder\":null,\"id\":\"cc7b8238-3d15-4f78-bd0c-8311691c9ff8\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Sleepy Swartz\",\"description\":\"Uncover Business Opportunities with NLP.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:08.028688\",\"folder\":null,\"id\":\"123369f9-c83c-4ed3-93b6-78ca29c271cf\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Cranky Kowalevski\",\"description\":\"Unleashing Linguistic Creativity.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:59.097607\",\"folder\":null,\"id\":\"ed4b1490-e9e5-46bf-b337-166b48eaadd6\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Sprightly Golick\",\"description\":\"Building Powerful Solutions with Language Models.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:59.617772\",\"folder\":null,\"id\":\"9d1be311-c618-4e3e-aeb1-4161ab37850e\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Boring Newton\",\"description\":\"Generate, Innovate, Communicate.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:59.646124\",\"folder\":null,\"id\":\"63a75f99-1745-40d3-9e27-3d19a143be45\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Sprightly Noyce\",\"description\":\"Beyond Text Generation - Unleashing Business Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:59.685781\",\"folder\":null,\"id\":\"b418ca87-eb17-42e8-b789-3fcb0cab3ddb\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Fluffy Fermat\",\"description\":\"Text Generation Meets Business Transformation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:59.705984\",\"folder\":null,\"id\":\"93802b07-eee9-4a2b-8691-7d9a231bd67e\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Stoic Payne\",\"description\":\"Beyond Text Generation - Unleashing Business Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:59.723990\",\"folder\":null,\"id\":\"d62df661-0ae5-4b41-a9fb-71cb2e46ad52\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Effervescent Darwin\",\"description\":\"Unleashing Linguistic Creativity.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:59.818343\",\"folder\":null,\"id\":\"d1f62248-415c-474a-bfa6-3509a528a33b\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Focused Thompson\",\"description\":\"Transform Your Business with Smart Dialogues.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:59.925999\",\"folder\":null,\"id\":\"d2267176-f020-4c52-90a4-7f944d7c1749\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Admiring Dewey\",\"description\":\"Navigate the Networks of Conversation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:15:07.400402\",\"folder\":null,\"id\":\"8cf1ac8d-d34d-4e8a-a9da-be44672e1dfb\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Prickly Zuse\",\"description\":\"Where Language Meets Logic.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:15:08.384611\",\"folder\":null,\"id\":\"bae3cb5b-0f1b-4e95-bf58-7eab38da3d73\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Hungry Zuse\",\"description\":\"The Pinnacle of Prompt Generation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:15:08.436591\",\"folder\":null,\"id\":\"4dfafe3e-e9ef-405d-be72-550084411d69\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Lonely Khayyam\",\"description\":\"Design Dialogues with Langflow.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:15:08.435958\",\"folder\":null,\"id\":\"e0f81215-dc55-4b5a-b8cf-6e2fcbf297a7\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Big Mendel\",\"description\":\"Innovation in Interaction with Langflow.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:15:08.470080\",\"folder\":null,\"id\":\"5022a71c-da47-4975-a4d0-6d2d9e760d3d\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Inquisitive Poitras\",\"description\":\"Navigate the Networks of Conversation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:15:08.484430\",\"folder\":null,\"id\":\"4f1ff9e3-3500-404c-80af-2010bc46cdcb\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Joyous Jones\",\"description\":\"The Power of Language at Your Fingertips.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:15:08.661306\",\"folder\":null,\"id\":\"77af3e47-c2cc-42f6-99e1-78589439a447\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Exuberant Khayyam\",\"description\":\"Empowering Communication, Enabling Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:15:08.662877\",\"folder\":null,\"id\":\"6f3e2e56-b329-47e3-86cc-024c29203016\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Dazzling Visvesvaraya\",\"description\":\"Maximize Impact with Intelligent Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:16:10.092917\",\"folder\":null,\"id\":\"449ac0ee-ee29-4a9f-9aff-fd6a86624457\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Nostalgic Tesla\",\"description\":\"Nurture NLP Nodes Here.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:16:10.630382\",\"folder\":null,\"id\":\"a2136ed3-dc75-4a8f-ab34-6887ff955b23\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Goofy Noether\",\"description\":\"Language Models, Unleashed.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:16:10.652058\",\"folder\":null,\"id\":\"fd1080f8-db07-481a-b2ba-60f67fcb20a6\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Dazzling Pasteur\",\"description\":\"Language Models, Unleashed.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:16:10.688661\",\"folder\":null,\"id\":\"d534d5e1-92aa-4fb2-a795-7071c4feba47\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Comical Sinoussi\",\"description\":\"Bridging Prompts for Brilliance.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:16:10.741385\",\"folder\":null,\"id\":\"85323170-c066-4d8f-acb0-1b142241389e\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Small Ramanujan\",\"description\":\"Uncover Business Opportunities with NLP.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:16:10.790086\",\"folder\":null,\"id\":\"b0d18432-21ab-404b-acb6-57ef97353fad\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Sick Joliot\",\"description\":\"Text Generation Meets Business Transformation.\",\"data\":{\"nodes\":[{\"width\":384,\"height\":442,\"id\":\"OpenAIEmbeddings-rVj1B\",\"type\":\"genericNode\",\"position\":{\"x\":-100.23754663035719,\"y\":-718.7575880388187},\"data\":{\"type\":\"OpenAIEmbeddings\",\"node\":{\"template\":{\"allowed_special\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[],\"password\":false,\"name\":\"allowed_special\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"async_client\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"async_client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"chunk_size\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":1000,\"password\":false,\"name\":\"chunk_size\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"default_headers\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"default_headers\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"default_query\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"default_query\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"deployment\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"text-embedding-ada-002\",\"password\":false,\"name\":\"deployment\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"disallowed_special\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"all\",\"password\":false,\"name\":\"disallowed_special\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"embedding_ctx_length\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":8191,\"password\":false,\"name\":\"embedding_ctx_length\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"headers\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"{\\\"Authorization\\\": \\\"Bearer \\\"}\",\"password\":false,\"name\":\"headers\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"http_client\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"http_client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":2,\"password\":false,\"name\":\"max_retries\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"model\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"text-embedding-ada-002\",\"password\":false,\"name\":\"model\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_api_type\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"openai_api_type\",\"display_name\":\"OpenAI API Type\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_api_version\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"openai_api_version\",\"display_name\":\"OpenAI API Version\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"show_progress_bar\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"show_progress_bar\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"skip_empty\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"skip_empty\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tiktoken_enabled\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":true,\"password\":true,\"name\":\"tiktoken_enabled\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"OpenAIEmbeddings\"},\"description\":\"OpenAI embedding models.\",\"base_classes\":[\"OpenAIEmbeddings\",\"Embeddings\"],\"display_name\":\"OpenAIEmbeddings\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/openai\",\"beta\":false,\"error\":null},\"id\":\"OpenAIEmbeddings-rVj1B\"},\"selected\":true,\"dragging\":false,\"positionAbsolute\":{\"x\":-100.23754663035719,\"y\":-718.7575880388187}}],\"edges\":[],\"viewport\":{\"x\":267.7156633365312,\"y\":716.9644817529361,\"zoom\":0.7169776240079139}},\"is_component\":false,\"updated_at\":\"2023-12-08T18:52:26.999440\",\"folder\":null,\"id\":\"be39958a-ef42-4fa8-8e54-b611e56b5c97\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Graceful Lumiere\",\"description\":\"Conversational Cartography Unlocked.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:16:11.012069\",\"folder\":null,\"id\":\"f7dcecfd-533c-4f40-9dcb-f213962ed1a2\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"aaaaa\",\"description\":\"Text Generation Meets Business Transformation.\",\"data\":{\"nodes\":[{\"width\":384,\"height\":442,\"id\":\"OpenAIEmbeddings-P6Z0D\",\"type\":\"genericNode\",\"position\":{\"x\":-100.23754663035719,\"y\":-718.7575880388187},\"data\":{\"type\":\"OpenAIEmbeddings\",\"node\":{\"template\":{\"allowed_special\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[],\"password\":false,\"name\":\"allowed_special\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"async_client\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"async_client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"chunk_size\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":1000,\"password\":false,\"name\":\"chunk_size\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"default_headers\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"default_headers\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"default_query\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"default_query\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"deployment\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"text-embedding-ada-002\",\"password\":false,\"name\":\"deployment\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"disallowed_special\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"all\",\"password\":false,\"name\":\"disallowed_special\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"embedding_ctx_length\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":8191,\"password\":false,\"name\":\"embedding_ctx_length\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"headers\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"{\\\"Authorization\\\": \\\"Bearer \\\"}\",\"password\":false,\"name\":\"headers\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"http_client\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"http_client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":2,\"password\":false,\"name\":\"max_retries\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"model\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"text-embedding-ada-002\",\"password\":false,\"name\":\"model\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_api_type\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"openai_api_type\",\"display_name\":\"OpenAI API Type\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"},\"openai_api_version\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"openai_api_version\",\"display_name\":\"OpenAI API Version\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"show_progress_bar\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"show_progress_bar\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"skip_empty\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"skip_empty\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tiktoken_enabled\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":true,\"password\":true,\"name\":\"tiktoken_enabled\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"},\"_type\":\"OpenAIEmbeddings\"},\"description\":\"OpenAI embedding models.\",\"base_classes\":[\"OpenAIEmbeddings\",\"Embeddings\"],\"display_name\":\"OpenAIEmbeddings\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/openai\",\"beta\":false,\"error\":null},\"id\":\"OpenAIEmbeddings-P6Z0D\"},\"selected\":true,\"dragging\":false,\"positionAbsolute\":{\"x\":-100.23754663035719,\"y\":-718.7575880388187}}],\"edges\":[],\"viewport\":{\"x\":266.7156633365312,\"y\":657.9644817529361,\"zoom\":0.7169776240079139}},\"is_component\":false,\"updated_at\":\"2023-12-08T19:05:14.503144\",\"folder\":null,\"id\":\"c2411a20-57c6-44cc-a0d0-2c857453633d\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Lively Aryabhata\",\"description\":\"Design, Develop, Dialogize.\",\"data\":{\"nodes\":[{\"width\":384,\"height\":459,\"id\":\"CustomComponent-Qhbd7\",\"type\":\"genericNode\",\"position\":{\"x\":-224.36198532285903,\"y\":-39.03047722134913},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nfrom openai import OpenAI\\n\\n\\nclass Component(CustomComponent):\\n display_name: str = \\\"OpenAI STT english translator\\\"\\n description: str = \\\"Transcript and translate any audio to english\\\"\\n documentation: str = \\\"http://docs.langflow.org/components/custom\\\"\\n\\n def build_config(self):\\n return {\\\"audio_path\\\":{\\\"display_name\\\":\\\"Audio path\\\",\\\"input_types\\\":[\\\"str\\\"]},\\\"openAI_key\\\":{\\\"display_name\\\":\\\"OpenAI key\\\",\\\"password\\\":True}}\\n\\n def build(self,audio_path:str,openAI_key:str) -> str:\\n client = OpenAI(api_key=openAI_key)\\n audio_file= open(audio_path, \\\"rb\\\")\\n transcript = client.audio.translations.create(\\n model=\\\"whisper-1\\\", \\n file=audio_file\\n )\\n self.status = transcript.text\\n return transcript.text\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"audio_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"audio_path\",\"display_name\":\"Audio path\",\"advanced\":false,\"input_types\":[\"str\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"aaaaa\"},\"openAI_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"openAI_key\",\"display_name\":\"OpenAI key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"}},\"description\":\"Transcript and translate any audio to english\",\"base_classes\":[\"str\"],\"display_name\":\"OpenAI STT english tra\",\"custom_fields\":{\"audio_path\":null,\"openAI_key\":null},\"output_types\":[\"str\"],\"documentation\":\"http://docs.langflow.org/components/custom\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"CustomComponent-Qhbd7\"},\"selected\":true,\"dragging\":false,\"positionAbsolute\":{\"x\":-224.36198532285903,\"y\":-39.03047722134913}}],\"edges\":[],\"viewport\":{\"x\":433.8372868055629,\"y\":250.9611989970935,\"zoom\":0.8467453123625275}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:16:56.971879\",\"folder\":null,\"id\":\"122eee5d-9734-4e51-9da5-b39bead64a8d\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Goofy Wing\",\"description\":\"Your Toolkit for Text Generation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:18:23.227017\",\"folder\":null,\"id\":\"171d0063-6446-4c6a-8f5b-786a38951d44\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Mad Boyd\",\"description\":\"Empowering Language Engineering.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:18:24.063781\",\"folder\":null,\"id\":\"3a7af50c-6555-4004-a86e-1ea37e477900\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Boring Dewey\",\"description\":\"Unleashing Linguistic Creativity.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:18:24.065404\",\"folder\":null,\"id\":\"dc4b4235-a550-41e2-9ddb-bcb352a1bc03\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Nauseous Carroll\",\"description\":\"Navigate the Networks of Conversation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:18:24.087501\",\"folder\":null,\"id\":\"9550e2bf-db7a-41f5-84e5-177a181bbeda\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Silly Engelbart\",\"description\":\"Generate, Innovate, Communicate.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:18:24.112543\",\"folder\":null,\"id\":\"6a3a24bb-01cb-4d8e-8d17-0dc92d257322\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Sassy Khayyam\",\"description\":\"Innovation in Interaction, Revolution in Revenue.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:18:24.147631\",\"folder\":null,\"id\":\"8d372f5e-ca12-4ea8-a1a1-8846afa72692\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Mirthful Bell\",\"description\":\"Connect the Dots, Craft Language.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:18:24.212921\",\"folder\":null,\"id\":\"800f8785-0f41-4db3-aef8-9e3de5250526\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Sleepy Bassi\",\"description\":\"Unleashing Business Potential through Language Engineering.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:18:24.395729\",\"folder\":null,\"id\":\"4589607a-065b-4a8f-ba52-5045d7b04086\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Lonely Volhard\",\"description\":\"Where Language Meets Logic.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:20:33.263971\",\"folder\":null,\"id\":\"b2440ed8-44fa-4684-adf7-b5e84bff6577\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Ecstatic Poincare\",\"description\":\"Your Passport to Linguistic Landscapes.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:20:33.377270\",\"folder\":null,\"id\":\"b996f514-e0b8-432f-969b-7276630a8f4b\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Grave Zuse\",\"description\":\"Text Generation Meets Business Transformation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:20:33.406385\",\"folder\":null,\"id\":\"6e2e9c12-0afc-499e-acdd-adf4b5f7d4fc\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Big Hopper\",\"description\":\"Conversation Catalyst Engine.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:20:33.413014\",\"folder\":null,\"id\":\"e020f1a5-aa12-45e7-ba50-6eb64a735e60\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Gleeful Jang\",\"description\":\"Conversation Catalyst Engine.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:20:33.433045\",\"folder\":null,\"id\":\"ee58f892-b7b2-408e-b4b9-9d862fc315aa\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Twinkly Ohm\",\"description\":\"Promptly Ingenious!\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:20:33.403404\",\"folder\":null,\"id\":\"023a1fc3-8807-4167-b6b2-f4e5daf036f1\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Distracted Degrasse\",\"description\":\"Bridging Prompts for Brilliance.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:20:33.411655\",\"folder\":null,\"id\":\"085f106f-c1e9-4a0f-ba31-d2fafe685d9c\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Exuberant Volta\",\"description\":\"Catalyzing Business Growth through Conversational AI.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:20:33.408697\",\"folder\":null,\"id\":\"14481bb5-1353-452f-9359-d38c9419d79c\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Goofy Bose\",\"description\":\"Conversational Cartography Unlocked.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:22:21.774940\",\"folder\":null,\"id\":\"e9316292-4ee1-441b-8327-0b09a7831fe9\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Thirsty Easley\",\"description\":\"Language Models, Mapped and Mastered.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:22:22.416556\",\"folder\":null,\"id\":\"668806ba-3efa-44de-aeb7-4ac082ba9172\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Joyous Mestorf\",\"description\":\"Generate, Innovate, Communicate.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:22:22.484048\",\"folder\":null,\"id\":\"3fc0a371-aada-4450-9d17-33d3cc05c870\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Playful Franklin\",\"description\":\"Empowering Language Engineering.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:22:22.509095\",\"folder\":null,\"id\":\"af967c98-5f08-4ee2-b1ce-6c16b4f9ebe2\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Goofy Bhaskara\",\"description\":\"Empowering Enterprises with Intelligent Interactions.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:22:22.508465\",\"folder\":null,\"id\":\"758c4164-b521-45d0-a15f-d49480e312eb\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Funky Edison\",\"description\":\"Unravel the Art of Articulation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:22:22.602296\",\"folder\":null,\"id\":\"f9d3d30f-8859-433f-bafc-ccf1a7196e35\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Silly Ride\",\"description\":\"Unfolding Linguistic Possibilities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:22:22.604061\",\"folder\":null,\"id\":\"0142bca5-eb61-42ed-9917-70c4c0f54eb0\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Goofy Noyce\",\"description\":\"Text Generation Meets Business Transformation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:22:22.603113\",\"folder\":null,\"id\":\"0b63d036-4669-4ceb-8ea4-34035340df77\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Cocky Bhabha\",\"description\":\"Language Engineering Excellence.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:23:07.345767\",\"folder\":null,\"id\":\"8b9a66d4-a924-4b84-a2b5-5dd0645ac07a\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Thirsty Zobell\",\"description\":\"Unleashing Business Potential through Language Engineering.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:23:07.722319\",\"folder\":null,\"id\":\"c912fd6b-b32d-409f-a0e5-c6249b066429\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Fervent Shaw\",\"description\":\"Language Architect at Work!\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:23:07.750779\",\"folder\":null,\"id\":\"9d755cd4-c652-43e0-a68d-75a5475ce7a3\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Giggly Newton\",\"description\":\"Navigate the Linguistic Landscape, Discover Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:23:07.786602\",\"folder\":null,\"id\":\"0d3af7de-1ada-4c43-a69f-1bfad370ccfc\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Modest Yalow\",\"description\":\"Text Generation Meets Business Transformation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:23:07.792245\",\"folder\":null,\"id\":\"b6444376-4162-436b-8b40-f5a6afc850db\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Sad Bhabha\",\"description\":\"Empowering Enterprises with Intelligent Interactions.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:23:07.890349\",\"folder\":null,\"id\":\"d90af439-fb34-4d27-98f2-06f7f9a9ed8c\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Spirited Hoover\",\"description\":\"The Pinnacle of Prompt Generation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:23:07.905750\",\"folder\":null,\"id\":\"31597ce2-de3c-490b-9ead-3f702f63cfd9\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Trusting Davinci\",\"description\":\"Design, Develop, Dialogize.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:23:08.001400\",\"folder\":null,\"id\":\"b43c63e9-a257-4a53-8acc-049e13706ac2\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"23\",\"description\":\"23\",\"data\":{\"nodes\":[{\"width\":384,\"height\":467,\"id\":\"PromptTemplate-K7xiS\",\"type\":\"genericNode\",\"position\":{\"x\":-658.2250903773149,\"y\":809.352046606987},\"data\":{\"type\":\"PromptTemplate\",\"node\":{\"template\":{\"output_parser\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"BaseOutputParser\",\"list\":false},\"input_types\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_types\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"input_variables\":{\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":true,\"value\":[\"dasdas\",\"dasdasd\"]},\"partial_variables\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"partial_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"template\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"password\":false,\"name\":\"template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"prompt\",\"list\":false,\"value\":\"{dasdas}\\n{dasdasd}\\n\"},\"template_format\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"f-string\",\"password\":false,\"name\":\"template_format\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":false},\"validate_template\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"validate_template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"PromptTemplate\",\"dasdas\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"dasdas\",\"display_name\":\"dasdas\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"dasdasd\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"dasdasd\",\"display_name\":\"dasdasd\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"A prompt template for a language model.\",\"base_classes\":[\"PromptTemplate\",\"BasePromptTemplate\",\"StringPromptTemplate\"],\"name\":\"\",\"display_name\":\"PromptTemplate\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/\",\"custom_fields\":{\"\":[\"dasdas\",\"dasdasd\"]},\"output_types\":[],\"full_path\":null,\"field_formatters\":{},\"beta\":false,\"error\":null},\"id\":\"PromptTemplate-K7xiS\"},\"selected\":false,\"positionAbsolute\":{\"x\":-658.2250903773149,\"y\":809.352046606987},\"dragging\":false},{\"width\":384,\"height\":366,\"id\":\"AirbyteJSONLoader-DXfcM\",\"type\":\"genericNode\",\"position\":{\"x\":-1110.8267574563533,\"y\":569.1107380883907},\"data\":{\"type\":\"AirbyteJSONLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"suffixes\":[\".json\"],\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\"json\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"\":\"\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"AirbyteJSONLoader\"},\"description\":\"Load local `Airbyte` json files.\",\"base_classes\":[\"Document\"],\"display_name\":\"AirbyteJSONLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/airbyte_json\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"AirbyteJSONLoader-DXfcM\"},\"selected\":false,\"positionAbsolute\":{\"x\":-1110.8267574563533,\"y\":569.1107380883907},\"dragging\":false},{\"width\":384,\"height\":376,\"id\":\"PromptRunner-ckWMH\",\"type\":\"genericNode\",\"position\":{\"x\":-1149.4746387825978,\"y\":992.3970573758324},\"data\":{\"type\":\"PromptRunner\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\n\\nfrom langchain.llms.base import BaseLLM\\nfrom langchain.prompts import PromptTemplate\\nfrom langchain.schema import Document\\n\\n\\nclass PromptRunner(CustomComponent):\\n display_name: str = \\\"Prompt Runner\\\"\\n description: str = \\\"Run a Chain with the given PromptTemplate\\\"\\n beta: bool = True\\n field_config = {\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"prompt\\\": {\\n \\\"display_name\\\": \\\"Prompt Template\\\",\\n \\\"info\\\": \\\"Make sure the prompt has all variables filled.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(self, llm: BaseLLM, prompt: PromptTemplate, inputs: dict = {}) -> Document:\\n chain = prompt | llm\\n # The input is an empty dict because the prompt is already filled\\n result = chain.invoke(input=inputs)\\n if hasattr(result, \\\"content\\\"):\\n result = result.content\\n self.repr_value = result\\n return Document(page_content=str(result))\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"inputs\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"\":\"\"}],\"password\":false,\"name\":\"inputs\",\"display_name\":\"inputs\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLLM\",\"list\":false},\"prompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"prompt\",\"display_name\":\"Prompt Template\",\"advanced\":false,\"dynamic\":false,\"info\":\"Make sure the prompt has all variables filled.\",\"type\":\"PromptTemplate\",\"list\":false}},\"description\":\"Run a Chain with the given PromptTemplate\",\"base_classes\":[\"Document\"],\"display_name\":\"Prompt Runner\",\"custom_fields\":{\"inputs\":null,\"llm\":null,\"prompt\":null},\"output_types\":[\"PromptRunner\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"PromptRunner-ckWMH\"},\"selected\":false,\"positionAbsolute\":{\"x\":-1149.4746387825978,\"y\":992.3970573758324},\"dragging\":false}],\"edges\":[{\"source\":\"PromptRunner-ckWMH\",\"sourceHandle\":\"{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œPromptRunnerœ,œidœ:œPromptRunner-ckWMHœ}\",\"target\":\"PromptTemplate-K7xiS\",\"targetHandle\":\"{œfieldNameœ:œdasdasdœ,œidœ:œPromptTemplate-K7xiSœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"dasdasd\",\"id\":\"PromptTemplate-K7xiS\",\"inputTypes\":[\"Document\",\"BaseOutputParser\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"Document\"],\"dataType\":\"PromptRunner\",\"id\":\"PromptRunner-ckWMH\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-PromptRunner-ckWMH{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œPromptRunnerœ,œidœ:œPromptRunner-ckWMHœ}-PromptTemplate-K7xiS{œfieldNameœ:œdasdasdœ,œidœ:œPromptTemplate-K7xiSœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\"},{\"source\":\"AirbyteJSONLoader-DXfcM\",\"sourceHandle\":\"{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œAirbyteJSONLoaderœ,œidœ:œAirbyteJSONLoader-DXfcMœ}\",\"target\":\"PromptTemplate-K7xiS\",\"targetHandle\":\"{œfieldNameœ:œdasdasœ,œidœ:œPromptTemplate-K7xiSœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"dasdas\",\"id\":\"PromptTemplate-K7xiS\",\"inputTypes\":[\"Document\",\"BaseOutputParser\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"Document\"],\"dataType\":\"AirbyteJSONLoader\",\"id\":\"AirbyteJSONLoader-DXfcM\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-AirbyteJSONLoader-DXfcM{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œAirbyteJSONLoaderœ,œidœ:œAirbyteJSONLoader-DXfcMœ}-PromptTemplate-K7xiS{œfieldNameœ:œdasdasœ,œidœ:œPromptTemplate-K7xiSœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\"}],\"viewport\":{\"x\":721.09842496776,\"y\":-303.59762799439625,\"zoom\":0.6417129487814537}},\"is_component\":false,\"updated_at\":\"2023-12-08T22:52:14.560323\",\"folder\":null,\"id\":\"8533c46e-21fd-4b92-b68e-1086ea86c72d\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Twinkly Stonebraker\",\"description\":\"Navigate the Linguistic Landscape, Discover Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-09T13:26:42.332360\",\"folder\":null,\"id\":\"92bc0875-4a73-44f2-9410-3b8342e404bf\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Metaphor Search (1)\",\"description\":\"Search in Metaphor with a custom string.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom typing import List, Union\\nfrom langchain.llms.base import BaseLLM\\nfrom langchain.chains import LLMChain\\nfrom langchain import PromptTemplate\\nfrom langchain.schema import Document\\nfrom metaphor_python import Metaphor\\nimport json\\n\\nfrom typing import List\\nfrom langflow.field_typing import Data\\n\\nclass MetaphorSearch(CustomComponent):\\n display_name: str = \\\"Metaphor Search\\\"\\n description: str = \\\"Search in Metaphor with a custom string.\\\"\\n beta = True\\n \\n def build_config(self):\\n return {\\n \\\"metaphor_client\\\": {\\\"display_name\\\": \\\"Metaphor Wrapper\\\"}, \\n \\\"search_num_results\\\": {\\\"display_name\\\": \\\"Number of Results (per domain)\\\"},\\n \\\"include_domains\\\": {\\\"display_name\\\": \\\"Include Domains\\\", \\\"is_list\\\": True},\\n \\\"start_date\\\": {\\\"display_name\\\": \\\"Start Date\\\"},\\n \\\"use_autoprompt\\\": {\\\"display_name\\\": \\\"Use Autoprompt\\\", \\\"type\\\": \\\"boolean\\\"},\\n \\\"search_type\\\": {\\\"display_name\\\": \\\"Search Type\\\", \\\"options\\\": [\\\"neural\\\", \\\"keyword\\\"]},\\n \\\"start_date\\\": {\\\"input_types\\\": [\\\"Data\\\"]}\\n }\\n\\n def build(\\n self,\\n methaphor_client: Data,\\n query: str,\\n search_type: str='keyword',\\n search_num_results: int = 5,\\n include_domains: List[str]= [\\\"youtube.com\\\"],\\n use_autoprompt: bool = False,\\n start_date: str=\\\"2023-01-01\\\",\\n \\n ) -> Data:\\n \\n results = []\\n for domain in include_domains:\\n response = methaphor_client.search(\\n query,\\n num_results=int(search_num_results),\\n include_domains=[domain],\\n use_autoprompt=use_autoprompt,\\n type=search_type,\\n # start_crawl_date=start_date,\\n start_published_date=start_date\\n )\\n results.extend(response.results)\\n \\n self.repr_value = results\\n\\n return results\\n\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"include_domains\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[\"yout\"],\"password\":false,\"name\":\"include_domains\",\"display_name\":\"Include Domains\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"methaphor_client\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"methaphor_client\",\"display_name\":\"methaphor_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Data\",\"list\":false},\"query\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"query\",\"display_name\":\"query\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"pasteldasdasdas\"},\"search_num_results\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":5,\"password\":false,\"name\":\"search_num_results\",\"display_name\":\"Number of Results (per domain)\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"search_type\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"keyword\",\"password\":false,\"options\":[\"neural\",\"keyword\"],\"name\":\"search_type\",\"display_name\":\"Search Type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"start_date\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"start_date\",\"display_name\":\"start_date\",\"advanced\":false,\"input_types\":[\"Data\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"use_autoprompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"use_autoprompt\",\"display_name\":\"Use Autoprompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false}},\"description\":\"Search in Metaphor with a custom string.\",\"base_classes\":[\"Data\"],\"display_name\":\"Metaphor Search\",\"custom_fields\":{\"include_domains\":null,\"methaphor_client\":null,\"query\":null,\"search_num_results\":null,\"search_type\":null,\"start_date\":null,\"use_autoprompt\":null},\"output_types\":[\"Data\"],\"documentation\":\"\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"CustomComponent-dMB5d\"},\"id\":\"CustomComponent-dMB5d\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T13:26:43.668665\",\"folder\":null,\"id\":\"912265df-9b87-4b30-a585-1ca59b944391\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Metaphor Search (2)\",\"description\":\"Search in Metaphor with a custom string.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom typing import List, Union\\nfrom langchain.llms.base import BaseLLM\\nfrom langchain.chains import LLMChain\\nfrom langchain import PromptTemplate\\nfrom langchain.schema import Document\\nfrom metaphor_python import Metaphor\\nimport json\\n\\nfrom typing import List\\nfrom langflow.field_typing import Data\\n\\nclass MetaphorSearch(CustomComponent):\\n display_name: str = \\\"Metaphor Search\\\"\\n description: str = \\\"Search in Metaphor with a custom string.\\\"\\n beta = True\\n \\n def build_config(self):\\n return {\\n \\\"metaphor_client\\\": {\\\"display_name\\\": \\\"Metaphor Wrapper\\\"}, \\n \\\"search_num_results\\\": {\\\"display_name\\\": \\\"Number of Results (per domain)\\\"},\\n \\\"include_domains\\\": {\\\"display_name\\\": \\\"Include Domains\\\", \\\"is_list\\\": True},\\n \\\"start_date\\\": {\\\"display_name\\\": \\\"Start Date\\\"},\\n \\\"use_autoprompt\\\": {\\\"display_name\\\": \\\"Use Autoprompt\\\", \\\"type\\\": \\\"boolean\\\"},\\n \\\"search_type\\\": {\\\"display_name\\\": \\\"Search Type\\\", \\\"options\\\": [\\\"neural\\\", \\\"keyword\\\"]},\\n \\\"start_date\\\": {\\\"input_types\\\": [\\\"Data\\\"]}\\n }\\n\\n def build(\\n self,\\n methaphor_client: Data,\\n query: str,\\n search_type: str='keyword',\\n search_num_results: int = 5,\\n include_domains: List[str]= [\\\"youtube.com\\\"],\\n use_autoprompt: bool = False,\\n start_date: str=\\\"2023-01-01\\\",\\n \\n ) -> Data:\\n \\n results = []\\n for domain in include_domains:\\n response = methaphor_client.search(\\n query,\\n num_results=int(search_num_results),\\n include_domains=[domain],\\n use_autoprompt=use_autoprompt,\\n type=search_type,\\n # start_crawl_date=start_date,\\n start_published_date=start_date\\n )\\n results.extend(response.results)\\n \\n self.repr_value = results\\n\\n return results\\n\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"include_domains\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[\"yout\"],\"password\":false,\"name\":\"include_domains\",\"display_name\":\"Include Domains\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"methaphor_client\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"methaphor_client\",\"display_name\":\"methaphor_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Data\",\"list\":false},\"query\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"query\",\"display_name\":\"query\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"pasteldasdasdas\"},\"search_num_results\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":5,\"password\":false,\"name\":\"search_num_results\",\"display_name\":\"Number of Results (per domain)\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"search_type\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"keyword\",\"password\":false,\"options\":[\"neural\",\"keyword\"],\"name\":\"search_type\",\"display_name\":\"Search Type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"start_date\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"start_date\",\"display_name\":\"start_date\",\"advanced\":false,\"input_types\":[\"Data\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"use_autoprompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"use_autoprompt\",\"display_name\":\"Use Autoprompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false}},\"description\":\"Search in Metaphor with a custom string.\",\"base_classes\":[\"Data\"],\"display_name\":\"Metaphor Search\",\"custom_fields\":{\"include_domains\":null,\"methaphor_client\":null,\"query\":null,\"search_num_results\":null,\"search_type\":null,\"start_date\":null,\"use_autoprompt\":null},\"output_types\":[\"Data\"],\"documentation\":\"\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"CustomComponent-ipifC\"},\"id\":\"CustomComponent-ipifC\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T13:26:49.799612\",\"folder\":null,\"id\":\"ca83ee08-2f93-427d-9897-80fef6dd5447\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Metaphor Search\",\"description\":\"Search in Metaphor with a custom string.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom typing import List, Union\\nfrom langchain.llms.base import BaseLLM\\nfrom langchain.chains import LLMChain\\nfrom langchain import PromptTemplate\\nfrom langchain.schema import Document\\nfrom metaphor_python import Metaphor\\nimport json\\n\\nfrom typing import List\\nfrom langflow.field_typing import Data\\n\\nclass MetaphorSearch(CustomComponent):\\n display_name: str = \\\"Metaphor Search\\\"\\n description: str = \\\"Search in Metaphor with a custom string.\\\"\\n beta = True\\n \\n def build_config(self):\\n return {\\n \\\"metaphor_client\\\": {\\\"display_name\\\": \\\"Metaphor Wrapper\\\"}, \\n \\\"search_num_results\\\": {\\\"display_name\\\": \\\"Number of Results (per domain)\\\"},\\n \\\"include_domains\\\": {\\\"display_name\\\": \\\"Include Domains\\\", \\\"is_list\\\": True},\\n \\\"start_date\\\": {\\\"display_name\\\": \\\"Start Date\\\"},\\n \\\"use_autoprompt\\\": {\\\"display_name\\\": \\\"Use Autoprompt\\\", \\\"type\\\": \\\"boolean\\\"},\\n \\\"search_type\\\": {\\\"display_name\\\": \\\"Search Type\\\", \\\"options\\\": [\\\"neural\\\", \\\"keyword\\\"]},\\n \\\"start_date\\\": {\\\"input_types\\\": [\\\"Data\\\"]}\\n }\\n\\n def build(\\n self,\\n methaphor_client: Data,\\n query: str,\\n search_type: str='keyword',\\n search_num_results: int = 5,\\n include_domains: List[str]= [\\\"youtube.com\\\"],\\n use_autoprompt: bool = False,\\n start_date: str=\\\"2023-01-01\\\",\\n \\n ) -> Data:\\n \\n results = []\\n for domain in include_domains:\\n response = methaphor_client.search(\\n query,\\n num_results=int(search_num_results),\\n include_domains=[domain],\\n use_autoprompt=use_autoprompt,\\n type=search_type,\\n # start_crawl_date=start_date,\\n start_published_date=start_date\\n )\\n results.extend(response.results)\\n \\n self.repr_value = results\\n\\n return results\\n\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"include_domains\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[\"yout\"],\"password\":false,\"name\":\"include_domains\",\"display_name\":\"Include Domains\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"methaphor_client\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"methaphor_client\",\"display_name\":\"methaphor_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Data\",\"list\":false},\"query\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"query\",\"display_name\":\"query\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"pasteldasdasdas\"},\"search_num_results\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":5,\"password\":false,\"name\":\"search_num_results\",\"display_name\":\"Number of Results (per domain)\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"search_type\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"keyword\",\"password\":false,\"options\":[\"neural\",\"keyword\"],\"name\":\"search_type\",\"display_name\":\"Search Type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"start_date\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"start_date\",\"display_name\":\"start_date\",\"advanced\":false,\"input_types\":[\"Data\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"use_autoprompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"use_autoprompt\",\"display_name\":\"Use Autoprompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false}},\"description\":\"Search in Metaphor with a custom string.\",\"base_classes\":[\"Data\"],\"display_name\":\"Metaphor Search\",\"custom_fields\":{\"include_domains\":null,\"methaphor_client\":null,\"query\":null,\"search_num_results\":null,\"search_type\":null,\"start_date\":null,\"use_autoprompt\":null},\"output_types\":[\"Data\"],\"documentation\":\"\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"CustomComponent-Y4qL7\"},\"id\":\"CustomComponent-Y4qL7\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T13:26:53.719960\",\"folder\":null,\"id\":\"5847602b-769a-4a82-82e8-a70f54a59929\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Lively Williams\",\"description\":\"Conversational Cartography Unlocked.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-09T13:27:45.691254\",\"folder\":null,\"id\":\"0e3bdba9-127a-4399-81a4-2865b70a4a47\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Shared Component\",\"description\":\"Conversational Cartography Unlocked.\",\"data\":{\"nodes\":[{\"width\":384,\"height\":328,\"id\":\"CSVAgent-TK9Ea\",\"type\":\"genericNode\",\"position\":{\"x\":251.25514772667083,\"y\":160.7424529887874},\"data\":{\"type\":\"CSVAgent\",\"node\":{\"template\":{\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".csv\"],\"file_path\":null},\"_type\":\"csv_agent\"},\"description\":\"Construct a CSV agent from a CSV and tools.\",\"base_classes\":[\"AgentExecutor\"],\"display_name\":\"CSVAgent\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/agents/toolkits/csv\",\"beta\":false,\"error\":null},\"id\":\"CSVAgent-TK9Ea\"},\"positionAbsolute\":{\"x\":251.25514772667083,\"y\":160.7424529887874}}],\"edges\":[],\"viewport\":{\"x\":104.85568116317398,\"y\":88.26375874183478,\"zoom\":0.7169776240079145}},\"is_component\":false,\"updated_at\":\"2023-12-09T13:28:34.119070\",\"folder\":null,\"id\":\"29c1a247-47b0-457b-8666-7c0a67dc72b0\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"teste cristhian\",\"description\":\"11111\",\"data\":{\"nodes\":[{\"width\":384,\"height\":328,\"id\":\"CSVAgent-P5wrB\",\"type\":\"genericNode\",\"position\":{\"x\":251.25514772667083,\"y\":160.7424529887874},\"data\":{\"type\":\"CSVAgent\",\"node\":{\"template\":{\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".csv\"],\"file_path\":null},\"_type\":\"csv_agent\"},\"description\":\"Construct a CSV agent from a CSV and tools.\",\"base_classes\":[\"AgentExecutor\"],\"display_name\":\"CSVAgent\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/agents/toolkits/csv\",\"beta\":false,\"error\":null},\"id\":\"CSVAgent-P5wrB\"},\"positionAbsolute\":{\"x\":251.25514772667083,\"y\":160.7424529887874}},{\"width\":384,\"height\":626,\"id\":\"OpenAI-zpihD\",\"type\":\"genericNode\",\"position\":{\"x\":-56.983202536768374,\"y\":61.715652677908665},\"data\":{\"type\":\"OpenAI\",\"node\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"list\":true},\"allowed_special\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":[],\"password\":false,\"name\":\"allowed_special\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"async_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"async_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"batch_size\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":20,\"password\":false,\"name\":\"batch_size\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"best_of\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"best_of\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"default_headers\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"default_query\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_query\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"disallowed_special\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"all\",\"password\":false,\"name\":\"disallowed_special\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"frequency_penalty\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":0,\"password\":false,\"name\":\"frequency_penalty\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"http_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"http_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"logit_bias\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"logit_bias\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":2,\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"max_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":true,\"name\":\"max_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"text-babbage-001\",\"password\":false,\"options\":[\"text-davinci-003\",\"text-davinci-002\",\"text-curie-001\",\"text-babbage-001\",\"text-ada-001\"],\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"n\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"n\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":false,\"dynamic\":false,\"info\":\"\\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\\n\",\"type\":\"str\",\"list\":false,\"value\":\"dasdasdasdsadasdas\"},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"presence_penalty\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":0,\"password\":false,\"name\":\"presence_penalty\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"1.4\",\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"top_p\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"top_p\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"OpenAI\"},\"description\":\"OpenAI large language models.\",\"base_classes\":[\"OpenAI\",\"BaseLanguageModel\",\"BaseLLM\",\"BaseOpenAI\"],\"display_name\":\"OpenAI\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/openai\",\"beta\":false,\"error\":null},\"id\":\"OpenAI-zpihD\"},\"selected\":true,\"dragging\":false,\"positionAbsolute\":{\"x\":-56.983202536768374,\"y\":61.715652677908665}}],\"edges\":[],\"viewport\":{\"x\":104.85568116317398,\"y\":88.26375874183478,\"zoom\":0.7169776240079145}},\"is_component\":false,\"updated_at\":\"2023-12-09T13:40:48.453096\",\"folder\":null,\"id\":\"2e59d013-2acb-49a6-915b-9231a7e6eb58\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"CSVAgent (1)\",\"description\":\"Construct a CSV agent from a CSV and tools.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CSVAgent\",\"node\":{\"template\":{\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".csv\"],\"file_path\":null},\"_type\":\"csv_agent\"},\"description\":\"Construct a CSV agent from a CSV and tools.\",\"base_classes\":[\"AgentExecutor\"],\"display_name\":\"CSVAgent\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/agents/toolkits/csv\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"CSVAgent-jsHqy\"},\"id\":\"CSVAgent-jsHqy\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T13:31:17.317322\",\"folder\":null,\"id\":\"ab1034a9-9b5b-4c65-bf6e-9f098a403942\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Suspicious Wilsonfasdfsd\",\"description\":\"Building Linguistic Labyrinths.fasdfads\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-09T14:43:45.298121\",\"folder\":null,\"id\":\"7d91c0c5-fba6-4c60-b4d1-11d430ef357a\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"AirbyteJSONLoader (1)\",\"description\":\"Load local `Airbyte` json files.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"AirbyteJSONLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".json\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"\":\"\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"AirbyteJSONLoader\"},\"description\":\"Load local `Airbyte` json files.\",\"base_classes\":[\"Document\"],\"display_name\":\"AirbyteJSONLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/airbyte_json\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"AirbyteJSONLoader-pAHh6\"},\"id\":\"AirbyteJSONLoader-pAHh6\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T13:47:58.573137\",\"folder\":null,\"id\":\"f0cc4292-97cc-4748-803d-949e30dcf661\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"AirbyteJSONLoader\",\"description\":\"Load local `Airbyte` json files.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"AirbyteJSONLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".json\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"ff2\":\"d3bbd\"},{\"w\":\"bvd\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"AirbyteJSONLoader\"},\"description\":\"Load local `Airbyte` json files.\",\"base_classes\":[\"Document\"],\"display_name\":\"AirbyteJSONLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/airbyte_json\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"AirbyteJSONLoader-0zU2Q\"},\"id\":\"AirbyteJSONLoader-0zU2Q\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T13:50:09.035318\",\"folder\":null,\"id\":\"5e3c0d55-1a00-4e15-9821-0c625c6415ff\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"CSVAgent\",\"description\":\"Construct a CSV agent from a CSV and tools.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CSVAgent\",\"node\":{\"template\":{\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".csv\"],\"file_path\":null},\"_type\":\"csv_agent\"},\"description\":\"Construct a CSV agent from a CSV and tools.\",\"base_classes\":[\"AgentExecutor\"],\"display_name\":\"CSVAgent\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/agents/toolkits/csv\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"CSVAgent-Ub1Xe\"},\"id\":\"CSVAgent-Ub1Xe\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T13:50:16.985419\",\"folder\":null,\"id\":\"baee8061-4788-4ce6-928f-c6ce1ecb443c\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Lively Heisenberg\",\"description\":\"Maximize Impact with Intelligent Conversations.\",\"data\":{\"nodes\":[{\"width\":384,\"height\":366,\"id\":\"CSVLoader-RMUx9\",\"type\":\"genericNode\",\"position\":{\"x\":111,\"y\":345.51250076293945},\"data\":{\"type\":\"CSVLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".csv\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"z2b\":\"z9\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"CSVLoader\"},\"description\":\"Load a `CSV` file into a list of Documents.\",\"base_classes\":[\"Document\"],\"display_name\":\"CSVLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/csv\",\"beta\":false,\"error\":null},\"id\":\"CSVLoader-RMUx9\"},\"positionAbsolute\":{\"x\":111,\"y\":345.51250076293945}}],\"edges\":[],\"viewport\":{\"x\":0,\"y\":0,\"zoom\":1}},\"is_component\":false,\"updated_at\":\"2023-12-09T14:38:40.291137\",\"folder\":null,\"id\":\"109e9629-d569-4555-9d40-42203a5ed035\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"CohereEmbeddings\",\"description\":\"Cohere embedding models.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CohereEmbeddings\",\"node\":{\"template\":{\"async_client\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"async_client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"cohere_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"cohere_api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"max_retries\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"model\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"embed-english-v2.0\",\"password\":false,\"name\":\"model\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"truncate\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"truncate\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"user_agent\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"langchain\",\"password\":false,\"name\":\"user_agent\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"CohereEmbeddings\"},\"description\":\"Cohere embedding models.\",\"base_classes\":[\"CohereEmbeddings\",\"Embeddings\"],\"display_name\":\"CohereEmbeddings\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/cohere\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"CohereEmbeddings-HFUAf\"},\"id\":\"CohereEmbeddings-HFUAf\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T13:50:46.172344\",\"folder\":null,\"id\":\"662d8040-d47c-40db-bda1-66489a1c9d24\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"CSVLoader (1)\",\"description\":\"Load a `CSV` file into a list of Documents.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CSVLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".csv\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"cddscz23\":\"aaqd\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"CSVLoader\"},\"description\":\"Load a `CSV` file into a list of Documents.\",\"base_classes\":[\"Document\"],\"display_name\":\"CSVLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/csv\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"CSVLoader-3wrib\"},\"id\":\"CSVLoader-3wrib\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T13:56:11.662526\",\"folder\":null,\"id\":\"4fae6aec-ddbd-498d-a4d1-ca0290f6a5ad\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"CSVLoader (2)\",\"description\":\"Load a `CSV` file into a list of Documents.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CSVLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".csv\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"cddscz23\":\"aaqd\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"CSVLoader\"},\"description\":\"Load a `CSV` file into a list of Documents.\",\"base_classes\":[\"Document\"],\"display_name\":\"CSVLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/csv\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"CSVLoader-VEjyx\"},\"id\":\"CSVLoader-VEjyx\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T13:57:37.560784\",\"folder\":null,\"id\":\"d80635ee-966c-41f2-981c-afa2c388ac6e\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"CSVLoader (3)\",\"description\":\"Load a `CSV` file into a list of Documents.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CSVLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".csv\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"cddscz23\":\"aaqd\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"CSVLoader\"},\"description\":\"Load a `CSV` file into a list of Documents.\",\"base_classes\":[\"Document\"],\"display_name\":\"CSVLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/csv\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"CSVLoader-PIhOc\"},\"id\":\"CSVLoader-PIhOc\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:00:27.991966\",\"folder\":null,\"id\":\"c5cc4c32-77c8-4889-a9f8-2632466b7366\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"CSVLoader (4)\",\"description\":\"Load a `CSV` file into a list of Documents.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CSVLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".csv\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"cddscz23\":\"aaqd\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"CSVLoader\"},\"description\":\"Load a `CSV` file into a list of Documents.\",\"base_classes\":[\"Document\"],\"display_name\":\"CSVLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/csv\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"CSVLoader-deB43\"},\"id\":\"CSVLoader-deB43\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:00:42.509243\",\"folder\":null,\"id\":\"0ab59938-ccf4-4bb9-b285-1f5da38648f0\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"CSVLoader\",\"description\":\"Load a `CSV` file into a list of Documents.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CSVLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".csv\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"\":\"aaqd\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"CSVLoader\"},\"description\":\"Load a `CSV` file into a list of Documents.\",\"base_classes\":[\"Document\"],\"display_name\":\"CSVLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/csv\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"CSVLoader-mdkLm\"},\"id\":\"CSVLoader-mdkLm\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:02:17.458354\",\"folder\":null,\"id\":\"f127b7e7-4149-492e-8998-6b1b35ec4153\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"CSVLoader (5)\",\"description\":\"Load a `CSV` file into a list of Documents.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CSVLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".csv\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"cddscz23\":\"aaqd\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"CSVLoader\"},\"description\":\"Load a `CSV` file into a list of Documents.\",\"base_classes\":[\"Document\"],\"display_name\":\"CSVLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/csv\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"CSVLoader-FRc6Y\"},\"id\":\"CSVLoader-FRc6Y\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:02:26.958867\",\"folder\":null,\"id\":\"a870a096-725c-4914-add0-8d57d710b7e5\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"AirbyteJSONLoader (2)\",\"description\":\"Load local `Airbyte` json files.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"AirbyteJSONLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".json\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"\":\"\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"AirbyteJSONLoader\"},\"description\":\"Load local `Airbyte` json files.\",\"base_classes\":[\"Document\"],\"display_name\":\"AirbyteJSONLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/airbyte_json\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"AirbyteJSONLoader-Z0uol\"},\"id\":\"AirbyteJSONLoader-Z0uol\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:03:33.764117\",\"folder\":null,\"id\":\"2a37c76c-65c8-4c01-a72d-eb46f3d41a56\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Amazon Bedrock Embeddings\",\"description\":\"Embeddings model from Amazon Bedrock.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"AmazonBedrockEmbeddings\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain.embeddings import BedrockEmbeddings\\nfrom langchain.embeddings.base import Embeddings\\nfrom langflow import CustomComponent\\n\\n\\nclass AmazonBedrockEmeddingsComponent(CustomComponent):\\n \\\"\\\"\\\"\\n A custom component for implementing an Embeddings Model using Amazon Bedrock.\\n \\\"\\\"\\\"\\n\\n display_name: str = \\\"Amazon Bedrock Embeddings\\\"\\n description: str = \\\"Embeddings model from Amazon Bedrock.\\\"\\n documentation = \\\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock\\\"\\n beta = True\\n\\n def build_config(self):\\n return {\\n \\\"model_id\\\": {\\n \\\"display_name\\\": \\\"Model Id\\\",\\n \\\"options\\\": [\\\"amazon.titan-embed-text-v1\\\"],\\n },\\n \\\"credentials_profile_name\\\": {\\\"display_name\\\": \\\"Credentials Profile Name\\\"},\\n \\\"endpoint_url\\\": {\\\"display_name\\\": \\\"Bedrock Endpoint URL\\\"},\\n \\\"region_name\\\": {\\\"display_name\\\": \\\"AWS Region\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n model_id: str = \\\"amazon.titan-embed-text-v1\\\",\\n credentials_profile_name: Optional[str] = None,\\n endpoint_url: Optional[str] = None,\\n region_name: Optional[str] = None,\\n ) -> Embeddings:\\n try:\\n output = BedrockEmbeddings(\\n credentials_profile_name=credentials_profile_name,\\n model_id=model_id,\\n endpoint_url=endpoint_url,\\n region_name=region_name,\\n ) # type: ignore\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to AmazonBedrock API.\\\") from e\\n return output\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"credentials_profile_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"credentials_profile_name\",\"display_name\":\"Credentials Profile Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"endpoint_url\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"endpoint_url\",\"display_name\":\"Bedrock Endpoint URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"model_id\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"amazon.titan-embed-text-v1\",\"password\":false,\"options\":[\"amazon.titan-embed-text-v1\"],\"name\":\"model_id\",\"display_name\":\"Model Id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"region_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"region_name\",\"display_name\":\"AWS Region\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"Embeddings model from Amazon Bedrock.\",\"base_classes\":[\"Embeddings\"],\"display_name\":\"Amazon Bedrock Embeddings\",\"custom_fields\":{\"credentials_profile_name\":null,\"endpoint_url\":null,\"model_id\":null,\"region_name\":null},\"output_types\":[\"AmazonBedrockEmbeddings\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"AmazonBedrockEmbeddings-28ASv\"},\"id\":\"AmazonBedrockEmbeddings-28ASv\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:03:41.066618\",\"folder\":null,\"id\":\"850ba4e6-96ca-49a7-9b0c-4b7048fd52c8\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"ConversationBufferMemory\",\"description\":\"Buffer for storing conversation memory.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"ConversationBufferMemory\",\"node\":{\"template\":{\"chat_memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"chat_memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseChatMessageHistory\",\"list\":false},\"ai_prefix\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"AI\",\"password\":false,\"name\":\"ai_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"human_prefix\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"Human\",\"password\":false,\"name\":\"human_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"input_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"input_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Input when more than one variable is available.\",\"type\":\"str\",\"list\":false},\"memory_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"chat_history\",\"password\":false,\"name\":\"memory_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"output_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"output_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Output (e.g. answer in a ConversationalRetrievalChain)\",\"type\":\"str\",\"list\":false},\"return_messages\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"return_messages\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ConversationBufferMemory\"},\"description\":\"Buffer for storing conversation memory.\",\"base_classes\":[\"BaseMemory\",\"BaseChatMemory\",\"ConversationBufferMemory\"],\"display_name\":\"ConversationBufferMemory\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/memory/how_to/buffer\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"ConversationBufferMemory-WaoLx\"},\"id\":\"ConversationBufferMemory-WaoLx\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:04:46.058568\",\"folder\":null,\"id\":\"be650940-0449-4eb0-a708-056310f924fd\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Amazon Bedrock Embeddings (1)\",\"description\":\"Embeddings model from Amazon Bedrock.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"AmazonBedrockEmbeddings\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain.embeddings import BedrockEmbeddings\\nfrom langchain.embeddings.base import Embeddings\\nfrom langflow import CustomComponent\\n\\n\\nclass AmazonBedrockEmeddingsComponent(CustomComponent):\\n \\\"\\\"\\\"\\n A custom component for implementing an Embeddings Model using Amazon Bedrock.\\n \\\"\\\"\\\"\\n\\n display_name: str = \\\"Amazon Bedrock Embeddings\\\"\\n description: str = \\\"Embeddings model from Amazon Bedrock.\\\"\\n documentation = \\\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock\\\"\\n beta = True\\n\\n def build_config(self):\\n return {\\n \\\"model_id\\\": {\\n \\\"display_name\\\": \\\"Model Id\\\",\\n \\\"options\\\": [\\\"amazon.titan-embed-text-v1\\\"],\\n },\\n \\\"credentials_profile_name\\\": {\\\"display_name\\\": \\\"Credentials Profile Name\\\"},\\n \\\"endpoint_url\\\": {\\\"display_name\\\": \\\"Bedrock Endpoint URL\\\"},\\n \\\"region_name\\\": {\\\"display_name\\\": \\\"AWS Region\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n model_id: str = \\\"amazon.titan-embed-text-v1\\\",\\n credentials_profile_name: Optional[str] = None,\\n endpoint_url: Optional[str] = None,\\n region_name: Optional[str] = None,\\n ) -> Embeddings:\\n try:\\n output = BedrockEmbeddings(\\n credentials_profile_name=credentials_profile_name,\\n model_id=model_id,\\n endpoint_url=endpoint_url,\\n region_name=region_name,\\n ) # type: ignore\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to AmazonBedrock API.\\\") from e\\n return output\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"credentials_profile_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"credentials_profile_name\",\"display_name\":\"Credentials Profile Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"endpoint_url\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"endpoint_url\",\"display_name\":\"Bedrock Endpoint URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"model_id\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"amazon.titan-embed-text-v1\",\"password\":false,\"options\":[\"amazon.titan-embed-text-v1\"],\"name\":\"model_id\",\"display_name\":\"Model Id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"region_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"region_name\",\"display_name\":\"AWS Region\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"Embeddings model from Amazon Bedrock.\",\"base_classes\":[\"Embeddings\"],\"display_name\":\"Amazon Bedrock Embeddings\",\"custom_fields\":{\"credentials_profile_name\":null,\"endpoint_url\":null,\"model_id\":null,\"region_name\":null},\"output_types\":[\"AmazonBedrockEmbeddings\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"AmazonBedrockEmbeddings-Bs5PG\"},\"id\":\"AmazonBedrockEmbeddings-Bs5PG\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:05:50.570800\",\"folder\":null,\"id\":\"53ad1fe2-f3af-4354-86e0-eb141ce12859\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Amazon Bedrock Embeddings (2)\",\"description\":\"Embeddings model from Amazon Bedrock.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"AmazonBedrockEmbeddings\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain.embeddings import BedrockEmbeddings\\nfrom langchain.embeddings.base import Embeddings\\nfrom langflow import CustomComponent\\n\\n\\nclass AmazonBedrockEmeddingsComponent(CustomComponent):\\n \\\"\\\"\\\"\\n A custom component for implementing an Embeddings Model using Amazon Bedrock.\\n \\\"\\\"\\\"\\n\\n display_name: str = \\\"Amazon Bedrock Embeddings\\\"\\n description: str = \\\"Embeddings model from Amazon Bedrock.\\\"\\n documentation = \\\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock\\\"\\n beta = True\\n\\n def build_config(self):\\n return {\\n \\\"model_id\\\": {\\n \\\"display_name\\\": \\\"Model Id\\\",\\n \\\"options\\\": [\\\"amazon.titan-embed-text-v1\\\"],\\n },\\n \\\"credentials_profile_name\\\": {\\\"display_name\\\": \\\"Credentials Profile Name\\\"},\\n \\\"endpoint_url\\\": {\\\"display_name\\\": \\\"Bedrock Endpoint URL\\\"},\\n \\\"region_name\\\": {\\\"display_name\\\": \\\"AWS Region\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n model_id: str = \\\"amazon.titan-embed-text-v1\\\",\\n credentials_profile_name: Optional[str] = None,\\n endpoint_url: Optional[str] = None,\\n region_name: Optional[str] = None,\\n ) -> Embeddings:\\n try:\\n output = BedrockEmbeddings(\\n credentials_profile_name=credentials_profile_name,\\n model_id=model_id,\\n endpoint_url=endpoint_url,\\n region_name=region_name,\\n ) # type: ignore\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to AmazonBedrock API.\\\") from e\\n return output\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"credentials_profile_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"credentials_profile_name\",\"display_name\":\"Credentials Profile Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"endpoint_url\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"endpoint_url\",\"display_name\":\"Bedrock Endpoint URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"model_id\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"amazon.titan-embed-text-v1\",\"password\":false,\"options\":[\"amazon.titan-embed-text-v1\"],\"name\":\"model_id\",\"display_name\":\"Model Id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"region_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"region_name\",\"display_name\":\"AWS Region\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"Embeddings model from Amazon Bedrock.\",\"base_classes\":[\"Embeddings\"],\"display_name\":\"Amazon Bedrock Embeddings\",\"custom_fields\":{\"credentials_profile_name\":null,\"endpoint_url\":null,\"model_id\":null,\"region_name\":null},\"output_types\":[\"AmazonBedrockEmbeddings\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"AmazonBedrockEmbeddings-zSZ4t\"},\"id\":\"AmazonBedrockEmbeddings-zSZ4t\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:06:11.415088\",\"folder\":null,\"id\":\"e9ed1c90-146e-452d-8ccd-ebf2e0da4331\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Amazon Bedrock Embeddings (3)\",\"description\":\"Embeddings model from Amazon Bedrock.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"AmazonBedrockEmbeddings\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain.embeddings import BedrockEmbeddings\\nfrom langchain.embeddings.base import Embeddings\\nfrom langflow import CustomComponent\\n\\n\\nclass AmazonBedrockEmeddingsComponent(CustomComponent):\\n \\\"\\\"\\\"\\n A custom component for implementing an Embeddings Model using Amazon Bedrock.\\n \\\"\\\"\\\"\\n\\n display_name: str = \\\"Amazon Bedrock Embeddings\\\"\\n description: str = \\\"Embeddings model from Amazon Bedrock.\\\"\\n documentation = \\\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock\\\"\\n beta = True\\n\\n def build_config(self):\\n return {\\n \\\"model_id\\\": {\\n \\\"display_name\\\": \\\"Model Id\\\",\\n \\\"options\\\": [\\\"amazon.titan-embed-text-v1\\\"],\\n },\\n \\\"credentials_profile_name\\\": {\\\"display_name\\\": \\\"Credentials Profile Name\\\"},\\n \\\"endpoint_url\\\": {\\\"display_name\\\": \\\"Bedrock Endpoint URL\\\"},\\n \\\"region_name\\\": {\\\"display_name\\\": \\\"AWS Region\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n model_id: str = \\\"amazon.titan-embed-text-v1\\\",\\n credentials_profile_name: Optional[str] = None,\\n endpoint_url: Optional[str] = None,\\n region_name: Optional[str] = None,\\n ) -> Embeddings:\\n try:\\n output = BedrockEmbeddings(\\n credentials_profile_name=credentials_profile_name,\\n model_id=model_id,\\n endpoint_url=endpoint_url,\\n region_name=region_name,\\n ) # type: ignore\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to AmazonBedrock API.\\\") from e\\n return output\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"credentials_profile_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"credentials_profile_name\",\"display_name\":\"Credentials Profile Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"endpoint_url\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"endpoint_url\",\"display_name\":\"Bedrock Endpoint URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"model_id\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"amazon.titan-embed-text-v1\",\"password\":false,\"options\":[\"amazon.titan-embed-text-v1\"],\"name\":\"model_id\",\"display_name\":\"Model Id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"region_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"region_name\",\"display_name\":\"AWS Region\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"Embeddings model from Amazon Bedrock.\",\"base_classes\":[\"Embeddings\"],\"display_name\":\"Amazon Bedrock Embeddings\",\"custom_fields\":{\"credentials_profile_name\":null,\"endpoint_url\":null,\"model_id\":null,\"region_name\":null},\"output_types\":[\"AmazonBedrockEmbeddings\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"AmazonBedrockEmbeddings-Bxhlt\"},\"id\":\"AmazonBedrockEmbeddings-Bxhlt\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:07:06.411108\",\"folder\":null,\"id\":\"83783c57-64e3-41a6-aa7e-ed82f80f1e53\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"CSVLoader (6)\",\"description\":\"Load a `CSV` file into a list of Documents.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CSVLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".csv\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"z2b\":\"z9\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"CSVLoader\"},\"description\":\"Load a `CSV` file into a list of Documents.\",\"base_classes\":[\"Document\"],\"display_name\":\"CSVLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/csv\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"CSVLoader-2pn2o\"},\"id\":\"CSVLoader-2pn2o\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:38:30.706258\",\"folder\":null,\"id\":\"c4ae9de6-9df3-4d3c-afc9-1752af4fecd7\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Agent Initializer\",\"description\":\"Initialize a Langchain Agent.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"AgentInitializer\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from typing import Callable, List, Union\\n\\nfrom langchain.agents import AgentExecutor, AgentType, initialize_agent, types\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import BaseChatMemory, BaseLanguageModel, Tool\\n\\n\\nclass AgentInitializerComponent(CustomComponent):\\n display_name: str = \\\"Agent Initializer\\\"\\n description: str = \\\"Initialize a Langchain Agent.\\\"\\n documentation: str = \\\"https://python.langchain.com/docs/modules/agents/agent_types/\\\"\\n\\n def build_config(self):\\n agents = list(types.AGENT_TO_CLASS.keys())\\n # field_type and required are optional\\n return {\\n \\\"agent\\\": {\\\"options\\\": agents, \\\"value\\\": agents[0], \\\"display_name\\\": \\\"Agent Type\\\"},\\n \\\"max_iterations\\\": {\\\"display_name\\\": \\\"Max Iterations\\\", \\\"value\\\": 10},\\n \\\"memory\\\": {\\\"display_name\\\": \\\"Memory\\\"},\\n \\\"tools\\\": {\\\"display_name\\\": \\\"Tools\\\"},\\n \\\"llm\\\": {\\\"display_name\\\": \\\"Language Model\\\"},\\n }\\n\\n def build(\\n self, agent: str, llm: BaseLanguageModel, memory: BaseChatMemory, tools: List[Tool], max_iterations: int\\n ) -> Union[AgentExecutor, Callable]:\\n agent = AgentType(agent)\\n return initialize_agent(\\n tools=tools,\\n llm=llm,\\n agent=agent,\\n memory=memory,\\n return_intermediate_steps=True,\\n handle_parsing_errors=True,\\n max_iterations=max_iterations,\\n )\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"agent\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"zero-shot-react-description\",\"password\":false,\"options\":[\"zero-shot-react-description\",\"react-docstore\",\"self-ask-with-search\",\"conversational-react-description\",\"chat-zero-shot-react-description\",\"chat-conversational-react-description\",\"structured-chat-zero-shot-react-description\",\"openai-functions\",\"openai-multi-functions\",\"JsonAgent\",\"CSVAgent\",\"AgentInitializer\",\"VectorStoreAgent\",\"VectorStoreRouterAgent\",\"SQLAgent\"],\"name\":\"agent\",\"display_name\":\"Agent Type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"Language Model\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"max_iterations\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":10,\"password\":false,\"name\":\"max_iterations\",\"display_name\":\"Max Iterations\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"memory\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseChatMemory\",\"list\":false},\"tools\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"tools\",\"display_name\":\"Tools\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Tool\",\"list\":true}},\"description\":\"Initialize a Langchain Agent.\",\"base_classes\":[\"Chain\",\"AgentExecutor\",\"Callable\"],\"display_name\":\"Agent Initializer\",\"custom_fields\":{\"agent\":null,\"llm\":null,\"max_iterations\":null,\"memory\":null,\"tools\":null},\"output_types\":[\"AgentInitializer\"],\"documentation\":\"https://python.langchain.com/docs/modules/agents/agent_types/\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"AgentInitializer-MJrAC\"},\"id\":\"AgentInitializer-MJrAC\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:42:54.715163\",\"folder\":null,\"id\":\"ff84b5f9-5680-4084-a9f1-7d94fe675486\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Agent Initializer (1)\",\"description\":\"Initialize a Langchain Agent.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"AgentInitializer\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from typing import Callable, List, Union\\n\\nfrom langchain.agents import AgentExecutor, AgentType, initialize_agent, types\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import BaseChatMemory, BaseLanguageModel, Tool\\n\\n\\nclass AgentInitializerComponent(CustomComponent):\\n display_name: str = \\\"Agent Initializer\\\"\\n description: str = \\\"Initialize a Langchain Agent.\\\"\\n documentation: str = \\\"https://python.langchain.com/docs/modules/agents/agent_types/\\\"\\n\\n def build_config(self):\\n agents = list(types.AGENT_TO_CLASS.keys())\\n # field_type and required are optional\\n return {\\n \\\"agent\\\": {\\\"options\\\": agents, \\\"value\\\": agents[0], \\\"display_name\\\": \\\"Agent Type\\\"},\\n \\\"max_iterations\\\": {\\\"display_name\\\": \\\"Max Iterations\\\", \\\"value\\\": 10},\\n \\\"memory\\\": {\\\"display_name\\\": \\\"Memory\\\"},\\n \\\"tools\\\": {\\\"display_name\\\": \\\"Tools\\\"},\\n \\\"llm\\\": {\\\"display_name\\\": \\\"Language Model\\\"},\\n }\\n\\n def build(\\n self, agent: str, llm: BaseLanguageModel, memory: BaseChatMemory, tools: List[Tool], max_iterations: int\\n ) -> Union[AgentExecutor, Callable]:\\n agent = AgentType(agent)\\n return initialize_agent(\\n tools=tools,\\n llm=llm,\\n agent=agent,\\n memory=memory,\\n return_intermediate_steps=True,\\n handle_parsing_errors=True,\\n max_iterations=max_iterations,\\n )\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"agent\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"zero-shot-react-description\",\"password\":false,\"options\":[\"zero-shot-react-description\",\"react-docstore\",\"self-ask-with-search\",\"conversational-react-description\",\"chat-zero-shot-react-description\",\"chat-conversational-react-description\",\"structured-chat-zero-shot-react-description\",\"openai-functions\",\"openai-multi-functions\",\"JsonAgent\",\"CSVAgent\",\"AgentInitializer\",\"VectorStoreAgent\",\"VectorStoreRouterAgent\",\"SQLAgent\"],\"name\":\"agent\",\"display_name\":\"Agent Type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"Language Model\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"max_iterations\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":10,\"password\":false,\"name\":\"max_iterations\",\"display_name\":\"Max Iterations\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"memory\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseChatMemory\",\"list\":false},\"tools\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"tools\",\"display_name\":\"Tools\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Tool\",\"list\":true}},\"description\":\"Initialize a Langchain Agent.\",\"base_classes\":[\"Chain\",\"AgentExecutor\",\"Callable\"],\"display_name\":\"Agent Initializer\",\"custom_fields\":{\"agent\":null,\"llm\":null,\"max_iterations\":null,\"memory\":null,\"tools\":null},\"output_types\":[\"AgentInitializer\"],\"documentation\":\"https://python.langchain.com/docs/modules/agents/agent_types/\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"AgentInitializer-3lcZ4\"},\"id\":\"AgentInitializer-3lcZ4\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:43:20.819934\",\"folder\":null,\"id\":\"97f5db9f-d6cc-4555-88fb-3be102c67814\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Exuberant Banach\",\"description\":\"Unfolding Linguistic Possibilities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-09T14:52:49.951416\",\"folder\":null,\"id\":\"a600acd1-213a-4ce7-8648-ab2ee59f5918\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"AirbyteJSONLoader (3)\",\"description\":\"Load local `Airbyte` json files.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"AirbyteJSONLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".json\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"\":\"\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"AirbyteJSONLoader\"},\"description\":\"Load local `Airbyte` json files.\",\"base_classes\":[\"Document\"],\"display_name\":\"AirbyteJSONLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/airbyte_json\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"AirbyteJSONLoader-JhQtx\"},\"id\":\"AirbyteJSONLoader-JhQtx\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:44:49.587337\",\"folder\":null,\"id\":\"07c52ad7-ca52-4cdd-ab40-74a91dbad0dd\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"AirbyteJSONLoader (4)\",\"description\":\"Load local `Airbyte` json files.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"AirbyteJSONLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".json\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"\":\"\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"AirbyteJSONLoader\"},\"description\":\"Load local `Airbyte` json files.\",\"base_classes\":[\"Document\"],\"display_name\":\"AirbyteJSONLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/airbyte_json\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"AirbyteJSONLoader-bIvDc\"},\"id\":\"AirbyteJSONLoader-bIvDc\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:45:13.458500\",\"folder\":null,\"id\":\"53e4d256-3653-444b-b8e0-fb97b3ae5c7e\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"AirbyteJSONLoader (5)\",\"description\":\"Load local `Airbyte` json files.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"AirbyteJSONLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".json\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"\":\"\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"AirbyteJSONLoader\"},\"description\":\"Load local `Airbyte` json files.\",\"base_classes\":[\"Document\"],\"display_name\":\"AirbyteJSONLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/airbyte_json\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"AirbyteJSONLoader-2BLS8\"},\"id\":\"AirbyteJSONLoader-2BLS8\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:45:44.461699\",\"folder\":null,\"id\":\"b5158cc1-c6b8-4e25-907a-bc7e7637aa38\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Amazon Bedrock Embeddings (4)\",\"description\":\"Embeddings model from Amazon Bedrock.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"AmazonBedrockEmbeddings\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain.embeddings import BedrockEmbeddings\\nfrom langchain.embeddings.base import Embeddings\\nfrom langflow import CustomComponent\\n\\n\\nclass AmazonBedrockEmeddingsComponent(CustomComponent):\\n \\\"\\\"\\\"\\n A custom component for implementing an Embeddings Model using Amazon Bedrock.\\n \\\"\\\"\\\"\\n\\n display_name: str = \\\"Amazon Bedrock Embeddings\\\"\\n description: str = \\\"Embeddings model from Amazon Bedrock.\\\"\\n documentation = \\\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock\\\"\\n beta = True\\n\\n def build_config(self):\\n return {\\n \\\"model_id\\\": {\\n \\\"display_name\\\": \\\"Model Id\\\",\\n \\\"options\\\": [\\\"amazon.titan-embed-text-v1\\\"],\\n },\\n \\\"credentials_profile_name\\\": {\\\"display_name\\\": \\\"Credentials Profile Name\\\"},\\n \\\"endpoint_url\\\": {\\\"display_name\\\": \\\"Bedrock Endpoint URL\\\"},\\n \\\"region_name\\\": {\\\"display_name\\\": \\\"AWS Region\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n model_id: str = \\\"amazon.titan-embed-text-v1\\\",\\n credentials_profile_name: Optional[str] = None,\\n endpoint_url: Optional[str] = None,\\n region_name: Optional[str] = None,\\n ) -> Embeddings:\\n try:\\n output = BedrockEmbeddings(\\n credentials_profile_name=credentials_profile_name,\\n model_id=model_id,\\n endpoint_url=endpoint_url,\\n region_name=region_name,\\n ) # type: ignore\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to AmazonBedrock API.\\\") from e\\n return output\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"credentials_profile_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"credentials_profile_name\",\"display_name\":\"Credentials Profile Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"endpoint_url\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"endpoint_url\",\"display_name\":\"Bedrock Endpoint URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"model_id\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"amazon.titan-embed-text-v1\",\"password\":false,\"options\":[\"amazon.titan-embed-text-v1\"],\"name\":\"model_id\",\"display_name\":\"Model Id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"region_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"region_name\",\"display_name\":\"AWS Region\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"Embeddings model from Amazon Bedrock.\",\"base_classes\":[\"Embeddings\"],\"display_name\":\"Amazon Bedrock Embeddings\",\"custom_fields\":{\"credentials_profile_name\":null,\"endpoint_url\":null,\"model_id\":null,\"region_name\":null},\"output_types\":[\"AmazonBedrockEmbeddings\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"AmazonBedrockEmbeddings-NsBzN\"},\"id\":\"AmazonBedrockEmbeddings-NsBzN\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:50:29.791575\",\"folder\":null,\"id\":\"3fb77f72-1be7-4ce0-ae89-a82b0eee9acf\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Evil Golick\",\"description\":\"Where Language Meets Logic.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:19:02.707854\",\"folder\":null,\"id\":\"9c5d21c2-ea82-4cf4-a591-c3d3fd3f13e6\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Gleeful Davinci (1)\",\"description\":\"Unleashing Linguistic Creativity.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:19:02.761150\",\"folder\":null,\"id\":\"f8e2e16e-129c-4116-9626-2c6b524d97b7\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Effervescent Degrasse\",\"description\":\"Language Models, Mapped and Mastered.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:19:02.764440\",\"folder\":null,\"id\":\"d7f4f7b5-effe-4834-8cab-4f2fc4f6e9de\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Prickly Archimedes\",\"description\":\"Language Chainlink Master.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:19:02.767546\",\"folder\":null,\"id\":\"2265d813-4a87-410f-b06a-65e35db8219e\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Boring Heyrovsky\",\"description\":\"Building Intelligent Interactions.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:19:02.765105\",\"folder\":null,\"id\":\"10bfd881-e67e-4c33-965d-ee041695edce\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Nostalgic Carroll\",\"description\":\"Unfolding Linguistic Possibilities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:19:02.811794\",\"folder\":null,\"id\":\"63fa5653-4513-47f2-8dfa-baeb1d981f93\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Pensive Perlman\",\"description\":\"Empowering Communication, Enabling Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:19:02.814993\",\"folder\":null,\"id\":\"f4bc5945-20d9-4703-a5bb-6a4a3ef7fc8e\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Hilarious Stallman\",\"description\":\"Connect the Dots, Craft Language.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:19:02.813144\",\"folder\":null,\"id\":\"8d8b80f9-4b74-4cd5-bc5c-08a32c4d2b95\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Awesome Einstein\",\"description\":\"The Power of Language at Your Fingertips.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:20:19.518262\",\"folder\":null,\"id\":\"21808fd7-a492-4e29-8863-301c2785f542\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Funky Swanson\",\"description\":\"Sculpting Language with Precision.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:20:20.185637\",\"folder\":null,\"id\":\"7752299a-4aa9-44db-8d9c-5c4a2ac1b071\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Romantic Pascal\",\"description\":\"Unlock the Power of AI in Your Business Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:20:20.223064\",\"folder\":null,\"id\":\"78f48a13-6a9f-42ce-9d58-ec9b63b381d2\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Twinkly Bartik\",\"description\":\"Sculpting Language with Precision.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:20:20.239758\",\"folder\":null,\"id\":\"38074091-3d7c-4d42-b61b-ae195c1b8a4e\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Condescending Joliot\",\"description\":\"Language Models, Unleashed.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:20:20.271996\",\"folder\":null,\"id\":\"773020aa-5c2d-4632-ad9e-21276861ab93\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Gleeful Kalam\",\"description\":\"The Power of Language at Your Fingertips.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:20:20.283929\",\"folder\":null,\"id\":\"0092d077-6d31-401f-a739-b164476b90ed\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Grinning Bhabha\",\"description\":\"Your Passport to Linguistic Landscapes.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:20:20.467739\",\"folder\":null,\"id\":\"4a395211-712d-4dd2-b3bb-e6b19200f15d\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Mirthful Babbage\",\"description\":\"Design Dialogues with Langflow.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:20:20.742990\",\"folder\":null,\"id\":\"3f086a82-3e29-4328-9da8-e02dc9201744\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Tiny Volta\",\"description\":\"Nurture NLP Nodes Here.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:24:18.594247\",\"folder\":null,\"id\":\"659b8289-c8e8-413d-9b2b-51e68411f170\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Radiant Jennings\",\"description\":\"Design, Develop, Dialogize.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:24:42.640309\",\"folder\":null,\"id\":\"f55f0640-d47e-4471-b1ba-3411d38ecac5\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Distracted Shaw\",\"description\":\"Interactive Language Weaving.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:24:58.376247\",\"folder\":null,\"id\":\"a039811e-449a-4244-83ed-4ddd731a0921\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Peppy Murdock (1)\",\"description\":\"Language Chainlink Master.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:25:14.674524\",\"folder\":null,\"id\":\"0faf6144-6ca6-4f64-a343-665ae54774ef\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Lively Volta\",\"description\":\"Language Models, Mapped and Mastered.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:26:50.418029\",\"folder\":null,\"id\":\"c5d149d0-c401-4f5e-b79f-2abcc7b8d98d\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Bubbly Curie\",\"description\":\"Navigate the Networks of Conversation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:27:10.900899\",\"folder\":null,\"id\":\"7bb2d226-9740-433d-861f-a499632c5a13\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Radiant Nobel\",\"description\":\"Navigate the Linguistic Landscape, Discover Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:29:11.541630\",\"folder\":null,\"id\":\"947906d8-75ea-470c-a8e2-cc80c5d3bdbb\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Cheerful Northcutt\",\"description\":\"Unleashing Business Potential through Language Engineering.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:29:37.169791\",\"folder\":null,\"id\":\"56f109fd-2c18-42ed-a9b2-089a678a0c11\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Suspicious Khayyam\",\"description\":\"Crafting Dialogues that Drive Business Success.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:30:24.686359\",\"folder\":null,\"id\":\"551d7bfa-49aa-43f1-a779-e47eabc2aaf2\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Twinkly Spence\",\"description\":\"Create, Curate, Communicate with Langflow.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:30:47.738472\",\"folder\":null,\"id\":\"12aef128-130e-492e-bf84-62d4cb4cd456\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Mirthful Lavoisier\",\"description\":\"Nurture NLP Nodes Here.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:31:43.272365\",\"folder\":null,\"id\":\"9952c044-6903-4fba-a270-6ed0b90c93c9\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Upbeat Bose\",\"description\":\"Unravel the Art of Articulation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:32:23.972035\",\"folder\":null,\"id\":\"65f49582-c9fa-4c67-a2bc-4e8fa73ca731\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Tender Perlman\",\"description\":\"Maximize Impact with Intelligent Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:33:26.984083\",\"folder\":null,\"id\":\"9ae57fe2-c677-47fa-a059-7d3d915a1178\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Sharp Cori\",\"description\":\"Conversation Catalyst Engine.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:33:52.377359\",\"folder\":null,\"id\":\"2920dde2-5c24-4fe0-9c06-ef86b5a16a99\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"}]" - }, - "headersSize": -1, - "bodySize": -1, - "redirectURL": "" - }, - "cache": {}, - "timings": { "send": -1, "wait": -1, "receive": 1.03 } - }, - { - "startedDateTime": "2023-12-11T18:54:58.423Z", - "time": 0.901, - "request": { - "method": "GET", - "url": "http://localhost:3000/api/v1/all", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Accept", "value": "application/json, text/plain, */*" }, - { "name": "Accept-Encoding", "value": "gzip, deflate, br" }, - { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, - { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20" }, - { "name": "Connection", "value": "keep-alive" }, - { "name": "Cookie", "value": "access_token_lf=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20; refresh_tkn_lflw=auto" }, - { "name": "Host", "value": "localhost:3000" }, - { "name": "Referer", "value": "http://localhost:3000/flows" }, - { "name": "Sec-Fetch-Dest", "value": "empty" }, - { "name": "Sec-Fetch-Mode", "value": "cors" }, - { "name": "Sec-Fetch-Site", "value": "same-origin" }, - { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" }, - { "name": "sec-ch-ua", "value": "\"Chromium\";v=\"119\", \"Not?A_Brand\";v=\"24\"" }, - { "name": "sec-ch-ua-mobile", "value": "?0" }, - { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } - ], - "queryString": [], - "headersSize": -1, - "bodySize": -1 - }, - "response": { - "status": 200, - "statusText": "OK", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Access-Control-Allow-Origin", "value": "*" }, - { "name": "connection", "value": "close" }, - { "name": "content-length", "value": "331584" }, - { "name": "content-type", "value": "application/json" }, - { "name": "date", "value": "Mon, 11 Dec 2023 18:54:58 GMT" }, - { "name": "server", "value": "uvicorn" } - ], - "content": { - "size": -1, - "mimeType": "application/json", - "text": "{\"chains\":{\"ConversationalRetrievalChain\":{\"template\":{\"callbacks\":{\"type\":\"Callbacks\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"condense_question_llm\":{\"type\":\"BaseLanguageModel\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"condense_question_llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"condense_question_prompt\":{\"type\":\"BasePromptTemplate\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":{\"input_variables\":[\"chat_history\",\"question\"],\"input_types\":{},\"output_parser\":null,\"partial_variables\":{},\"template\":\"Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question, in its original language.\\n\\nChat History:\\n{chat_history}\\nFollow Up Input: {question}\\nStandalone question:\",\"template_format\":\"f-string\",\"validate_template\":false},\"fileTypes\":[],\"password\":false,\"name\":\"condense_question_prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"memory\":{\"type\":\"BaseChatMemory\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"retriever\":{\"type\":\"BaseRetriever\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"retriever\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"chain_type\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"stuff\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"stuff\",\"map_reduce\",\"map_rerank\",\"refine\"],\"name\":\"chain_type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"combine_docs_chain_kwargs\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"combine_docs_chain_kwargs\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"return_source_documents\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":true,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"return_source_documents\",\"display_name\":\"Return source documents\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"verbose\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"_type\":\"ConversationalRetrievalChain\"},\"description\":\"Convenience method to load chain from LLM and retriever.\",\"base_classes\":[\"BaseConversationalRetrievalChain\",\"ConversationalRetrievalChain\",\"Chain\",\"Callable\"],\"display_name\":\"ConversationalRetrievalChain\",\"documentation\":\"https://python.langchain.com/docs/modules/chains/popular/chat_vector_db\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"LLMCheckerChain\":{\"template\":{\"check_assertions_prompt\":{\"type\":\"PromptTemplate\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":{\"input_variables\":[\"assertions\"],\"input_types\":{},\"output_parser\":null,\"partial_variables\":{},\"template\":\"Here is a bullet point list of assertions:\\n{assertions}\\nFor each assertion, determine whether it is true or false. If it is false, explain why.\\n\\n\",\"template_format\":\"f-string\",\"validate_template\":false},\"fileTypes\":[],\"password\":false,\"name\":\"check_assertions_prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"create_draft_answer_prompt\":{\"type\":\"PromptTemplate\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":{\"input_variables\":[\"question\"],\"input_types\":{},\"output_parser\":null,\"partial_variables\":{},\"template\":\"{question}\\n\\n\",\"template_format\":\"f-string\",\"validate_template\":false},\"fileTypes\":[],\"password\":false,\"name\":\"create_draft_answer_prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"list_assertions_prompt\":{\"type\":\"PromptTemplate\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":{\"input_variables\":[\"statement\"],\"input_types\":{},\"output_parser\":null,\"partial_variables\":{},\"template\":\"Here is a statement:\\n{statement}\\nMake a bullet point list of the assumptions you made when producing the above statement.\\n\\n\",\"template_format\":\"f-string\",\"validate_template\":false},\"fileTypes\":[],\"password\":false,\"name\":\"list_assertions_prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"revised_answer_prompt\":{\"type\":\"PromptTemplate\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":{\"input_variables\":[\"checked_assertions\",\"question\"],\"input_types\":{},\"output_parser\":null,\"partial_variables\":{},\"template\":\"{checked_assertions}\\n\\nQuestion: In light of the above assertions and checks, how would you answer the question '{question}'?\\n\\nAnswer:\",\"template_format\":\"f-string\",\"validate_template\":false},\"fileTypes\":[],\"password\":false,\"name\":\"revised_answer_prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"LLMCheckerChain\"},\"description\":\"\",\"base_classes\":[\"Chain\",\"LLMCheckerChain\",\"Callable\"],\"display_name\":\"LLMCheckerChain\",\"documentation\":\"https://python.langchain.com/docs/modules/chains/additional/llm_checker\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"LLMMathChain\":{\"template\":{\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"llm_chain\":{\"type\":\"LLMChain\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"llm_chain\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"memory\":{\"type\":\"BaseMemory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"prompt\":{\"type\":\"BasePromptTemplate\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":{\"input_variables\":[\"question\"],\"input_types\":{},\"output_parser\":null,\"partial_variables\":{},\"template\":\"Translate a math problem into a expression that can be executed using Python's numexpr library. Use the output of running this code to answer the question.\\n\\nQuestion: ${{Question with math problem.}}\\n```text\\n${{single line mathematical expression that solves the problem}}\\n```\\n...numexpr.evaluate(text)...\\n```output\\n${{Output of running the code}}\\n```\\nAnswer: ${{Answer}}\\n\\nBegin.\\n\\nQuestion: What is 37593 * 67?\\n```text\\n37593 * 67\\n```\\n...numexpr.evaluate(\\\"37593 * 67\\\")...\\n```output\\n2518731\\n```\\nAnswer: 2518731\\n\\nQuestion: 37593^(1/5)\\n```text\\n37593**(1/5)\\n```\\n...numexpr.evaluate(\\\"37593**(1/5)\\\")...\\n```output\\n8.222831614237718\\n```\\nAnswer: 8.222831614237718\\n\\nQuestion: {question}\\n\",\"template_format\":\"f-string\",\"validate_template\":false},\"fileTypes\":[],\"password\":false,\"name\":\"prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"input_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"question\",\"fileTypes\":[],\"password\":false,\"name\":\"input_key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"output_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"answer\",\"fileTypes\":[],\"password\":false,\"name\":\"output_key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"verbose\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"_type\":\"LLMMathChain\"},\"description\":\"Chain that interprets a prompt and executes python code to do math.\",\"base_classes\":[\"Chain\",\"LLMMathChain\",\"Callable\"],\"display_name\":\"LLMMathChain\",\"documentation\":\"https://python.langchain.com/docs/modules/chains/additional/llm_math\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"RetrievalQA\":{\"template\":{\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"combine_documents_chain\":{\"type\":\"BaseCombineDocumentsChain\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"combine_documents_chain\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"memory\":{\"type\":\"BaseMemory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"retriever\":{\"type\":\"BaseRetriever\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"retriever\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"input_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"query\",\"fileTypes\":[],\"password\":false,\"name\":\"input_key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"output_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"result\",\"fileTypes\":[],\"password\":false,\"name\":\"output_key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"return_source_documents\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":true,\"fileTypes\":[],\"password\":false,\"name\":\"return_source_documents\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"verbose\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"_type\":\"RetrievalQA\"},\"description\":\"Chain for question-answering against an index.\",\"base_classes\":[\"RetrievalQA\",\"BaseRetrievalQA\",\"Chain\",\"Callable\"],\"display_name\":\"RetrievalQA\",\"documentation\":\"https://python.langchain.com/docs/modules/chains/popular/vector_db_qa\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"RetrievalQAWithSourcesChain\":{\"template\":{\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"combine_documents_chain\":{\"type\":\"BaseCombineDocumentsChain\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"combine_documents_chain\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"memory\":{\"type\":\"BaseMemory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"retriever\":{\"type\":\"BaseRetriever\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"retriever\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"answer_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"answer\",\"fileTypes\":[],\"password\":false,\"name\":\"answer_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"input_docs_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"docs\",\"fileTypes\":[],\"password\":false,\"name\":\"input_docs_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"max_tokens_limit\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":3375,\"fileTypes\":[],\"password\":false,\"name\":\"max_tokens_limit\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"question_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"question\",\"fileTypes\":[],\"password\":false,\"name\":\"question_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"reduce_k_below_max_tokens\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"reduce_k_below_max_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"return_source_documents\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":true,\"fileTypes\":[],\"password\":false,\"name\":\"return_source_documents\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"sources_answer_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"sources\",\"fileTypes\":[],\"password\":false,\"name\":\"sources_answer_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"verbose\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"_type\":\"RetrievalQAWithSourcesChain\"},\"description\":\"Question-answering with sources over an index.\",\"base_classes\":[\"RetrievalQAWithSourcesChain\",\"BaseQAWithSourcesChain\",\"Chain\",\"Callable\"],\"display_name\":\"RetrievalQAWithSourcesChain\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"SQLDatabaseChain\":{\"template\":{\"db\":{\"type\":\"SQLDatabase\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"db\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"prompt\":{\"type\":\"BasePromptTemplate\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"SQLDatabaseChain\"},\"description\":\"Create a SQLDatabaseChain from an LLM and a database connection.\",\"base_classes\":[\"SQLDatabaseChain\",\"Chain\",\"Callable\"],\"display_name\":\"SQLDatabaseChain\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"CombineDocsChain\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"chain_type\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"stuff\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"stuff\",\"map_reduce\",\"map_rerank\",\"refine\"],\"name\":\"chain_type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"load_qa_chain\"},\"description\":\"Load question answering chain.\",\"base_classes\":[\"BaseCombineDocumentsChain\",\"Callable\"],\"display_name\":\"CombineDocsChain\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"SeriesCharacterChain\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"character\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"character\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"series\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"series\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"SeriesCharacterChain\"},\"description\":\"SeriesCharacterChain is a chain you can use to have a conversation with a character from a series.\",\"base_classes\":[\"LLMChain\",\"BaseCustomChain\",\"Chain\",\"ConversationChain\",\"SeriesCharacterChain\",\"Callable\"],\"display_name\":\"SeriesCharacterChain\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"MidJourneyPromptChain\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"memory\":{\"type\":\"BaseChatMemory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"MidJourneyPromptChain\"},\"description\":\"MidJourneyPromptChain is a chain you can use to generate new MidJourney prompts.\",\"base_classes\":[\"LLMChain\",\"BaseCustomChain\",\"Chain\",\"ConversationChain\",\"MidJourneyPromptChain\"],\"display_name\":\"MidJourneyPromptChain\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"TimeTravelGuideChain\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"memory\":{\"type\":\"BaseChatMemory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"TimeTravelGuideChain\"},\"description\":\"Time travel guide chain.\",\"base_classes\":[\"LLMChain\",\"BaseCustomChain\",\"TimeTravelGuideChain\",\"Chain\",\"ConversationChain\"],\"display_name\":\"TimeTravelGuideChain\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"LLMChain\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"memory\":{\"type\":\"BaseMemory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"prompt\":{\"type\":\"BasePromptTemplate\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"prompt\",\"display_name\":\"Prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Callable, Optional, Union\\n\\nfrom langchain.chains import LLMChain\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import (\\n BaseLanguageModel,\\n BaseMemory,\\n BasePromptTemplate,\\n Chain,\\n)\\n\\n\\nclass LLMChainComponent(CustomComponent):\\n display_name = \\\"LLMChain\\\"\\n description = \\\"Chain to run queries against LLMs\\\"\\n\\n def build_config(self):\\n return {\\n \\\"prompt\\\": {\\\"display_name\\\": \\\"Prompt\\\"},\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"memory\\\": {\\\"display_name\\\": \\\"Memory\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n prompt: BasePromptTemplate,\\n llm: BaseLanguageModel,\\n memory: Optional[BaseMemory] = None,\\n ) -> Union[Chain, Callable]:\\n return LLMChain(prompt=prompt, llm=llm, memory=memory)\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"_type\":\"CustomComponent\"},\"description\":\"Chain to run queries against LLMs\",\"base_classes\":[\"Chain\",\"Callable\"],\"display_name\":\"LLMChain\",\"documentation\":\"\",\"custom_fields\":{\"llm\":null,\"memory\":null,\"prompt\":null},\"output_types\":[\"LLMChain\"],\"field_formatters\":{},\"beta\":true},\"ConversationChain\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"memory\":{\"type\":\"BaseMemory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"Memory to load context from. If none is provided, a ConversationBufferMemory will be used.\"},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langchain.chains import ConversationChain\\nfrom typing import Optional, Union, Callable\\nfrom langflow.field_typing import BaseLanguageModel, BaseMemory, Chain\\n\\n\\nclass ConversationChainComponent(CustomComponent):\\n display_name = \\\"ConversationChain\\\"\\n description = \\\"Chain to have a conversation and load context from memory.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"prompt\\\": {\\\"display_name\\\": \\\"Prompt\\\"},\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"memory\\\": {\\n \\\"display_name\\\": \\\"Memory\\\",\\n \\\"info\\\": \\\"Memory to load context from. If none is provided, a ConversationBufferMemory will be used.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n llm: BaseLanguageModel,\\n memory: Optional[BaseMemory] = None,\\n ) -> Union[Chain, Callable]:\\n if memory is None:\\n return ConversationChain(llm=llm)\\n return ConversationChain(llm=llm, memory=memory)\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"_type\":\"CustomComponent\"},\"description\":\"Chain to have a conversation and load context from memory.\",\"base_classes\":[\"Chain\",\"Callable\"],\"display_name\":\"ConversationChain\",\"documentation\":\"\",\"custom_fields\":{\"llm\":null,\"memory\":null},\"output_types\":[\"ConversationChain\"],\"field_formatters\":{},\"beta\":true},\"PromptRunner\":{\"template\":{\"llm\":{\"type\":\"BaseLLM\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"prompt\":{\"type\":\"PromptTemplate\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"prompt\",\"display_name\":\"Prompt Template\",\"advanced\":false,\"dynamic\":false,\"info\":\"Make sure the prompt has all variables filled.\"},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\n\\nfrom langchain.llms.base import BaseLLM\\nfrom langchain.prompts import PromptTemplate\\nfrom langchain.schema import Document\\n\\n\\nclass PromptRunner(CustomComponent):\\n display_name: str = \\\"Prompt Runner\\\"\\n description: str = \\\"Run a Chain with the given PromptTemplate\\\"\\n beta: bool = True\\n field_config = {\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"prompt\\\": {\\n \\\"display_name\\\": \\\"Prompt Template\\\",\\n \\\"info\\\": \\\"Make sure the prompt has all variables filled.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(self, llm: BaseLLM, prompt: PromptTemplate, inputs: dict = {}) -> Document:\\n chain = prompt | llm\\n # The input is an empty dict because the prompt is already filled\\n result = chain.invoke(input=inputs)\\n if hasattr(result, \\\"content\\\"):\\n result = result.content\\n self.repr_value = result\\n return Document(page_content=str(result))\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"inputs\":{\"type\":\"dict\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"inputs\",\"display_name\":\"inputs\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"CustomComponent\"},\"description\":\"Run a Chain with the given PromptTemplate\",\"base_classes\":[\"Document\"],\"display_name\":\"Prompt Runner\",\"documentation\":\"\",\"custom_fields\":{\"inputs\":null,\"llm\":null,\"prompt\":null},\"output_types\":[\"PromptRunner\"],\"field_formatters\":{},\"beta\":true}},\"agents\":{\"ZeroShotAgent\":{\"template\":{\"callback_manager\":{\"type\":\"BaseCallbackManager\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"callback_manager\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"output_parser\":{\"type\":\"AgentOutputParser\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tools\":{\"type\":\"BaseTool\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"tools\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"format_instructions\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":true,\"value\":\"Use the following format:\\n\\nQuestion: the input question you must answer\\nThought: you should always think about what to do\\nAction: the action to take, should be one of [{tool_names}]\\nAction Input: the input to the action\\nObservation: the result of the action\\n... (this Thought/Action/Action Input/Observation can repeat N times)\\nThought: I now know the final answer\\nFinal Answer: the final answer to the original input question\",\"fileTypes\":[],\"password\":false,\"name\":\"format_instructions\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"input_variables\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"input_variables\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"prefix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"Answer the following questions as best you can. You have access to the following tools:\",\"fileTypes\":[],\"password\":false,\"name\":\"prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"suffix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"Begin!\\n\\nQuestion: {input}\\nThought:{agent_scratchpad}\",\"fileTypes\":[],\"password\":false,\"name\":\"suffix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"ZeroShotAgent\"},\"description\":\"Construct an agent from an LLM and tools.\",\"base_classes\":[\"ZeroShotAgent\",\"BaseSingleActionAgent\",\"Agent\",\"Callable\"],\"display_name\":\"ZeroShotAgent\",\"documentation\":\"https://python.langchain.com/docs/modules/agents/how_to/custom_mrkl_agent\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"JsonAgent\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"toolkit\":{\"type\":\"BaseToolkit\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"toolkit\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"json_agent\"},\"description\":\"Construct a json agent from an LLM and tools.\",\"base_classes\":[\"AgentExecutor\"],\"display_name\":\"JsonAgent\",\"documentation\":\"https://python.langchain.com/docs/modules/agents/toolkits/openapi\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"CSVAgent\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".csv\"],\"file_path\":\"\",\"password\":false,\"name\":\"path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"csv_agent\"},\"description\":\"Construct a CSV agent from a CSV and tools.\",\"base_classes\":[\"AgentExecutor\"],\"display_name\":\"CSVAgent\",\"documentation\":\"https://python.langchain.com/docs/modules/agents/toolkits/csv\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"VectorStoreAgent\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"vectorstoreinfo\":{\"type\":\"VectorStoreInfo\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"vectorstoreinfo\",\"display_name\":\"Vector Store Info\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"vectorstore_agent\"},\"description\":\"Construct an agent from a Vector Store.\",\"base_classes\":[\"AgentExecutor\"],\"display_name\":\"VectorStoreAgent\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"VectorStoreRouterAgent\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"vectorstoreroutertoolkit\":{\"type\":\"VectorStoreRouterToolkit\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"vectorstoreroutertoolkit\",\"display_name\":\"Vector Store Router Toolkit\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"vectorstorerouter_agent\"},\"description\":\"Construct an agent from a Vector Store Router.\",\"base_classes\":[\"AgentExecutor\"],\"display_name\":\"VectorStoreRouterAgent\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"SQLAgent\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"database_uri\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"database_uri\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"sql_agent\"},\"description\":\"Construct an SQL agent from an LLM and tools.\",\"base_classes\":[\"AgentExecutor\"],\"display_name\":\"SQLAgent\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"AgentInitializer\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"Language Model\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"memory\":{\"type\":\"BaseChatMemory\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tools\":{\"type\":\"Tool\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tools\",\"display_name\":\"Tools\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"agent\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"zero-shot-react-description\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"zero-shot-react-description\",\"react-docstore\",\"self-ask-with-search\",\"conversational-react-description\",\"chat-zero-shot-react-description\",\"chat-conversational-react-description\",\"structured-chat-zero-shot-react-description\",\"openai-functions\",\"openai-multi-functions\",\"JsonAgent\",\"CSVAgent\",\"AgentInitializer\",\"VectorStoreAgent\",\"VectorStoreRouterAgent\",\"SQLAgent\"],\"name\":\"agent\",\"display_name\":\"Agent Type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Callable, List, Union\\n\\nfrom langchain.agents import AgentExecutor, AgentType, initialize_agent, types\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import BaseChatMemory, BaseLanguageModel, Tool\\n\\n\\nclass AgentInitializerComponent(CustomComponent):\\n display_name: str = \\\"Agent Initializer\\\"\\n description: str = \\\"Initialize a Langchain Agent.\\\"\\n documentation: str = \\\"https://python.langchain.com/docs/modules/agents/agent_types/\\\"\\n\\n def build_config(self):\\n agents = list(types.AGENT_TO_CLASS.keys())\\n # field_type and required are optional\\n return {\\n \\\"agent\\\": {\\\"options\\\": agents, \\\"value\\\": agents[0], \\\"display_name\\\": \\\"Agent Type\\\"},\\n \\\"max_iterations\\\": {\\\"display_name\\\": \\\"Max Iterations\\\", \\\"value\\\": 10},\\n \\\"memory\\\": {\\\"display_name\\\": \\\"Memory\\\"},\\n \\\"tools\\\": {\\\"display_name\\\": \\\"Tools\\\"},\\n \\\"llm\\\": {\\\"display_name\\\": \\\"Language Model\\\"},\\n }\\n\\n def build(\\n self, agent: str, llm: BaseLanguageModel, memory: BaseChatMemory, tools: List[Tool], max_iterations: int\\n ) -> Union[AgentExecutor, Callable]:\\n agent = AgentType(agent)\\n return initialize_agent(\\n tools=tools,\\n llm=llm,\\n agent=agent,\\n memory=memory,\\n return_intermediate_steps=True,\\n handle_parsing_errors=True,\\n max_iterations=max_iterations,\\n )\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"max_iterations\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":10,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_iterations\",\"display_name\":\"Max Iterations\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"CustomComponent\"},\"description\":\"Initialize a Langchain Agent.\",\"base_classes\":[\"AgentExecutor\",\"Chain\",\"Callable\"],\"display_name\":\"Agent Initializer\",\"documentation\":\"https://python.langchain.com/docs/modules/agents/agent_types/\",\"custom_fields\":{\"agent\":null,\"llm\":null,\"max_iterations\":null,\"memory\":null,\"tools\":null},\"output_types\":[\"AgentInitializer\"],\"field_formatters\":{},\"beta\":true},\"OpenAIConversationalAgent\":{\"template\":{\"memory\":{\"type\":\"BaseMemory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"system_message\":{\"type\":\"SystemMessagePromptTemplate\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"system_message\",\"display_name\":\"System Message\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tools\":{\"type\":\"Tool\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tools\",\"display_name\":\"Tools\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import List, Optional\\n\\nfrom langchain.agents.agent import AgentExecutor\\nfrom langchain.agents.agent_toolkits.conversational_retrieval.openai_functions import _get_default_system_message\\nfrom langchain.agents.openai_functions_agent.base import OpenAIFunctionsAgent\\nfrom langchain.chat_models import ChatOpenAI\\nfrom langchain.memory.token_buffer import ConversationTokenBufferMemory\\nfrom langchain.prompts import SystemMessagePromptTemplate\\nfrom langchain.prompts.chat import MessagesPlaceholder\\nfrom langchain.schema.memory import BaseMemory\\nfrom langchain.tools import Tool\\nfrom langflow import CustomComponent\\n\\n\\nclass ConversationalAgent(CustomComponent):\\n display_name: str = \\\"OpenAI Conversational Agent\\\"\\n description: str = \\\"Conversational Agent that can use OpenAI's function calling API\\\"\\n\\n def build_config(self):\\n openai_function_models = [\\n \\\"gpt-4-1106-preview\\\",\\n \\\"gpt-3.5-turbo\\\",\\n \\\"gpt-3.5-turbo-16k\\\",\\n \\\"gpt-4\\\",\\n \\\"gpt-4-32k\\\",\\n ]\\n return {\\n \\\"tools\\\": {\\\"display_name\\\": \\\"Tools\\\"},\\n \\\"memory\\\": {\\\"display_name\\\": \\\"Memory\\\"},\\n \\\"system_message\\\": {\\\"display_name\\\": \\\"System Message\\\"},\\n \\\"max_token_limit\\\": {\\\"display_name\\\": \\\"Max Token Limit\\\"},\\n \\\"model_name\\\": {\\n \\\"display_name\\\": \\\"Model Name\\\",\\n \\\"options\\\": openai_function_models,\\n \\\"value\\\": openai_function_models[0],\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n model_name: str,\\n openai_api_key: str,\\n tools: List[Tool],\\n openai_api_base: Optional[str] = None,\\n memory: Optional[BaseMemory] = None,\\n system_message: Optional[SystemMessagePromptTemplate] = None,\\n max_token_limit: int = 2000,\\n ) -> AgentExecutor:\\n llm = ChatOpenAI(\\n model=model_name,\\n api_key=openai_api_key,\\n base_url=openai_api_base,\\n )\\n if not memory:\\n memory_key = \\\"chat_history\\\"\\n memory = ConversationTokenBufferMemory(\\n memory_key=memory_key,\\n return_messages=True,\\n output_key=\\\"output\\\",\\n llm=llm,\\n max_token_limit=max_token_limit,\\n )\\n else:\\n memory_key = memory.memory_key # type: ignore\\n\\n _system_message = system_message or _get_default_system_message()\\n prompt = OpenAIFunctionsAgent.create_prompt(\\n system_message=_system_message, # type: ignore\\n extra_prompt_messages=[MessagesPlaceholder(variable_name=memory_key)],\\n )\\n agent = OpenAIFunctionsAgent(\\n llm=llm,\\n tools=tools,\\n prompt=prompt, # type: ignore\\n )\\n return AgentExecutor(\\n agent=agent,\\n tools=tools, # type: ignore\\n memory=memory,\\n verbose=True,\\n return_intermediate_steps=True,\\n handle_parsing_errors=True,\\n )\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"max_token_limit\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":2000,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"max_token_limit\",\"display_name\":\"Max Token Limit\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"model_name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"gpt-4-1106-preview\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"gpt-4-1106-preview\",\"gpt-3.5-turbo\",\"gpt-3.5-turbo-16k\",\"gpt-4\",\"gpt-4-32k\"],\"name\":\"model_name\",\"display_name\":\"Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"openai_api_base\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"openai_api_base\",\"display_name\":\"openai_api_base\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"openai_api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"openai_api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"CustomComponent\"},\"description\":\"Conversational Agent that can use OpenAI's function calling API\",\"base_classes\":[\"AgentExecutor\",\"Chain\"],\"display_name\":\"OpenAI Conversational Agent\",\"documentation\":\"\",\"custom_fields\":{\"max_token_limit\":null,\"memory\":null,\"model_name\":null,\"openai_api_base\":null,\"openai_api_key\":null,\"system_message\":null,\"tools\":null},\"output_types\":[\"OpenAIConversationalAgent\"],\"field_formatters\":{},\"beta\":true}},\"prompts\":{\"ChatMessagePromptTemplate\":{\"template\":{\"additional_kwargs\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"additional_kwargs\",\"advanced\":true,\"dynamic\":true,\"info\":\"\"},\"prompt\":{\"type\":\"prompt\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"\\nYou are a helpful assistant that talks casually about life in general.\\nYou are a good listener and you can talk about anything.\\n\",\"fileTypes\":[],\"password\":false,\"name\":\"prompt\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"role\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"role\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"_type\":\"ChatMessagePromptTemplate\"},\"description\":\"Chat message prompt template.\",\"base_classes\":[\"BaseStringMessagePromptTemplate\",\"ChatMessagePromptTemplate\",\"BaseMessagePromptTemplate\"],\"display_name\":\"ChatMessagePromptTemplate\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/msg_prompt_templates\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"ChatPromptTemplate\":{\"template\":{\"messages\":{\"type\":\"BaseMessagePromptTemplate\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"messages\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"output_parser\":{\"type\":\"BaseOutputParser\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"input_types\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"input_types\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"input_variables\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"input_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"partial_variables\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"partial_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"validate_template\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"validate_template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"_type\":\"ChatPromptTemplate\"},\"description\":\"A prompt template for chat models.\",\"base_classes\":[\"BaseChatPromptTemplate\",\"BasePromptTemplate\",\"ChatPromptTemplate\"],\"display_name\":\"ChatPromptTemplate\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/how_to/prompts\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"HumanMessagePromptTemplate\":{\"template\":{\"additional_kwargs\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"additional_kwargs\",\"advanced\":true,\"dynamic\":true,\"info\":\"\"},\"prompt\":{\"type\":\"prompt\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"\\nYou are a helpful assistant that talks casually about life in general.\\nYou are a good listener and you can talk about anything.\\n\",\"fileTypes\":[],\"password\":false,\"name\":\"prompt\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"_type\":\"HumanMessagePromptTemplate\"},\"description\":\"Human message prompt template. This is a message sent from the user.\",\"base_classes\":[\"BaseStringMessagePromptTemplate\",\"HumanMessagePromptTemplate\",\"BaseMessagePromptTemplate\"],\"display_name\":\"HumanMessagePromptTemplate\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/how_to/prompts\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"PromptTemplate\":{\"template\":{\"output_parser\":{\"type\":\"BaseOutputParser\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"input_types\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"input_types\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"input_variables\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"input_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"partial_variables\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"partial_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"template\":{\"type\":\"prompt\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"fileTypes\":[],\"password\":false,\"name\":\"template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"template_format\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"f-string\",\"fileTypes\":[],\"password\":false,\"name\":\"template_format\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"validate_template\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"validate_template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"_type\":\"PromptTemplate\"},\"description\":\"A prompt template for a language model.\",\"base_classes\":[\"BasePromptTemplate\",\"PromptTemplate\",\"StringPromptTemplate\"],\"display_name\":\"PromptTemplate\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"SystemMessagePromptTemplate\":{\"template\":{\"additional_kwargs\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"additional_kwargs\",\"advanced\":true,\"dynamic\":true,\"info\":\"\"},\"prompt\":{\"type\":\"prompt\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"\\nYou are a helpful assistant that talks casually about life in general.\\nYou are a good listener and you can talk about anything.\\n\",\"fileTypes\":[],\"password\":false,\"name\":\"prompt\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"_type\":\"SystemMessagePromptTemplate\"},\"description\":\"System message prompt template.\",\"base_classes\":[\"BaseStringMessagePromptTemplate\",\"SystemMessagePromptTemplate\",\"BaseMessagePromptTemplate\"],\"display_name\":\"SystemMessagePromptTemplate\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/how_to/prompts\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false}},\"llms\":{\"Anthropic\":{\"template\":{\"anthropic_api_key\":{\"type\":\"SecretStr\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":true,\"name\":\"anthropic_api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"count_tokens\":{\"type\":\"Callable[[str], int]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"count_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"AI_PROMPT\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"AI_PROMPT\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"HUMAN_PROMPT\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"HUMAN_PROMPT\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"anthropic_api_url\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"anthropic_api_url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"async_client\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"async_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"cache\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"client\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"default_request_timeout\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"default_request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"max_tokens_to_sample\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":256,\"fileTypes\":[],\"password\":false,\"name\":\"max_tokens_to_sample\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"model\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"claude-2\",\"fileTypes\":[],\"password\":false,\"name\":\"model\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"model_kwargs\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"streaming\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"top_k\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"top_k\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"top_p\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"top_p\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"verbose\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"Anthropic\"},\"description\":\"Anthropic large language models.\",\"base_classes\":[\"LLM\",\"BaseLanguageModel\",\"_AnthropicCommon\",\"BaseLLM\",\"Anthropic\"],\"display_name\":\"Anthropic\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"Cohere\":{\"template\":{\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"async_client\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"async_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"cache\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"client\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"cohere_api_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":true,\"name\":\"cohere_api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"frequency_penalty\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":0.0,\"fileTypes\":[],\"password\":false,\"name\":\"frequency_penalty\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"k\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":0,\"fileTypes\":[],\"password\":false,\"name\":\"k\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"max_retries\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":10,\"fileTypes\":[],\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"max_tokens\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":256,\"fileTypes\":[],\"password\":true,\"name\":\"max_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"model\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"model\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"p\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":1,\"fileTypes\":[],\"password\":false,\"name\":\"p\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"presence_penalty\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":0.0,\"fileTypes\":[],\"password\":false,\"name\":\"presence_penalty\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"stop\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"stop\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"streaming\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.75,\"fileTypes\":[],\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"truncate\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"truncate\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"user_agent\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"langchain\",\"fileTypes\":[],\"password\":false,\"name\":\"user_agent\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"verbose\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"Cohere\"},\"description\":\"Cohere large language models.\",\"base_classes\":[\"LLM\",\"BaseLanguageModel\",\"Cohere\",\"BaseLLM\",\"BaseCohere\"],\"display_name\":\"Cohere\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/cohere\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"CTransformers\":{\"template\":{\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"cache\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"client\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"config\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"{\\n \\\"top_k\\\": 40,\\n \\\"top_p\\\": 0.95,\\n \\\"temperature\\\": 0.8,\\n \\\"repetition_penalty\\\": 1.1,\\n \\\"last_n_tokens\\\": 64,\\n \\\"seed\\\": -1,\\n \\\"max_new_tokens\\\": 256,\\n \\\"stop\\\": null,\\n \\\"stream\\\": false,\\n \\\"reset\\\": true,\\n \\\"batch_size\\\": 8,\\n \\\"threads\\\": -1,\\n \\\"context_length\\\": -1,\\n \\\"gpu_layers\\\": 0\\n}\",\"fileTypes\":[],\"password\":false,\"name\":\"config\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"lib\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"lib\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"model\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"model\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"model_file\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"model_file\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"model_type\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"model_type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"verbose\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"CTransformers\"},\"description\":\"C Transformers LLM models.\",\"base_classes\":[\"LLM\",\"BaseLanguageModel\",\"BaseLLM\",\"CTransformers\"],\"display_name\":\"CTransformers\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/ctransformers\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"HuggingFaceHub\":{\"template\":{\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"cache\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"client\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"huggingfacehub_api_token\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":true,\"name\":\"huggingfacehub_api_token\",\"display_name\":\"HuggingFace Hub API Token\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"model_kwargs\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"repo_id\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"gpt2\",\"fileTypes\":[],\"password\":false,\"name\":\"repo_id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"task\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"text-generation\",\"fileTypes\":[],\"password\":false,\"options\":[\"text-generation\",\"text2text-generation\",\"summarization\"],\"name\":\"task\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"verbose\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"HuggingFaceHub\"},\"description\":\"HuggingFaceHub models.\",\"base_classes\":[\"LLM\",\"BaseLanguageModel\",\"HuggingFaceHub\",\"BaseLLM\"],\"display_name\":\"HuggingFaceHub\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/huggingface_hub\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"LlamaCpp\":{\"template\":{\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"callbacks\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"grammar\":{\"type\":\"ForwardRef('str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"grammar\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"cache\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"cache\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"client\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"echo\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"echo\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"f16_kv\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":true,\"fileTypes\":[],\"password\":false,\"name\":\"f16_kv\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"grammar_path\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"grammar_path\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"last_n_tokens_size\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":64,\"fileTypes\":[],\"password\":false,\"name\":\"last_n_tokens_size\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"logits_all\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"logits_all\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"logprobs\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"logprobs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"lora_base\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"lora_base\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"lora_path\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"lora_path\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"max_tokens\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":256,\"fileTypes\":[],\"password\":true,\"name\":\"max_tokens\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"metadata\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"model_kwargs\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"model_path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"model_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"n_batch\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":8,\"fileTypes\":[],\"password\":false,\"name\":\"n_batch\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"n_ctx\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":512,\"fileTypes\":[],\"password\":false,\"name\":\"n_ctx\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"n_gpu_layers\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"n_gpu_layers\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"n_parts\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":-1,\"fileTypes\":[],\"password\":false,\"name\":\"n_parts\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"n_threads\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"n_threads\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"repeat_penalty\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1.1,\"fileTypes\":[],\"password\":false,\"name\":\"repeat_penalty\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"rope_freq_base\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":10000.0,\"fileTypes\":[],\"password\":false,\"name\":\"rope_freq_base\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"rope_freq_scale\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1.0,\"fileTypes\":[],\"password\":false,\"name\":\"rope_freq_scale\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"seed\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":-1,\"fileTypes\":[],\"password\":false,\"name\":\"seed\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"stop\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":[],\"fileTypes\":[],\"password\":false,\"name\":\"stop\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"streaming\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":true,\"fileTypes\":[],\"password\":false,\"name\":\"streaming\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"suffix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"fileTypes\":[],\"password\":false,\"name\":\"suffix\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"tags\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.8,\"fileTypes\":[],\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"top_k\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":40,\"fileTypes\":[],\"password\":false,\"name\":\"top_k\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"top_p\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.95,\"fileTypes\":[],\"password\":false,\"name\":\"top_p\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"use_mlock\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"use_mlock\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"use_mmap\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":true,\"fileTypes\":[],\"password\":false,\"name\":\"use_mmap\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"verbose\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":true,\"fileTypes\":[],\"password\":false,\"name\":\"verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"vocab_only\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"vocab_only\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"_type\":\"LlamaCpp\"},\"description\":\"llama.cpp model.\",\"base_classes\":[\"LLM\",\"BaseLanguageModel\",\"LlamaCpp\",\"BaseLLM\"],\"display_name\":\"LlamaCpp\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/llamacpp\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"OpenAI\":{\"template\":{\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"allowed_special\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"value\":[],\"fileTypes\":[],\"password\":false,\"name\":\"allowed_special\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"async_client\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"async_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"batch_size\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":20,\"fileTypes\":[],\"password\":false,\"name\":\"batch_size\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"best_of\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":1,\"fileTypes\":[],\"password\":false,\"name\":\"best_of\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"cache\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"client\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"default_headers\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"default_headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"default_query\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"default_query\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"disallowed_special\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"all\",\"fileTypes\":[],\"password\":false,\"name\":\"disallowed_special\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"frequency_penalty\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":0,\"fileTypes\":[],\"password\":false,\"name\":\"frequency_penalty\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"http_client\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"http_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"logit_bias\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"logit_bias\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"max_retries\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":2,\"fileTypes\":[],\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"max_tokens\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":256,\"fileTypes\":[],\"password\":true,\"name\":\"max_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"model_kwargs\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"model_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"text-davinci-003\",\"fileTypes\":[],\"password\":false,\"options\":[\"text-davinci-003\",\"text-davinci-002\",\"text-curie-001\",\"text-babbage-001\",\"text-ada-001\"],\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"n\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":1,\"fileTypes\":[],\"password\":false,\"name\":\"n\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"openai_api_base\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":false,\"dynamic\":false,\"info\":\"\\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\\n\"},\"openai_api_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"openai_organization\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"openai_proxy\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"presence_penalty\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":0,\"fileTypes\":[],\"password\":false,\"name\":\"presence_penalty\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"request_timeout\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"streaming\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.7,\"fileTypes\":[],\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"tiktoken_model_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"top_p\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":1,\"fileTypes\":[],\"password\":false,\"name\":\"top_p\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"verbose\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"OpenAI\"},\"description\":\"OpenAI large language models.\",\"base_classes\":[\"BaseLanguageModel\",\"OpenAI\",\"BaseOpenAI\",\"BaseLLM\"],\"display_name\":\"OpenAI\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/openai\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"VertexAI\":{\"template\":{\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"client\":{\"type\":\"ForwardRef(\\\"'_LanguageModel'\\\")\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"client_preview\":{\"type\":\"ForwardRef(\\\"'_LanguageModel'\\\")\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"client_preview\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"credentials\":{\"type\":\"file\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".json\"],\"file_path\":\"\",\"password\":false,\"name\":\"credentials\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"cache\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"location\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"us-central1\",\"fileTypes\":[],\"password\":false,\"name\":\"location\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"max_output_tokens\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":128,\"fileTypes\":[],\"password\":false,\"name\":\"max_output_tokens\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"max_retries\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":6,\"fileTypes\":[],\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"model_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"text-bison\",\"fileTypes\":[],\"password\":false,\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"n\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1,\"fileTypes\":[],\"password\":false,\"name\":\"n\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"project\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"project\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"request_parallelism\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":5,\"fileTypes\":[],\"password\":false,\"name\":\"request_parallelism\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"stop\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"stop\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"streaming\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.0,\"fileTypes\":[],\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"top_k\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":40,\"fileTypes\":[],\"password\":false,\"name\":\"top_k\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"top_p\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.95,\"fileTypes\":[],\"password\":false,\"name\":\"top_p\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"tuned_model_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"tuned_model_name\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"verbose\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"_type\":\"VertexAI\"},\"description\":\"Google Vertex AI large language models.\",\"base_classes\":[\"BaseLanguageModel\",\"_VertexAIBase\",\"_VertexAICommon\",\"BaseLLM\",\"VertexAI\"],\"display_name\":\"VertexAI\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/google_vertex_ai_palm\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"ChatAnthropic\":{\"template\":{\"anthropic_api_key\":{\"type\":\"SecretStr\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":true,\"name\":\"anthropic_api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"count_tokens\":{\"type\":\"Callable[[str], int]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"count_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"AI_PROMPT\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"AI_PROMPT\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"HUMAN_PROMPT\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"HUMAN_PROMPT\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"anthropic_api_url\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"anthropic_api_url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"async_client\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"async_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"cache\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"client\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"default_request_timeout\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"default_request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"max_tokens_to_sample\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":256,\"fileTypes\":[],\"password\":false,\"name\":\"max_tokens_to_sample\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"model\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"claude-2\",\"fileTypes\":[],\"password\":false,\"name\":\"model\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"model_kwargs\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"streaming\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"top_k\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"top_k\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"top_p\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"top_p\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"verbose\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"ChatAnthropic\"},\"description\":\"`Anthropic` chat large language models.\",\"base_classes\":[\"_AnthropicCommon\",\"BaseLanguageModel\",\"BaseChatModel\",\"ChatAnthropic\",\"BaseLLM\"],\"display_name\":\"ChatAnthropic\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/integrations/anthropic\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"ChatOpenAI\":{\"template\":{\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"async_client\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"async_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"cache\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"client\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"default_headers\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"default_headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"default_query\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"default_query\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"http_client\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"http_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"max_retries\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":2,\"fileTypes\":[],\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"max_tokens\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":true,\"name\":\"max_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"model_kwargs\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"model_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"gpt-4-1106-preview\",\"fileTypes\":[],\"password\":false,\"options\":[\"gpt-4-1106-preview\",\"gpt-4-vision-preview\",\"gpt-4\",\"gpt-4-32k\",\"gpt-3.5-turbo\",\"gpt-3.5-turbo-16k\"],\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"n\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":1,\"fileTypes\":[],\"password\":false,\"name\":\"n\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"openai_api_base\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":false,\"dynamic\":false,\"info\":\"\\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\\n\"},\"openai_api_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"openai_organization\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"openai_proxy\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"request_timeout\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"streaming\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.7,\"fileTypes\":[],\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"tiktoken_model_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"verbose\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"ChatOpenAI\"},\"description\":\"`OpenAI` Chat large language models API.\",\"base_classes\":[\"BaseLanguageModel\",\"BaseChatModel\",\"ChatOpenAI\",\"BaseLLM\"],\"display_name\":\"ChatOpenAI\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"ChatVertexAI\":{\"template\":{\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"client\":{\"type\":\"ForwardRef(\\\"'_LanguageModel'\\\")\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"client_preview\":{\"type\":\"ForwardRef(\\\"'_LanguageModel'\\\")\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"client_preview\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"credentials\":{\"type\":\"file\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".json\"],\"file_path\":\"\",\"password\":false,\"name\":\"credentials\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"examples\":{\"type\":\"BaseMessage\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":true,\"fileTypes\":[],\"password\":false,\"name\":\"examples\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"cache\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"location\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"us-central1\",\"fileTypes\":[],\"password\":false,\"name\":\"location\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"max_output_tokens\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":128,\"fileTypes\":[],\"password\":false,\"name\":\"max_output_tokens\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"max_retries\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":6,\"fileTypes\":[],\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"model_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"chat-bison\",\"fileTypes\":[],\"password\":false,\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"n\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":1,\"fileTypes\":[],\"password\":false,\"name\":\"n\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"project\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"project\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"request_parallelism\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":5,\"fileTypes\":[],\"password\":false,\"name\":\"request_parallelism\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"stop\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"stop\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"streaming\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.0,\"fileTypes\":[],\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"top_k\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":40,\"fileTypes\":[],\"password\":false,\"name\":\"top_k\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"top_p\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.95,\"fileTypes\":[],\"password\":false,\"name\":\"top_p\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"verbose\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"_type\":\"ChatVertexAI\"},\"description\":\"`Vertex AI` Chat large language models API.\",\"base_classes\":[\"BaseLanguageModel\",\"BaseChatModel\",\"_VertexAIBase\",\"_VertexAICommon\",\"ChatVertexAI\",\"BaseLLM\"],\"display_name\":\"ChatVertexAI\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/integrations/google_vertex_ai_palm\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"AmazonBedrock\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\nfrom langflow import CustomComponent\\nfrom langchain.llms.bedrock import Bedrock\\nfrom langchain.llms.base import BaseLLM\\n\\n\\nclass AmazonBedrockComponent(CustomComponent):\\n display_name: str = \\\"Amazon Bedrock\\\"\\n description: str = \\\"LLM model from Amazon Bedrock.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"model_id\\\": {\\n \\\"display_name\\\": \\\"Model Id\\\",\\n \\\"options\\\": [\\n \\\"ai21.j2-grande-instruct\\\",\\n \\\"ai21.j2-jumbo-instruct\\\",\\n \\\"ai21.j2-mid\\\",\\n \\\"ai21.j2-mid-v1\\\",\\n \\\"ai21.j2-ultra\\\",\\n \\\"ai21.j2-ultra-v1\\\",\\n \\\"anthropic.claude-instant-v1\\\",\\n \\\"anthropic.claude-v1\\\",\\n \\\"anthropic.claude-v2\\\",\\n \\\"cohere.command-text-v14\\\",\\n ],\\n },\\n \\\"credentials_profile_name\\\": {\\\"display_name\\\": \\\"Credentials Profile Name\\\"},\\n \\\"streaming\\\": {\\\"display_name\\\": \\\"Streaming\\\", \\\"field_type\\\": \\\"bool\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n model_id: str = \\\"anthropic.claude-instant-v1\\\",\\n credentials_profile_name: Optional[str] = None,\\n ) -> BaseLLM:\\n try:\\n output = Bedrock(\\n credentials_profile_name=credentials_profile_name,\\n model_id=model_id,\\n ) # type: ignore\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to AmazonBedrock API.\\\") from e\\n return output\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"credentials_profile_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"credentials_profile_name\",\"display_name\":\"Credentials Profile Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"model_id\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"anthropic.claude-instant-v1\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"ai21.j2-grande-instruct\",\"ai21.j2-jumbo-instruct\",\"ai21.j2-mid\",\"ai21.j2-mid-v1\",\"ai21.j2-ultra\",\"ai21.j2-ultra-v1\",\"anthropic.claude-instant-v1\",\"anthropic.claude-v1\",\"anthropic.claude-v2\",\"cohere.command-text-v14\"],\"name\":\"model_id\",\"display_name\":\"Model Id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"CustomComponent\"},\"description\":\"LLM model from Amazon Bedrock.\",\"base_classes\":[\"BaseLanguageModel\",\"BaseLLM\"],\"display_name\":\"Amazon Bedrock\",\"documentation\":\"\",\"custom_fields\":{\"credentials_profile_name\":null,\"model_id\":null},\"output_types\":[\"AmazonBedrock\"],\"field_formatters\":{},\"beta\":true},\"AnthropicLLM\":{\"template\":{\"anthropic_api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"anthropic_api_key\",\"display_name\":\"Anthropic API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"Your Anthropic API key.\"},\"api_endpoint\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"api_endpoint\",\"display_name\":\"API Endpoint\",\"advanced\":false,\"dynamic\":false,\"info\":\"Endpoint of the Anthropic API. Defaults to 'https://api.anthropic.com' if not specified.\"},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain.chat_models.anthropic import ChatAnthropic\\nfrom langchain.llms.base import BaseLanguageModel\\nfrom pydantic.v1 import SecretStr\\n\\nfrom langflow import CustomComponent\\n\\n\\nclass AnthropicLLM(CustomComponent):\\n display_name: str = \\\"AnthropicLLM\\\"\\n description: str = \\\"Anthropic Chat&Completion large language models.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"model\\\": {\\n \\\"display_name\\\": \\\"Model Name\\\",\\n \\\"options\\\": [\\n \\\"claude-2.1\\\",\\n \\\"claude-2.0\\\",\\n \\\"claude-instant-1.2\\\",\\n \\\"claude-instant-1\\\",\\n # Add more models as needed\\n ],\\n \\\"info\\\": \\\"https://python.langchain.com/docs/integrations/chat/anthropic\\\",\\n \\\"required\\\": True,\\n \\\"value\\\": \\\"claude-2.1\\\",\\n },\\n \\\"anthropic_api_key\\\": {\\n \\\"display_name\\\": \\\"Anthropic API Key\\\",\\n \\\"required\\\": True,\\n \\\"password\\\": True,\\n \\\"info\\\": \\\"Your Anthropic API key.\\\",\\n },\\n \\\"max_tokens\\\": {\\n \\\"display_name\\\": \\\"Max Tokens\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"value\\\": 256,\\n },\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"value\\\": 0.7,\\n },\\n \\\"api_endpoint\\\": {\\n \\\"display_name\\\": \\\"API Endpoint\\\",\\n \\\"info\\\": \\\"Endpoint of the Anthropic API. Defaults to 'https://api.anthropic.com' if not specified.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n model: str,\\n anthropic_api_key: Optional[str] = None,\\n max_tokens: Optional[int] = None,\\n temperature: Optional[float] = None,\\n api_endpoint: Optional[str] = None,\\n ) -> BaseLanguageModel:\\n # Set default API endpoint if not provided\\n if not api_endpoint:\\n api_endpoint = \\\"https://api.anthropic.com\\\"\\n\\n try:\\n output = ChatAnthropic(\\n model_name=model,\\n anthropic_api_key=SecretStr(anthropic_api_key) if anthropic_api_key else None,\\n max_tokens_to_sample=max_tokens, # type: ignore\\n temperature=temperature,\\n anthropic_api_url=api_endpoint,\\n )\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to Anthropic API.\\\") from e\\n return output\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"max_tokens\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":256,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"max_tokens\",\"display_name\":\"Max Tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"model\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"claude-2.1\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"claude-2.1\",\"claude-2.0\",\"claude-instant-1.2\",\"claude-instant-1\"],\"name\":\"model\",\"display_name\":\"Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"https://python.langchain.com/docs/integrations/chat/anthropic\"},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.7,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"_type\":\"CustomComponent\"},\"description\":\"Anthropic Chat&Completion large language models.\",\"base_classes\":[\"BaseLanguageModel\"],\"display_name\":\"AnthropicLLM\",\"documentation\":\"\",\"custom_fields\":{\"anthropic_api_key\":null,\"api_endpoint\":null,\"max_tokens\":null,\"model\":null,\"temperature\":null},\"output_types\":[\"AnthropicLLM\"],\"field_formatters\":{},\"beta\":true},\"HuggingFaceEndpoints\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\nfrom langflow import CustomComponent\\nfrom langchain.llms.huggingface_endpoint import HuggingFaceEndpoint\\nfrom langchain.llms.base import BaseLLM\\n\\n\\nclass HuggingFaceEndpointsComponent(CustomComponent):\\n display_name: str = \\\"Hugging Face Inference API\\\"\\n description: str = \\\"LLM model from Hugging Face Inference API.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"endpoint_url\\\": {\\\"display_name\\\": \\\"Endpoint URL\\\", \\\"password\\\": True},\\n \\\"task\\\": {\\n \\\"display_name\\\": \\\"Task\\\",\\n \\\"options\\\": [\\\"text2text-generation\\\", \\\"text-generation\\\", \\\"summarization\\\"],\\n },\\n \\\"huggingfacehub_api_token\\\": {\\\"display_name\\\": \\\"API token\\\", \\\"password\\\": True},\\n \\\"model_kwargs\\\": {\\n \\\"display_name\\\": \\\"Model Keyword Arguments\\\",\\n \\\"field_type\\\": \\\"code\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n endpoint_url: str,\\n task: str = \\\"text2text-generation\\\",\\n huggingfacehub_api_token: Optional[str] = None,\\n model_kwargs: Optional[dict] = None,\\n ) -> BaseLLM:\\n try:\\n output = HuggingFaceEndpoint(\\n endpoint_url=endpoint_url,\\n task=task,\\n huggingfacehub_api_token=huggingfacehub_api_token,\\n model_kwargs=model_kwargs,\\n )\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to HuggingFace Endpoints API.\\\") from e\\n return output\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"endpoint_url\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"endpoint_url\",\"display_name\":\"Endpoint URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"huggingfacehub_api_token\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"huggingfacehub_api_token\",\"display_name\":\"API token\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"model_kwargs\":{\"type\":\"code\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model_kwargs\",\"display_name\":\"Model Keyword Arguments\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"task\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"text2text-generation\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"text2text-generation\",\"text-generation\",\"summarization\"],\"name\":\"task\",\"display_name\":\"Task\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"CustomComponent\"},\"description\":\"LLM model from Hugging Face Inference API.\",\"base_classes\":[\"BaseLanguageModel\",\"BaseLLM\"],\"display_name\":\"Hugging Face Inference API\",\"documentation\":\"\",\"custom_fields\":{\"endpoint_url\":null,\"huggingfacehub_api_token\":null,\"model_kwargs\":null,\"task\":null},\"output_types\":[\"HuggingFaceEndpoints\"],\"field_formatters\":{},\"beta\":true},\"BaiduQianfanChatEndpoints\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain.chat_models.baidu_qianfan_endpoint import QianfanChatEndpoint\\nfrom langchain.llms.base import BaseLLM\\nfrom pydantic.v1 import SecretStr\\n\\nfrom langflow import CustomComponent\\n\\n\\nclass QianfanChatEndpointComponent(CustomComponent):\\n display_name: str = \\\"QianfanChatEndpoint\\\"\\n description: str = (\\n \\\"Baidu Qianfan chat models. Get more detail from \\\"\\n \\\"https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint.\\\"\\n )\\n\\n def build_config(self):\\n return {\\n \\\"model\\\": {\\n \\\"display_name\\\": \\\"Model Name\\\",\\n \\\"options\\\": [\\n \\\"ERNIE-Bot\\\",\\n \\\"ERNIE-Bot-turbo\\\",\\n \\\"BLOOMZ-7B\\\",\\n \\\"Llama-2-7b-chat\\\",\\n \\\"Llama-2-13b-chat\\\",\\n \\\"Llama-2-70b-chat\\\",\\n \\\"Qianfan-BLOOMZ-7B-compressed\\\",\\n \\\"Qianfan-Chinese-Llama-2-7B\\\",\\n \\\"ChatGLM2-6B-32K\\\",\\n \\\"AquilaChat-7B\\\",\\n ],\\n \\\"info\\\": \\\"https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint\\\",\\n \\\"required\\\": True,\\n },\\n \\\"qianfan_ak\\\": {\\n \\\"display_name\\\": \\\"Qianfan Ak\\\",\\n \\\"required\\\": True,\\n \\\"password\\\": True,\\n \\\"info\\\": \\\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\\\",\\n },\\n \\\"qianfan_sk\\\": {\\n \\\"display_name\\\": \\\"Qianfan Sk\\\",\\n \\\"required\\\": True,\\n \\\"password\\\": True,\\n \\\"info\\\": \\\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\\\",\\n },\\n \\\"top_p\\\": {\\n \\\"display_name\\\": \\\"Top p\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\\\",\\n \\\"value\\\": 0.8,\\n },\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\\\",\\n \\\"value\\\": 0.95,\\n },\\n \\\"penalty_score\\\": {\\n \\\"display_name\\\": \\\"Penalty Score\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\\\",\\n \\\"value\\\": 1.0,\\n },\\n \\\"endpoint\\\": {\\n \\\"display_name\\\": \\\"Endpoint\\\",\\n \\\"info\\\": \\\"Endpoint of the Qianfan LLM, required if custom model used.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n model: str = \\\"ERNIE-Bot-turbo\\\",\\n qianfan_ak: Optional[str] = None,\\n qianfan_sk: Optional[str] = None,\\n top_p: Optional[float] = None,\\n temperature: Optional[float] = None,\\n penalty_score: Optional[float] = None,\\n endpoint: Optional[str] = None,\\n ) -> BaseLLM:\\n try:\\n output = QianfanChatEndpoint( # type: ignore\\n model=model,\\n qianfan_ak=SecretStr(qianfan_ak) if qianfan_ak else None,\\n qianfan_sk=SecretStr(qianfan_sk) if qianfan_sk else None,\\n top_p=top_p,\\n temperature=temperature,\\n penalty_score=penalty_score,\\n endpoint=endpoint,\\n )\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to Baidu Qianfan API.\\\") from e\\n return output # type: ignore\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"endpoint\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"endpoint\",\"display_name\":\"Endpoint\",\"advanced\":false,\"dynamic\":false,\"info\":\"Endpoint of the Qianfan LLM, required if custom model used.\"},\"model\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"ERNIE-Bot-turbo\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"ERNIE-Bot\",\"ERNIE-Bot-turbo\",\"BLOOMZ-7B\",\"Llama-2-7b-chat\",\"Llama-2-13b-chat\",\"Llama-2-70b-chat\",\"Qianfan-BLOOMZ-7B-compressed\",\"Qianfan-Chinese-Llama-2-7B\",\"ChatGLM2-6B-32K\",\"AquilaChat-7B\"],\"name\":\"model\",\"display_name\":\"Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint\"},\"penalty_score\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":1.0,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"penalty_score\",\"display_name\":\"Penalty Score\",\"advanced\":false,\"dynamic\":false,\"info\":\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"qianfan_ak\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"qianfan_ak\",\"display_name\":\"Qianfan Ak\",\"advanced\":false,\"dynamic\":false,\"info\":\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\"},\"qianfan_sk\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"qianfan_sk\",\"display_name\":\"Qianfan Sk\",\"advanced\":false,\"dynamic\":false,\"info\":\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\"},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.95,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"top_p\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":0.8,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_p\",\"display_name\":\"Top p\",\"advanced\":false,\"dynamic\":false,\"info\":\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"_type\":\"CustomComponent\"},\"description\":\"Baidu Qianfan chat models. Get more detail from https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint.\",\"base_classes\":[\"BaseLanguageModel\",\"BaseLLM\"],\"display_name\":\"QianfanChatEndpoint\",\"documentation\":\"\",\"custom_fields\":{\"endpoint\":null,\"model\":null,\"penalty_score\":null,\"qianfan_ak\":null,\"qianfan_sk\":null,\"temperature\":null,\"top_p\":null},\"output_types\":[\"BaiduQianfanChatEndpoints\"],\"field_formatters\":{},\"beta\":true},\"BaiduQianfanLLMEndpoints\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\nfrom langflow import CustomComponent\\nfrom langchain.llms.baidu_qianfan_endpoint import QianfanLLMEndpoint\\nfrom langchain.llms.base import BaseLLM\\n\\n\\nclass QianfanLLMEndpointComponent(CustomComponent):\\n display_name: str = \\\"QianfanLLMEndpoint\\\"\\n description: str = (\\n \\\"Baidu Qianfan hosted open source or customized models. \\\"\\n \\\"Get more detail from https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint\\\"\\n )\\n\\n def build_config(self):\\n return {\\n \\\"model\\\": {\\n \\\"display_name\\\": \\\"Model Name\\\",\\n \\\"options\\\": [\\n \\\"ERNIE-Bot\\\",\\n \\\"ERNIE-Bot-turbo\\\",\\n \\\"BLOOMZ-7B\\\",\\n \\\"Llama-2-7b-chat\\\",\\n \\\"Llama-2-13b-chat\\\",\\n \\\"Llama-2-70b-chat\\\",\\n \\\"Qianfan-BLOOMZ-7B-compressed\\\",\\n \\\"Qianfan-Chinese-Llama-2-7B\\\",\\n \\\"ChatGLM2-6B-32K\\\",\\n \\\"AquilaChat-7B\\\",\\n ],\\n \\\"info\\\": \\\"https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint\\\",\\n \\\"required\\\": True,\\n },\\n \\\"qianfan_ak\\\": {\\n \\\"display_name\\\": \\\"Qianfan Ak\\\",\\n \\\"required\\\": True,\\n \\\"password\\\": True,\\n \\\"info\\\": \\\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\\\",\\n },\\n \\\"qianfan_sk\\\": {\\n \\\"display_name\\\": \\\"Qianfan Sk\\\",\\n \\\"required\\\": True,\\n \\\"password\\\": True,\\n \\\"info\\\": \\\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\\\",\\n },\\n \\\"top_p\\\": {\\n \\\"display_name\\\": \\\"Top p\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\\\",\\n \\\"value\\\": 0.8,\\n },\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\\\",\\n \\\"value\\\": 0.95,\\n },\\n \\\"penalty_score\\\": {\\n \\\"display_name\\\": \\\"Penalty Score\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\\\",\\n \\\"value\\\": 1.0,\\n },\\n \\\"endpoint\\\": {\\n \\\"display_name\\\": \\\"Endpoint\\\",\\n \\\"info\\\": \\\"Endpoint of the Qianfan LLM, required if custom model used.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n model: str = \\\"ERNIE-Bot-turbo\\\",\\n qianfan_ak: Optional[str] = None,\\n qianfan_sk: Optional[str] = None,\\n top_p: Optional[float] = None,\\n temperature: Optional[float] = None,\\n penalty_score: Optional[float] = None,\\n endpoint: Optional[str] = None,\\n ) -> BaseLLM:\\n try:\\n output = QianfanLLMEndpoint( # type: ignore\\n model=model,\\n qianfan_ak=qianfan_ak,\\n qianfan_sk=qianfan_sk,\\n top_p=top_p,\\n temperature=temperature,\\n penalty_score=penalty_score,\\n endpoint=endpoint,\\n )\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to Baidu Qianfan API.\\\") from e\\n return output # type: ignore\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"endpoint\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"endpoint\",\"display_name\":\"Endpoint\",\"advanced\":false,\"dynamic\":false,\"info\":\"Endpoint of the Qianfan LLM, required if custom model used.\"},\"model\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"ERNIE-Bot-turbo\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"ERNIE-Bot\",\"ERNIE-Bot-turbo\",\"BLOOMZ-7B\",\"Llama-2-7b-chat\",\"Llama-2-13b-chat\",\"Llama-2-70b-chat\",\"Qianfan-BLOOMZ-7B-compressed\",\"Qianfan-Chinese-Llama-2-7B\",\"ChatGLM2-6B-32K\",\"AquilaChat-7B\"],\"name\":\"model\",\"display_name\":\"Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint\"},\"penalty_score\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":1.0,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"penalty_score\",\"display_name\":\"Penalty Score\",\"advanced\":false,\"dynamic\":false,\"info\":\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"qianfan_ak\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"qianfan_ak\",\"display_name\":\"Qianfan Ak\",\"advanced\":false,\"dynamic\":false,\"info\":\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\"},\"qianfan_sk\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"qianfan_sk\",\"display_name\":\"Qianfan Sk\",\"advanced\":false,\"dynamic\":false,\"info\":\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\"},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.95,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"top_p\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":0.8,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_p\",\"display_name\":\"Top p\",\"advanced\":false,\"dynamic\":false,\"info\":\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"_type\":\"CustomComponent\"},\"description\":\"Baidu Qianfan hosted open source or customized models. Get more detail from https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint\",\"base_classes\":[\"BaseLanguageModel\",\"BaseLLM\"],\"display_name\":\"QianfanLLMEndpoint\",\"documentation\":\"\",\"custom_fields\":{\"endpoint\":null,\"model\":null,\"penalty_score\":null,\"qianfan_ak\":null,\"qianfan_sk\":null,\"temperature\":null,\"top_p\":null},\"output_types\":[\"BaiduQianfanLLMEndpoints\"],\"field_formatters\":{},\"beta\":true}},\"memories\":{\"ConversationBufferMemory\":{\"template\":{\"chat_memory\":{\"type\":\"BaseChatMessageHistory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"chat_memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"ai_prefix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"AI\",\"fileTypes\":[],\"password\":false,\"name\":\"ai_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"human_prefix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"Human\",\"fileTypes\":[],\"password\":false,\"name\":\"human_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"input_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"input_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Input when more than one variable is available.\"},\"memory_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"chat_history\",\"fileTypes\":[],\"password\":false,\"name\":\"memory_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"output_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"output_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Output (e.g. answer in a ConversationalRetrievalChain)\"},\"return_messages\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"return_messages\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"ConversationBufferMemory\"},\"description\":\"Buffer for storing conversation memory.\",\"base_classes\":[\"BaseChatMemory\",\"BaseMemory\",\"ConversationBufferMemory\"],\"display_name\":\"ConversationBufferMemory\",\"documentation\":\"https://python.langchain.com/docs/modules/memory/how_to/buffer\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"ConversationBufferWindowMemory\":{\"template\":{\"chat_memory\":{\"type\":\"BaseChatMessageHistory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"chat_memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"ai_prefix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"AI\",\"fileTypes\":[],\"password\":false,\"name\":\"ai_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"human_prefix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"Human\",\"fileTypes\":[],\"password\":false,\"name\":\"human_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"input_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"input_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Input when more than one variable is available.\"},\"k\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":10,\"fileTypes\":[],\"password\":false,\"name\":\"k\",\"display_name\":\"Memory Size\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"memory_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"chat_history\",\"fileTypes\":[],\"password\":false,\"name\":\"memory_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"output_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"output_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Output (e.g. answer in a ConversationalRetrievalChain)\"},\"return_messages\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"return_messages\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"ConversationBufferWindowMemory\"},\"description\":\"Buffer for storing conversation memory inside a limited size window.\",\"base_classes\":[\"BaseChatMemory\",\"ConversationBufferWindowMemory\",\"BaseMemory\"],\"display_name\":\"ConversationBufferWindowMemory\",\"documentation\":\"https://python.langchain.com/docs/modules/memory/how_to/buffer_window\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"ConversationEntityMemory\":{\"template\":{\"chat_memory\":{\"type\":\"BaseChatMessageHistory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"chat_memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"entity_extraction_prompt\":{\"type\":\"BasePromptTemplate\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"entity_extraction_prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"entity_store\":{\"type\":\"BaseEntityStore\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"entity_store\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"entity_summarization_prompt\":{\"type\":\"BasePromptTemplate\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"entity_summarization_prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"ai_prefix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"AI\",\"fileTypes\":[],\"password\":false,\"name\":\"ai_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"chat_history_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"history\",\"fileTypes\":[],\"password\":false,\"name\":\"chat_history_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"entity_cache\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"entity_cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"human_prefix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"Human\",\"fileTypes\":[],\"password\":false,\"name\":\"human_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"input_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"input_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Input when more than one variable is available.\"},\"k\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":10,\"fileTypes\":[],\"password\":false,\"name\":\"k\",\"display_name\":\"Memory Size\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"output_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"output_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Output (e.g. answer in a ConversationalRetrievalChain)\"},\"return_messages\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"return_messages\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"ConversationEntityMemory\"},\"description\":\"Entity extractor & summarizer memory.\",\"base_classes\":[\"BaseChatMemory\",\"BaseMemory\",\"ConversationEntityMemory\"],\"display_name\":\"ConversationEntityMemory\",\"documentation\":\"https://python.langchain.com/docs/modules/memory/integrations/entity_memory_with_sqlite\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"ConversationKGMemory\":{\"template\":{\"chat_memory\":{\"type\":\"BaseChatMessageHistory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"chat_memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"entity_extraction_prompt\":{\"type\":\"BasePromptTemplate\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"entity_extraction_prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"kg\":{\"type\":\"NetworkxEntityGraph\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"kg\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"knowledge_extraction_prompt\":{\"type\":\"BasePromptTemplate\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"knowledge_extraction_prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"summary_message_cls\":{\"type\":\"Type[langchain_core.messages.base.BaseMessage]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"summary_message_cls\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"ai_prefix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"AI\",\"fileTypes\":[],\"password\":false,\"name\":\"ai_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"human_prefix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"Human\",\"fileTypes\":[],\"password\":false,\"name\":\"human_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"input_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"input_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Input when more than one variable is available.\"},\"k\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":10,\"fileTypes\":[],\"password\":false,\"name\":\"k\",\"display_name\":\"Memory Size\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"memory_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"chat_history\",\"fileTypes\":[],\"password\":false,\"name\":\"memory_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"output_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"output_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Output (e.g. answer in a ConversationalRetrievalChain)\"},\"return_messages\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"return_messages\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"ConversationKGMemory\"},\"description\":\"Knowledge graph conversation memory.\",\"base_classes\":[\"BaseChatMemory\",\"ConversationKGMemory\",\"BaseMemory\"],\"display_name\":\"ConversationKGMemory\",\"documentation\":\"https://python.langchain.com/docs/modules/memory/how_to/kg\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"ConversationSummaryMemory\":{\"template\":{\"chat_memory\":{\"type\":\"BaseChatMessageHistory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"chat_memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"prompt\":{\"type\":\"BasePromptTemplate\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"summary_message_cls\":{\"type\":\"Type[langchain_core.messages.base.BaseMessage]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"summary_message_cls\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"ai_prefix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"AI\",\"fileTypes\":[],\"password\":false,\"name\":\"ai_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"buffer\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"password\":false,\"name\":\"buffer\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"human_prefix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"Human\",\"fileTypes\":[],\"password\":false,\"name\":\"human_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"input_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"input_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Input when more than one variable is available.\"},\"memory_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"chat_history\",\"fileTypes\":[],\"password\":false,\"name\":\"memory_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"output_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"output_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Output (e.g. answer in a ConversationalRetrievalChain)\"},\"return_messages\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"return_messages\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"ConversationSummaryMemory\"},\"description\":\"Conversation summarizer to chat memory.\",\"base_classes\":[\"BaseChatMemory\",\"ConversationSummaryMemory\",\"BaseMemory\",\"SummarizerMixin\"],\"display_name\":\"ConversationSummaryMemory\",\"documentation\":\"https://python.langchain.com/docs/modules/memory/how_to/summary\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"MongoDBChatMessageHistory\":{\"template\":{\"collection_name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"message_store\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"collection_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"connection_string\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"connection_string\",\"advanced\":false,\"dynamic\":false,\"info\":\"MongoDB connection string (e.g mongodb://mongo_user:password123@mongo:27017)\"},\"database_name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"chat_history\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"database_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"session_id\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"session_id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"MongoDBChatMessageHistory\"},\"description\":\"Memory store with MongoDB\",\"base_classes\":[\"MongoDBChatMessageHistory\",\"BaseChatMessageHistory\"],\"display_name\":\"MongoDBChatMessageHistory\",\"documentation\":\"https://python.langchain.com/docs/modules/memory/integrations/mongodb_chat_message_history\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"MotorheadMemory\":{\"template\":{\"chat_memory\":{\"type\":\"BaseChatMessageHistory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"chat_memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"api_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"client_id\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"client_id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"context\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"context\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"input_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"input_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Input when more than one variable is available.\"},\"memory_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"chat_history\",\"fileTypes\":[],\"password\":false,\"name\":\"memory_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"output_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"output_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Output (e.g. answer in a ConversationalRetrievalChain)\"},\"return_messages\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"return_messages\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"session_id\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"session_id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"timeout\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"url\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"https://api.getmetal.io/v1/motorhead\",\"fileTypes\":[],\"password\":false,\"name\":\"url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"MotorheadMemory\"},\"description\":\"Chat message memory backed by Motorhead service.\",\"base_classes\":[\"BaseChatMemory\",\"MotorheadMemory\",\"BaseMemory\"],\"display_name\":\"MotorheadMemory\",\"documentation\":\"https://python.langchain.com/docs/integrations/memory/motorhead_memory\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"PostgresChatMessageHistory\":{\"template\":{\"connection_string\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"postgresql://postgres:mypassword@localhost/chat_history\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"connection_string\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"session_id\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"session_id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"table_name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"message_store\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"table_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"PostgresChatMessageHistory\"},\"description\":\"Memory store with Postgres\",\"base_classes\":[\"PostgresChatMessageHistory\",\"BaseChatMessageHistory\"],\"display_name\":\"PostgresChatMessageHistory\",\"documentation\":\"https://python.langchain.com/docs/modules/memory/integrations/postgres_chat_message_history\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"VectorStoreRetrieverMemory\":{\"template\":{\"retriever\":{\"type\":\"VectorStoreRetriever\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"retriever\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"exclude_input_keys\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"exclude_input_keys\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"input_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"input_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Input when more than one variable is available.\"},\"memory_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"chat_history\",\"fileTypes\":[],\"password\":false,\"name\":\"memory_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"return_docs\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"return_docs\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"return_messages\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"return_messages\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"VectorStoreRetrieverMemory\"},\"description\":\"VectorStoreRetriever-backed memory.\",\"base_classes\":[\"BaseMemory\",\"VectorStoreRetrieverMemory\"],\"display_name\":\"VectorStoreRetrieverMemory\",\"documentation\":\"https://python.langchain.com/docs/modules/memory/how_to/vectorstore_retriever_memory\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false}},\"tools\":{\"Calculator\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"Calculator\"},\"description\":\"Useful for when you need to answer questions about math.\",\"base_classes\":[\"Tool\",\"BaseTool\"],\"display_name\":\"Calculator\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"Search\":{\"template\":{\"aiosession\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"aiosession\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"serpapi_api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"serpapi_api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"Search\"},\"description\":\"A search engine. Useful for when you need to answer questions about current events. Input should be a search query.\",\"base_classes\":[\"Tool\",\"BaseTool\"],\"display_name\":\"Search\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"Tool\":{\"template\":{\"func\":{\"type\":\"Callable\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"func\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"description\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"description\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"return_direct\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"return_direct\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"Tool\"},\"description\":\"Converts a chain, agent or function into a tool.\",\"base_classes\":[\"Tool\",\"BaseTool\"],\"display_name\":\"Tool\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"PythonFunctionTool\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"\\ndef python_function(text: str) -> str:\\n \\\"\\\"\\\"This is a default python function that returns the input text\\\"\\\"\\\"\\n return text\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"description\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"description\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"return_direct\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"return_direct\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"PythonFunctionTool\"},\"description\":\"Python function to be executed.\",\"base_classes\":[\"BaseTool\",\"Tool\"],\"display_name\":\"PythonFunctionTool\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"PythonFunction\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"\\ndef python_function(text: str) -> str:\\n \\\"\\\"\\\"This is a default python function that returns the input text\\\"\\\"\\\"\\n return text\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"PythonFunction\"},\"description\":\"Python function to be executed.\",\"base_classes\":[\"Callable\"],\"display_name\":\"PythonFunction\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"JsonSpec\":{\"template\":{\"path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".json\",\".yaml\",\".yml\"],\"file_path\":\"\",\"password\":false,\"name\":\"path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"max_value_length\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_value_length\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"JsonSpec\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"JsonSpec\"],\"display_name\":\"JsonSpec\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"BingSearchRun\":{\"template\":{\"api_wrapper\":{\"type\":\"BingSearchAPIWrapper\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"api_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"BingSearchRun\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"BaseTool\",\"BingSearchRun\"],\"display_name\":\"BingSearchRun\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"GoogleSearchResults\":{\"template\":{\"api_wrapper\":{\"type\":\"GoogleSearchAPIWrapper\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"api_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"num_results\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":4,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"num_results\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"GoogleSearchResults\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"GoogleSearchResults\",\"BaseTool\"],\"display_name\":\"GoogleSearchResults\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"GoogleSearchRun\":{\"template\":{\"api_wrapper\":{\"type\":\"GoogleSearchAPIWrapper\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"api_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"GoogleSearchRun\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"BaseTool\",\"GoogleSearchRun\"],\"display_name\":\"GoogleSearchRun\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"GoogleSerperRun\":{\"template\":{\"api_wrapper\":{\"type\":\"GoogleSerperAPIWrapper\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"api_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"GoogleSerperRun\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"BaseTool\",\"GoogleSerperRun\"],\"display_name\":\"GoogleSerperRun\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"InfoSQLDatabaseTool\":{\"template\":{\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"db\":{\"type\":\"SQLDatabase\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"db\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"InfoSQLDatabaseTool\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"BaseSQLDatabaseTool\",\"BaseTool\",\"InfoSQLDatabaseTool\"],\"display_name\":\"InfoSQLDatabaseTool\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"JsonGetValueTool\":{\"template\":{\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"spec\":{\"type\":\"JsonSpec\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"spec\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"JsonGetValueTool\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"BaseTool\",\"JsonGetValueTool\"],\"display_name\":\"JsonGetValueTool\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"JsonListKeysTool\":{\"template\":{\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"spec\":{\"type\":\"JsonSpec\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"spec\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"JsonListKeysTool\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"JsonListKeysTool\",\"BaseTool\"],\"display_name\":\"JsonListKeysTool\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"ListSQLDatabaseTool\":{\"template\":{\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"db\":{\"type\":\"SQLDatabase\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"db\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"ListSQLDatabaseTool\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"BaseSQLDatabaseTool\",\"ListSQLDatabaseTool\",\"BaseTool\"],\"display_name\":\"ListSQLDatabaseTool\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"QuerySQLDataBaseTool\":{\"template\":{\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"db\":{\"type\":\"SQLDatabase\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"db\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"QuerySQLDataBaseTool\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"BaseSQLDatabaseTool\",\"BaseTool\",\"QuerySQLDataBaseTool\"],\"display_name\":\"QuerySQLDataBaseTool\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"RequestsDeleteTool\":{\"template\":{\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"requests_wrapper\":{\"type\":\"TextRequestsWrapper\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"requests_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"RequestsDeleteTool\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"RequestsDeleteTool\",\"BaseRequestsTool\",\"BaseTool\"],\"display_name\":\"RequestsDeleteTool\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"RequestsGetTool\":{\"template\":{\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"requests_wrapper\":{\"type\":\"TextRequestsWrapper\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"requests_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"RequestsGetTool\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"RequestsGetTool\",\"BaseRequestsTool\",\"BaseTool\"],\"display_name\":\"RequestsGetTool\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"RequestsPatchTool\":{\"template\":{\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"requests_wrapper\":{\"type\":\"TextRequestsWrapper\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"requests_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"RequestsPatchTool\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"RequestsPatchTool\",\"BaseRequestsTool\",\"BaseTool\"],\"display_name\":\"RequestsPatchTool\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"RequestsPostTool\":{\"template\":{\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"requests_wrapper\":{\"type\":\"TextRequestsWrapper\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"requests_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"RequestsPostTool\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"RequestsPostTool\",\"BaseRequestsTool\",\"BaseTool\"],\"display_name\":\"RequestsPostTool\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"RequestsPutTool\":{\"template\":{\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"requests_wrapper\":{\"type\":\"TextRequestsWrapper\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"requests_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"RequestsPutTool\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"BaseRequestsTool\",\"BaseTool\",\"RequestsPutTool\"],\"display_name\":\"RequestsPutTool\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"WikipediaQueryRun\":{\"template\":{\"api_wrapper\":{\"type\":\"WikipediaAPIWrapper\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"api_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"WikipediaQueryRun\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"WikipediaQueryRun\",\"BaseTool\"],\"display_name\":\"WikipediaQueryRun\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"WolframAlphaQueryRun\":{\"template\":{\"api_wrapper\":{\"type\":\"WolframAlphaAPIWrapper\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"api_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"WolframAlphaQueryRun\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"BaseTool\",\"WolframAlphaQueryRun\"],\"display_name\":\"WolframAlphaQueryRun\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false}},\"toolkits\":{\"JsonToolkit\":{\"template\":{\"spec\":{\"type\":\"JsonSpec\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"spec\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"JsonToolkit\"},\"description\":\"Toolkit for interacting with a JSON spec.\",\"base_classes\":[\"JsonToolkit\",\"BaseToolkit\",\"Tool\"],\"display_name\":\"JsonToolkit\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"OpenAPIToolkit\":{\"template\":{\"json_agent\":{\"type\":\"AgentExecutor\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"json_agent\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"requests_wrapper\":{\"type\":\"TextRequestsWrapper\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"requests_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"OpenAPIToolkit\"},\"description\":\"Toolkit for interacting with an OpenAPI API.\",\"base_classes\":[\"OpenAPIToolkit\",\"BaseToolkit\",\"Tool\"],\"display_name\":\"OpenAPIToolkit\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"VectorStoreInfo\":{\"template\":{\"vectorstore\":{\"type\":\"VectorStore\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"vectorstore\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"description\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"fileTypes\":[],\"password\":false,\"name\":\"description\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"VectorStoreInfo\"},\"description\":\"Information about a VectorStore.\",\"base_classes\":[\"VectorStoreInfo\"],\"display_name\":\"VectorStoreInfo\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"VectorStoreRouterToolkit\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"vectorstores\":{\"type\":\"VectorStoreInfo\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"vectorstores\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"VectorStoreRouterToolkit\"},\"description\":\"Toolkit for routing between Vector Stores.\",\"base_classes\":[\"VectorStoreRouterToolkit\",\"BaseToolkit\",\"Tool\"],\"display_name\":\"VectorStoreRouterToolkit\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"VectorStoreToolkit\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"vectorstore_info\":{\"type\":\"VectorStoreInfo\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"vectorstore_info\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"VectorStoreToolkit\"},\"description\":\"Toolkit for interacting with a Vector Store.\",\"base_classes\":[\"VectorStoreToolkit\",\"BaseToolkit\",\"Tool\"],\"display_name\":\"VectorStoreToolkit\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"Metaphor\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import List, Union\\n\\nfrom langchain.agents import tool\\nfrom langchain.agents.agent_toolkits.base import BaseToolkit\\nfrom langchain.tools import Tool\\nfrom metaphor_python import Metaphor # type: ignore\\n\\nfrom langflow import CustomComponent\\n\\n\\nclass MetaphorToolkit(CustomComponent):\\n display_name: str = \\\"Metaphor\\\"\\n description: str = \\\"Metaphor Toolkit\\\"\\n documentation = \\\"https://python.langchain.com/docs/integrations/tools/metaphor_search\\\"\\n beta: bool = True\\n # api key should be password = True\\n field_config = {\\n \\\"metaphor_api_key\\\": {\\\"display_name\\\": \\\"Metaphor API Key\\\", \\\"password\\\": True},\\n \\\"code\\\": {\\\"advanced\\\": True},\\n }\\n\\n def build(\\n self,\\n metaphor_api_key: str,\\n use_autoprompt: bool = True,\\n search_num_results: int = 5,\\n similar_num_results: int = 5,\\n ) -> Union[Tool, BaseToolkit]:\\n # If documents, then we need to create a Vectara instance using .from_documents\\n client = Metaphor(api_key=metaphor_api_key)\\n\\n @tool\\n def search(query: str):\\n \\\"\\\"\\\"Call search engine with a query.\\\"\\\"\\\"\\n return client.search(query, use_autoprompt=use_autoprompt, num_results=search_num_results)\\n\\n @tool\\n def get_contents(ids: List[str]):\\n \\\"\\\"\\\"Get contents of a webpage.\\n\\n The ids passed in should be a list of ids as fetched from `search`.\\n \\\"\\\"\\\"\\n return client.get_contents(ids)\\n\\n @tool\\n def find_similar(url: str):\\n \\\"\\\"\\\"Get search results similar to a given URL.\\n\\n The url passed in should be a URL returned from `search`\\n \\\"\\\"\\\"\\n return client.find_similar(url, num_results=similar_num_results)\\n\\n return [search, get_contents, find_similar] # type: ignore\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":true,\"dynamic\":true,\"info\":\"\"},\"metaphor_api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"metaphor_api_key\",\"display_name\":\"Metaphor API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"search_num_results\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":5,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"search_num_results\",\"display_name\":\"search_num_results\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"similar_num_results\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":5,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"similar_num_results\",\"display_name\":\"similar_num_results\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"use_autoprompt\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":true,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"use_autoprompt\",\"display_name\":\"use_autoprompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"CustomComponent\"},\"description\":\"Metaphor Toolkit\",\"base_classes\":[\"Tool\",\"BaseTool\",\"BaseToolkit\"],\"display_name\":\"Metaphor\",\"documentation\":\"https://python.langchain.com/docs/integrations/tools/metaphor_search\",\"custom_fields\":{\"metaphor_api_key\":null,\"search_num_results\":null,\"similar_num_results\":null,\"use_autoprompt\":null},\"output_types\":[\"Metaphor\"],\"field_formatters\":{},\"beta\":true}},\"wrappers\":{\"TextRequestsWrapper\":{\"template\":{\"aiosession\":{\"type\":\"ClientSession\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"aiosession\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"auth\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"auth\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"headers\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"{\\\"Authorization\\\": \\\"Bearer \\\"}\",\"fileTypes\":[],\"password\":false,\"name\":\"headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"TextRequestsWrapper\"},\"description\":\"Lightweight wrapper around requests library.\",\"base_classes\":[\"TextRequestsWrapper\"],\"display_name\":\"TextRequestsWrapper\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"SQLDatabase\":{\"template\":{\"database_uri\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"database_uri\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"engine_args\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"engine_args\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"SQLDatabase\"},\"description\":\"Construct a SQLAlchemy engine from URI.\",\"base_classes\":[\"SQLDatabase\",\"Callable\"],\"display_name\":\"SQLDatabase\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false}},\"embeddings\":{\"OpenAIEmbeddings\":{\"template\":{\"allowed_special\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":[],\"fileTypes\":[],\"password\":false,\"name\":\"allowed_special\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"async_client\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"async_client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"chunk_size\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1000,\"fileTypes\":[],\"password\":false,\"name\":\"chunk_size\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"client\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"default_headers\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"default_headers\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"default_query\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"default_query\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"deployment\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"text-embedding-ada-002\",\"fileTypes\":[],\"password\":false,\"name\":\"deployment\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"disallowed_special\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"all\",\"fileTypes\":[],\"password\":false,\"name\":\"disallowed_special\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"embedding_ctx_length\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":8191,\"fileTypes\":[],\"password\":false,\"name\":\"embedding_ctx_length\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"headers\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":true,\"value\":\"{\\\"Authorization\\\": \\\"Bearer \\\"}\",\"fileTypes\":[],\"password\":false,\"name\":\"headers\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"http_client\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"http_client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"max_retries\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":2,\"fileTypes\":[],\"password\":false,\"name\":\"max_retries\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"model\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"text-embedding-ada-002\",\"fileTypes\":[],\"password\":false,\"name\":\"model\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"model_kwargs\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"openai_api_base\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":true,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"openai_api_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"openai_api_type\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":true,\"name\":\"openai_api_type\",\"display_name\":\"OpenAI API Type\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"openai_api_version\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":true,\"name\":\"openai_api_version\",\"display_name\":\"OpenAI API Version\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"openai_organization\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"openai_proxy\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"request_timeout\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"request_timeout\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"retry_max_seconds\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":20,\"fileTypes\":[],\"password\":false,\"name\":\"retry_max_seconds\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"retry_min_seconds\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":4,\"fileTypes\":[],\"password\":false,\"name\":\"retry_min_seconds\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"show_progress_bar\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"show_progress_bar\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"skip_empty\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"skip_empty\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"tiktoken_enabled\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":true,\"fileTypes\":[],\"password\":true,\"name\":\"tiktoken_enabled\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tiktoken_model_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":true,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"OpenAIEmbeddings\"},\"description\":\"OpenAI embedding models.\",\"base_classes\":[\"OpenAIEmbeddings\",\"Embeddings\"],\"display_name\":\"OpenAIEmbeddings\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/openai\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"CohereEmbeddings\":{\"template\":{\"async_client\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"async_client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"client\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"cohere_api_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":true,\"name\":\"cohere_api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"max_retries\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"max_retries\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"model\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"embed-english-v2.0\",\"fileTypes\":[],\"password\":false,\"name\":\"model\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"request_timeout\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"request_timeout\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"truncate\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"truncate\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"user_agent\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"langchain\",\"fileTypes\":[],\"password\":false,\"name\":\"user_agent\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"_type\":\"CohereEmbeddings\"},\"description\":\"Cohere embedding models.\",\"base_classes\":[\"Embeddings\",\"CohereEmbeddings\"],\"display_name\":\"CohereEmbeddings\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/cohere\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"HuggingFaceEmbeddings\":{\"template\":{\"cache_folder\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"cache_folder\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"client\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"encode_kwargs\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"encode_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"model_kwargs\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"model_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"sentence-transformers/all-mpnet-base-v2\",\"fileTypes\":[],\"password\":false,\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"multi_process\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"multi_process\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"_type\":\"HuggingFaceEmbeddings\"},\"description\":\"HuggingFace sentence_transformers embedding models.\",\"base_classes\":[\"Embeddings\",\"HuggingFaceEmbeddings\"],\"display_name\":\"HuggingFaceEmbeddings\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/sentence_transformers\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"VertexAIEmbeddings\":{\"template\":{\"client\":{\"type\":\"ForwardRef(\\\"'_LanguageModel'\\\")\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"client_preview\":{\"type\":\"ForwardRef(\\\"'_LanguageModel'\\\")\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"client_preview\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"credentials\":{\"type\":\"file\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".json\"],\"file_path\":\"\",\"password\":false,\"name\":\"credentials\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"location\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"us-central1\",\"fileTypes\":[],\"password\":false,\"name\":\"location\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"max_output_tokens\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":128,\"fileTypes\":[],\"password\":true,\"name\":\"max_output_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"max_retries\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":6,\"fileTypes\":[],\"password\":false,\"name\":\"max_retries\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"model_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"textembedding-gecko\",\"fileTypes\":[],\"password\":false,\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"n\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1,\"fileTypes\":[],\"password\":false,\"name\":\"n\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"project\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"project\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"request_parallelism\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":5,\"fileTypes\":[],\"password\":false,\"name\":\"request_parallelism\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"stop\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"stop\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"streaming\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"streaming\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.0,\"fileTypes\":[],\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"top_k\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":40,\"fileTypes\":[],\"password\":false,\"name\":\"top_k\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"top_p\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.95,\"fileTypes\":[],\"password\":false,\"name\":\"top_p\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"_type\":\"VertexAIEmbeddings\"},\"description\":\"Google Cloud VertexAI embedding models.\",\"base_classes\":[\"_VertexAIBase\",\"_VertexAICommon\",\"Embeddings\",\"VertexAIEmbeddings\"],\"display_name\":\"VertexAIEmbeddings\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/google_vertex_ai_palm\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"AmazonBedrockEmbeddings\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain.embeddings import BedrockEmbeddings\\nfrom langchain.embeddings.base import Embeddings\\nfrom langflow import CustomComponent\\n\\n\\nclass AmazonBedrockEmeddingsComponent(CustomComponent):\\n \\\"\\\"\\\"\\n A custom component for implementing an Embeddings Model using Amazon Bedrock.\\n \\\"\\\"\\\"\\n\\n display_name: str = \\\"Amazon Bedrock Embeddings\\\"\\n description: str = \\\"Embeddings model from Amazon Bedrock.\\\"\\n documentation = \\\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock\\\"\\n beta = True\\n\\n def build_config(self):\\n return {\\n \\\"model_id\\\": {\\n \\\"display_name\\\": \\\"Model Id\\\",\\n \\\"options\\\": [\\\"amazon.titan-embed-text-v1\\\"],\\n },\\n \\\"credentials_profile_name\\\": {\\\"display_name\\\": \\\"Credentials Profile Name\\\"},\\n \\\"endpoint_url\\\": {\\\"display_name\\\": \\\"Bedrock Endpoint URL\\\"},\\n \\\"region_name\\\": {\\\"display_name\\\": \\\"AWS Region\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n model_id: str = \\\"amazon.titan-embed-text-v1\\\",\\n credentials_profile_name: Optional[str] = None,\\n endpoint_url: Optional[str] = None,\\n region_name: Optional[str] = None,\\n ) -> Embeddings:\\n try:\\n output = BedrockEmbeddings(\\n credentials_profile_name=credentials_profile_name,\\n model_id=model_id,\\n endpoint_url=endpoint_url,\\n region_name=region_name,\\n ) # type: ignore\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to AmazonBedrock API.\\\") from e\\n return output\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"credentials_profile_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"credentials_profile_name\",\"display_name\":\"Credentials Profile Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"endpoint_url\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"endpoint_url\",\"display_name\":\"Bedrock Endpoint URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"model_id\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"amazon.titan-embed-text-v1\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"amazon.titan-embed-text-v1\"],\"name\":\"model_id\",\"display_name\":\"Model Id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"region_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"region_name\",\"display_name\":\"AWS Region\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"CustomComponent\"},\"description\":\"Embeddings model from Amazon Bedrock.\",\"base_classes\":[\"Embeddings\"],\"display_name\":\"Amazon Bedrock Embeddings\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock\",\"custom_fields\":{\"credentials_profile_name\":null,\"endpoint_url\":null,\"model_id\":null,\"region_name\":null},\"output_types\":[\"AmazonBedrockEmbeddings\"],\"field_formatters\":{},\"beta\":true}},\"vectorstores\":{\"FAISS\":{\"template\":{\"documents\":{\"type\":\"Document\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"embedding\":{\"type\":\"Embeddings\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"folder_path\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"folder_path\",\"display_name\":\"Local Path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"ids\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"ids\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"index_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"index_name\",\"display_name\":\"Index Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadatas\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"metadatas\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"search_kwargs\":{\"type\":\"NestedDict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"{}\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"search_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"_type\":\"FAISS\"},\"description\":\"Construct FAISS wrapper from raw documents.\",\"base_classes\":[\"VectorStore\",\"FAISS\",\"BaseRetriever\",\"VectorStoreRetriever\"],\"display_name\":\"FAISS\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/faiss\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"MongoDBAtlasVectorSearch\":{\"template\":{\"collection\":{\"type\":\"Collection[MongoDBDocumentType]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"collection\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"documents\":{\"type\":\"Document\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"embedding\":{\"type\":\"Embeddings\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"collection_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"collection_name\",\"display_name\":\"Collection Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"db_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"db_name\",\"display_name\":\"Database Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"index_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"index_name\",\"display_name\":\"Index Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadatas\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"metadatas\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"mongodb_atlas_cluster_uri\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"mongodb_atlas_cluster_uri\",\"display_name\":\"MongoDB Atlas Cluster URI\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"search_kwargs\":{\"type\":\"NestedDict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"{}\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"search_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"_type\":\"MongoDBAtlasVectorSearch\"},\"description\":\"Construct a `MongoDB Atlas Vector Search` vector store from raw documents.\",\"base_classes\":[\"VectorStore\",\"MongoDBAtlasVectorSearch\",\"BaseRetriever\",\"VectorStoreRetriever\"],\"display_name\":\"MongoDB Atlas\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/mongodb_atlas\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"Pinecone\":{\"template\":{\"documents\":{\"type\":\"Document\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"embedding\":{\"type\":\"Embeddings\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1000,\"fileTypes\":[],\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"batch_size\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":32,\"fileTypes\":[],\"password\":false,\"name\":\"batch_size\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"ids\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"ids\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"index_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"index_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadatas\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"metadatas\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"namespace\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"namespace\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"pinecone_api_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"pinecone_api_key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"pinecone_env\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"pinecone_env\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"pool_threads\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":4,\"fileTypes\":[],\"password\":false,\"name\":\"pool_threads\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"search_kwargs\":{\"type\":\"NestedDict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"{}\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"search_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"text_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"text\",\"fileTypes\":[],\"password\":true,\"name\":\"text_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"upsert_kwargs\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"upsert_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"_type\":\"Pinecone\"},\"description\":\"Construct Pinecone wrapper from raw documents.\",\"base_classes\":[\"VectorStore\",\"Pinecone\",\"BaseRetriever\",\"VectorStoreRetriever\"],\"display_name\":\"Pinecone\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/pinecone\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"Qdrant\":{\"template\":{\"documents\":{\"type\":\"Document\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"embedding\":{\"type\":\"Embeddings\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"hnsw_config\":{\"type\":\"common_types.HnswConfigDiff\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"hnsw_config\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"init_from\":{\"type\":\"common_types.InitFrom\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"init_from\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"optimizers_config\":{\"type\":\"common_types.OptimizersConfigDiff\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"optimizers_config\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"quantization_config\":{\"type\":\"common_types.QuantizationConfig\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"quantization_config\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"wal_config\":{\"type\":\"common_types.WalConfigDiff\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"wal_config\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"api_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":true,\"name\":\"api_key\",\"display_name\":\"API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"batch_size\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":64,\"fileTypes\":[],\"password\":false,\"name\":\"batch_size\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"collection_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"collection_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"content_payload_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"page_content\",\"fileTypes\":[],\"password\":false,\"name\":\"content_payload_key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"distance_func\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"Cosine\",\"fileTypes\":[],\"password\":false,\"name\":\"distance_func\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"force_recreate\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"force_recreate\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"grpc_port\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":6334,\"fileTypes\":[],\"password\":false,\"name\":\"grpc_port\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"host\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"host\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"https\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"https\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"ids\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"ids\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"location\":{\"type\":\"str\",\"required\":false,\"placeholder\":\":memory:\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\":memory:\",\"fileTypes\":[],\"password\":false,\"name\":\"location\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata_payload_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"metadata\",\"fileTypes\":[],\"password\":false,\"name\":\"metadata_payload_key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"metadatas\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"metadatas\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"on_disk\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"on_disk\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"on_disk_payload\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"on_disk_payload\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"path\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"path\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"port\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":6333,\"fileTypes\":[],\"password\":false,\"name\":\"port\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"prefer_grpc\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"prefer_grpc\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"prefix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"fileTypes\":[],\"password\":false,\"name\":\"prefix\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"replication_factor\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"replication_factor\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"search_kwargs\":{\"type\":\"NestedDict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"{}\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"search_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"shard_number\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"shard_number\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"timeout\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"timeout\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1}},\"url\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"url\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"vector_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"vector_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"write_consistency_factor\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"write_consistency_factor\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"Qdrant\"},\"description\":\"Construct Qdrant wrapper from a list of texts.\",\"base_classes\":[\"VectorStore\",\"Qdrant\",\"BaseRetriever\",\"VectorStoreRetriever\"],\"display_name\":\"Qdrant\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/qdrant\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"SupabaseVectorStore\":{\"template\":{\"client\":{\"type\":\"supabase.client.Client\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"documents\":{\"type\":\"Document\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"embedding\":{\"type\":\"Embeddings\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"chunk_size\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":500,\"fileTypes\":[],\"password\":false,\"name\":\"chunk_size\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"ids\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"ids\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadatas\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"metadatas\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"query_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"query_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"search_kwargs\":{\"type\":\"NestedDict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"{}\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"search_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"supabase_service_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"supabase_service_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"supabase_url\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"supabase_url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"table_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"table_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"SupabaseVectorStore\"},\"description\":\"Return VectorStore initialized from texts and embeddings.\",\"base_classes\":[\"VectorStore\",\"SupabaseVectorStore\",\"BaseRetriever\",\"VectorStoreRetriever\"],\"display_name\":\"Supabase\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/supabase\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"Weaviate\":{\"template\":{\"client\":{\"type\":\"weaviate.Client\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"documents\":{\"type\":\"Document\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"embedding\":{\"type\":\"Embeddings\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"relevance_score_fn\":{\"type\":\"Callable[[float], float]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"password\":false,\"name\":\"relevance_score_fn\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"batch_size\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"batch_size\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"by_text\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"by_text\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"client_kwargs\":{\"type\":\"code\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"{}\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"client_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"index_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"index_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadatas\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"metadatas\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"search_kwargs\":{\"type\":\"NestedDict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"{}\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"search_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"text_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"text\",\"fileTypes\":[],\"password\":true,\"name\":\"text_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"weaviate_api_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":true,\"name\":\"weaviate_api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"weaviate_url\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"http://localhost:8080\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"http://localhost:8080\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"weaviate_url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"Weaviate\"},\"description\":\"Construct Weaviate wrapper from raw documents.\",\"base_classes\":[\"VectorStore\",\"Weaviate\",\"BaseRetriever\",\"VectorStoreRetriever\"],\"display_name\":\"Weaviate\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/weaviate\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"Redis\":{\"template\":{\"documents\":{\"type\":\"Document\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"embedding\":{\"type\":\"Embeddings\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\nfrom langflow import CustomComponent\\n\\nfrom langchain.vectorstores.redis import Redis\\nfrom langchain.schema import Document\\nfrom langchain.vectorstores.base import VectorStore\\nfrom langchain.embeddings.base import Embeddings\\n\\n\\nclass RedisComponent(CustomComponent):\\n \\\"\\\"\\\"\\n A custom component for implementing a Vector Store using Redis.\\n \\\"\\\"\\\"\\n\\n display_name: str = \\\"Redis\\\"\\n description: str = \\\"Implementation of Vector Store using Redis\\\"\\n documentation = \\\"https://python.langchain.com/docs/integrations/vectorstores/redis\\\"\\n beta = True\\n\\n def build_config(self):\\n \\\"\\\"\\\"\\n Builds the configuration for the component.\\n\\n Returns:\\n - dict: A dictionary containing the configuration options for the component.\\n \\\"\\\"\\\"\\n return {\\n \\\"index_name\\\": {\\\"display_name\\\": \\\"Index Name\\\", \\\"value\\\": \\\"your_index\\\"},\\n \\\"code\\\": {\\\"show\\\": False, \\\"display_name\\\": \\\"Code\\\"},\\n \\\"documents\\\": {\\\"display_name\\\": \\\"Documents\\\", \\\"is_list\\\": True},\\n \\\"embedding\\\": {\\\"display_name\\\": \\\"Embedding\\\"},\\n \\\"redis_server_url\\\": {\\n \\\"display_name\\\": \\\"Redis Server Connection String\\\",\\n \\\"advanced\\\": False,\\n },\\n \\\"redis_index_name\\\": {\\\"display_name\\\": \\\"Redis Index\\\", \\\"advanced\\\": False},\\n }\\n\\n def build(\\n self,\\n embedding: Embeddings,\\n redis_server_url: str,\\n redis_index_name: str,\\n documents: Optional[Document] = None,\\n ) -> VectorStore:\\n \\\"\\\"\\\"\\n Builds the Vector Store or BaseRetriever object.\\n\\n Args:\\n - embedding (Embeddings): The embeddings to use for the Vector Store.\\n - documents (Optional[Document]): The documents to use for the Vector Store.\\n - redis_index_name (str): The name of the Redis index.\\n - redis_server_url (str): The URL for the Redis server.\\n\\n Returns:\\n - VectorStore: The Vector Store object.\\n \\\"\\\"\\\"\\n\\n return Redis.from_documents(\\n documents=documents, # type: ignore\\n embedding=embedding,\\n redis_url=redis_server_url,\\n index_name=redis_index_name,\\n )\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"redis_index_name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"redis_index_name\",\"display_name\":\"Redis Index\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"redis_server_url\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"redis_server_url\",\"display_name\":\"Redis Server Connection String\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"CustomComponent\"},\"description\":\"Implementation of Vector Store using Redis\",\"base_classes\":[\"VectorStore\"],\"display_name\":\"Redis\",\"documentation\":\"https://python.langchain.com/docs/integrations/vectorstores/redis\",\"custom_fields\":{\"documents\":null,\"embedding\":null,\"redis_index_name\":null,\"redis_server_url\":null},\"output_types\":[\"Redis\"],\"field_formatters\":{},\"beta\":true},\"Chroma\":{\"template\":{\"documents\":{\"type\":\"Document\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"embedding\":{\"type\":\"Embeddings\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"chroma_server_cors_allow_origins\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chroma_server_cors_allow_origins\",\"display_name\":\"Server CORS Allow Origins\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"chroma_server_grpc_port\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chroma_server_grpc_port\",\"display_name\":\"Server gRPC Port\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"chroma_server_host\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chroma_server_host\",\"display_name\":\"Server Host\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"chroma_server_port\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chroma_server_port\",\"display_name\":\"Server Port\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"chroma_server_ssl_enabled\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chroma_server_ssl_enabled\",\"display_name\":\"Server SSL Enabled\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional, Union\\nfrom langflow import CustomComponent\\n\\nfrom langchain.vectorstores import Chroma\\nfrom langchain.schema import Document\\nfrom langchain.vectorstores.base import VectorStore\\nfrom langchain.schema import BaseRetriever\\nfrom langchain.embeddings.base import Embeddings\\nimport chromadb # type: ignore\\n\\n\\nclass ChromaComponent(CustomComponent):\\n \\\"\\\"\\\"\\n A custom component for implementing a Vector Store using Chroma.\\n \\\"\\\"\\\"\\n\\n display_name: str = \\\"Chroma\\\"\\n description: str = \\\"Implementation of Vector Store using Chroma\\\"\\n documentation = \\\"https://python.langchain.com/docs/integrations/vectorstores/chroma\\\"\\n beta: bool = True\\n\\n def build_config(self):\\n \\\"\\\"\\\"\\n Builds the configuration for the component.\\n\\n Returns:\\n - dict: A dictionary containing the configuration options for the component.\\n \\\"\\\"\\\"\\n return {\\n \\\"collection_name\\\": {\\\"display_name\\\": \\\"Collection Name\\\", \\\"value\\\": \\\"langflow\\\"},\\n \\\"persist\\\": {\\\"display_name\\\": \\\"Persist\\\"},\\n \\\"persist_directory\\\": {\\\"display_name\\\": \\\"Persist Directory\\\"},\\n \\\"code\\\": {\\\"show\\\": False, \\\"display_name\\\": \\\"Code\\\"},\\n \\\"documents\\\": {\\\"display_name\\\": \\\"Documents\\\", \\\"is_list\\\": True},\\n \\\"embedding\\\": {\\\"display_name\\\": \\\"Embedding\\\"},\\n \\\"chroma_server_cors_allow_origins\\\": {\\n \\\"display_name\\\": \\\"Server CORS Allow Origins\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"chroma_server_host\\\": {\\\"display_name\\\": \\\"Server Host\\\", \\\"advanced\\\": True},\\n \\\"chroma_server_port\\\": {\\\"display_name\\\": \\\"Server Port\\\", \\\"advanced\\\": True},\\n \\\"chroma_server_grpc_port\\\": {\\n \\\"display_name\\\": \\\"Server gRPC Port\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"chroma_server_ssl_enabled\\\": {\\n \\\"display_name\\\": \\\"Server SSL Enabled\\\",\\n \\\"advanced\\\": True,\\n },\\n }\\n\\n def build(\\n self,\\n collection_name: str,\\n persist: bool,\\n chroma_server_ssl_enabled: bool,\\n persist_directory: Optional[str] = None,\\n embedding: Optional[Embeddings] = None,\\n documents: Optional[Document] = None,\\n chroma_server_cors_allow_origins: Optional[str] = None,\\n chroma_server_host: Optional[str] = None,\\n chroma_server_port: Optional[int] = None,\\n chroma_server_grpc_port: Optional[int] = None,\\n ) -> Union[VectorStore, BaseRetriever]:\\n \\\"\\\"\\\"\\n Builds the Vector Store or BaseRetriever object.\\n\\n Args:\\n - collection_name (str): The name of the collection.\\n - persist_directory (Optional[str]): The directory to persist the Vector Store to.\\n - chroma_server_ssl_enabled (bool): Whether to enable SSL for the Chroma server.\\n - persist (bool): Whether to persist the Vector Store or not.\\n - embedding (Optional[Embeddings]): The embeddings to use for the Vector Store.\\n - documents (Optional[Document]): The documents to use for the Vector Store.\\n - chroma_server_cors_allow_origins (Optional[str]): The CORS allow origins for the Chroma server.\\n - chroma_server_host (Optional[str]): The host for the Chroma server.\\n - chroma_server_port (Optional[int]): The port for the Chroma server.\\n - chroma_server_grpc_port (Optional[int]): The gRPC port for the Chroma server.\\n\\n Returns:\\n - Union[VectorStore, BaseRetriever]: The Vector Store or BaseRetriever object.\\n \\\"\\\"\\\"\\n\\n # Chroma settings\\n chroma_settings = None\\n\\n if chroma_server_host is not None:\\n chroma_settings = chromadb.config.Settings(\\n chroma_server_cors_allow_origins=chroma_server_cors_allow_origins or None,\\n chroma_server_host=chroma_server_host,\\n chroma_server_port=chroma_server_port or None,\\n chroma_server_grpc_port=chroma_server_grpc_port or None,\\n chroma_server_ssl_enabled=chroma_server_ssl_enabled,\\n )\\n\\n # If documents, then we need to create a Chroma instance using .from_documents\\n if documents is not None and embedding is not None:\\n return Chroma.from_documents(\\n documents=documents, # type: ignore\\n persist_directory=persist_directory if persist else None,\\n collection_name=collection_name,\\n embedding=embedding,\\n client_settings=chroma_settings,\\n )\\n\\n return Chroma(persist_directory=persist_directory, client_settings=chroma_settings)\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"collection_name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"langflow\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"collection_name\",\"display_name\":\"Collection Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"persist\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"persist\",\"display_name\":\"Persist\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"persist_directory\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"persist_directory\",\"display_name\":\"Persist Directory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"CustomComponent\"},\"description\":\"Implementation of Vector Store using Chroma\",\"base_classes\":[\"VectorStore\",\"BaseRetriever\"],\"display_name\":\"Chroma\",\"documentation\":\"https://python.langchain.com/docs/integrations/vectorstores/chroma\",\"custom_fields\":{\"chroma_server_cors_allow_origins\":null,\"chroma_server_grpc_port\":null,\"chroma_server_host\":null,\"chroma_server_port\":null,\"chroma_server_ssl_enabled\":null,\"collection_name\":null,\"documents\":null,\"embedding\":null,\"persist\":null,\"persist_directory\":null},\"output_types\":[\"Chroma\"],\"field_formatters\":{},\"beta\":true},\"pgvector\":{\"template\":{\"documents\":{\"type\":\"Document\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"embedding\":{\"type\":\"Embeddings\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional, List\\nfrom langflow import CustomComponent\\n\\nfrom langchain.vectorstores.pgvector import PGVector\\nfrom langchain.schema import Document\\nfrom langchain.vectorstores.base import VectorStore\\nfrom langchain.embeddings.base import Embeddings\\n\\n\\nclass PostgresqlVectorComponent(CustomComponent):\\n \\\"\\\"\\\"\\n A custom component for implementing a Vector Store using PostgreSQL.\\n \\\"\\\"\\\"\\n\\n display_name: str = \\\"PGVector\\\"\\n description: str = \\\"Implementation of Vector Store using PostgreSQL\\\"\\n documentation = \\\"https://python.langchain.com/docs/integrations/vectorstores/pgvector\\\"\\n beta = True\\n\\n def build_config(self):\\n \\\"\\\"\\\"\\n Builds the configuration for the component.\\n\\n Returns:\\n - dict: A dictionary containing the configuration options for the component.\\n \\\"\\\"\\\"\\n return {\\n \\\"index_name\\\": {\\\"display_name\\\": \\\"Index Name\\\", \\\"value\\\": \\\"your_index\\\"},\\n \\\"code\\\": {\\\"show\\\": True, \\\"display_name\\\": \\\"Code\\\"},\\n \\\"documents\\\": {\\\"display_name\\\": \\\"Documents\\\", \\\"is_list\\\": True},\\n \\\"embedding\\\": {\\\"display_name\\\": \\\"Embedding\\\"},\\n \\\"pg_server_url\\\": {\\n \\\"display_name\\\": \\\"PostgreSQL Server Connection String\\\",\\n \\\"advanced\\\": False,\\n },\\n \\\"collection_name\\\": {\\\"display_name\\\": \\\"Table\\\", \\\"advanced\\\": False},\\n }\\n\\n def build(\\n self,\\n embedding: Embeddings,\\n pg_server_url: str,\\n collection_name: str,\\n documents: Optional[List[Document]] = None,\\n ) -> VectorStore:\\n \\\"\\\"\\\"\\n Builds the Vector Store or BaseRetriever object.\\n\\n Args:\\n - embedding (Embeddings): The embeddings to use for the Vector Store.\\n - documents (Optional[Document]): The documents to use for the Vector Store.\\n - collection_name (str): The name of the PG table.\\n - pg_server_url (str): The URL for the PG server.\\n\\n Returns:\\n - VectorStore: The Vector Store object.\\n \\\"\\\"\\\"\\n\\n try:\\n if documents is None:\\n return PGVector.from_existing_index(\\n embedding=embedding,\\n collection_name=collection_name,\\n connection_string=pg_server_url,\\n )\\n\\n return PGVector.from_documents(\\n embedding=embedding,\\n documents=documents,\\n collection_name=collection_name,\\n connection_string=pg_server_url,\\n )\\n except Exception as e:\\n raise RuntimeError(f\\\"Failed to build PGVector: {e}\\\")\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"collection_name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"collection_name\",\"display_name\":\"Table\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"pg_server_url\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"pg_server_url\",\"display_name\":\"PostgreSQL Server Connection String\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"CustomComponent\"},\"description\":\"Implementation of Vector Store using PostgreSQL\",\"base_classes\":[],\"display_name\":\"PGVector\",\"documentation\":\"https://python.langchain.com/docs/integrations/vectorstores/pgvector\",\"custom_fields\":{\"collection_name\":null,\"documents\":null,\"embedding\":null,\"pg_server_url\":null},\"output_types\":[\"pgvector\"],\"field_formatters\":{},\"beta\":true},\"Vectara\":{\"template\":{\"documents\":{\"type\":\"Document\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional, Union\\n\\nfrom langchain.schema import BaseRetriever, Document\\nfrom langchain.vectorstores import Vectara\\nfrom langchain.vectorstores.base import VectorStore\\n\\nfrom langflow import CustomComponent\\n\\n\\nclass VectaraComponent(CustomComponent):\\n display_name: str = \\\"Vectara\\\"\\n description: str = \\\"Implementation of Vector Store using Vectara\\\"\\n documentation = \\\"https://python.langchain.com/docs/integrations/vectorstores/vectara\\\"\\n beta = True\\n # api key should be password = True\\n field_config = {\\n \\\"vectara_customer_id\\\": {\\\"display_name\\\": \\\"Vectara Customer ID\\\"},\\n \\\"vectara_corpus_id\\\": {\\\"display_name\\\": \\\"Vectara Corpus ID\\\"},\\n \\\"vectara_api_key\\\": {\\\"display_name\\\": \\\"Vectara API Key\\\", \\\"password\\\": True},\\n \\\"code\\\": {\\\"show\\\": False},\\n \\\"documents\\\": {\\\"display_name\\\": \\\"Documents\\\"},\\n }\\n\\n def build(\\n self,\\n vectara_customer_id: str,\\n vectara_corpus_id: str,\\n vectara_api_key: str,\\n documents: Optional[Document] = None,\\n ) -> Union[VectorStore, BaseRetriever]:\\n # If documents, then we need to create a Vectara instance using .from_documents\\n if documents is not None:\\n return Vectara.from_documents(\\n documents=documents, # type: ignore\\n vectara_customer_id=vectara_customer_id,\\n vectara_corpus_id=vectara_corpus_id,\\n vectara_api_key=vectara_api_key,\\n source=\\\"langflow\\\",\\n )\\n\\n return Vectara(\\n vectara_customer_id=vectara_customer_id,\\n vectara_corpus_id=vectara_corpus_id,\\n vectara_api_key=vectara_api_key,\\n source=\\\"langflow\\\",\\n )\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"vectara_api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"vectara_api_key\",\"display_name\":\"Vectara API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"vectara_corpus_id\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"vectara_corpus_id\",\"display_name\":\"Vectara Corpus ID\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"vectara_customer_id\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"vectara_customer_id\",\"display_name\":\"Vectara Customer ID\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"CustomComponent\"},\"description\":\"Implementation of Vector Store using Vectara\",\"base_classes\":[\"VectorStore\",\"BaseRetriever\"],\"display_name\":\"Vectara\",\"documentation\":\"https://python.langchain.com/docs/integrations/vectorstores/vectara\",\"custom_fields\":{\"documents\":null,\"vectara_api_key\":null,\"vectara_corpus_id\":null,\"vectara_customer_id\":null},\"output_types\":[\"Vectara\"],\"field_formatters\":{},\"beta\":true}},\"documentloaders\":{\"AZLyricsLoader\":{\"template\":{\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"web_path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"web_path\",\"display_name\":\"Web Page\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"AZLyricsLoader\"},\"description\":\"Load `AZLyrics` webpages.\",\"base_classes\":[\"Document\"],\"display_name\":\"AZLyricsLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/azlyrics\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"AirbyteJSONLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".json\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"AirbyteJSONLoader\"},\"description\":\"Load local `Airbyte` json files.\",\"base_classes\":[\"Document\"],\"display_name\":\"AirbyteJSONLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/airbyte_json\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"BSHTMLLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".html\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"BSHTMLLoader\"},\"description\":\"Load `HTML` files and parse them with `beautiful soup`.\",\"base_classes\":[\"Document\"],\"display_name\":\"BSHTMLLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/how_to/html\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"CSVLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".csv\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"CSVLoader\"},\"description\":\"Load a `CSV` file into a list of Documents.\",\"base_classes\":[\"Document\"],\"display_name\":\"CSVLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/csv\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"CoNLLULoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".csv\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"CoNLLULoader\"},\"description\":\"Load `CoNLL-U` files.\",\"base_classes\":[\"Document\"],\"display_name\":\"CoNLLULoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/conll-u\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"CollegeConfidentialLoader\":{\"template\":{\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"web_path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"web_path\",\"display_name\":\"Web Page\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"CollegeConfidentialLoader\"},\"description\":\"Load `College Confidential` webpages.\",\"base_classes\":[\"Document\"],\"display_name\":\"CollegeConfidentialLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/college_confidential\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"DirectoryLoader\":{\"template\":{\"glob\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"**/*.txt\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"glob\",\"display_name\":\"glob\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"load_hidden\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"False\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"load_hidden\",\"display_name\":\"Load hidden files\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"max_concurrency\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":10,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_concurrency\",\"display_name\":\"Max concurrency\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"path\",\"display_name\":\"Local directory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"recursive\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"True\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"recursive\",\"display_name\":\"Recursive\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"silent_errors\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"False\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"silent_errors\",\"display_name\":\"Silent errors\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"use_multithreading\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"True\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"use_multithreading\",\"display_name\":\"Use multithreading\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"_type\":\"DirectoryLoader\"},\"description\":\"Load from a directory.\",\"base_classes\":[\"Document\"],\"display_name\":\"DirectoryLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/how_to/file_directory\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"EverNoteLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".xml\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"EverNoteLoader\"},\"description\":\"Load from `EverNote`.\",\"base_classes\":[\"Document\"],\"display_name\":\"EverNoteLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/evernote\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"FacebookChatLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".json\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"FacebookChatLoader\"},\"description\":\"Load `Facebook Chat` messages directory dump.\",\"base_classes\":[\"Document\"],\"display_name\":\"FacebookChatLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/facebook_chat\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"GitLoader\":{\"template\":{\"branch\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"branch\",\"display_name\":\"Branch\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"clone_url\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"clone_url\",\"display_name\":\"Clone URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"file_filter\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"file_filter\",\"display_name\":\"File extensions (comma-separated)\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"repo_path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"repo_path\",\"display_name\":\"Path to repository\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"GitLoader\"},\"description\":\"Load `Git` repository files.\",\"base_classes\":[\"Document\"],\"display_name\":\"GitLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/git\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"GitbookLoader\":{\"template\":{\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"web_page\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"web_page\",\"display_name\":\"Web Page\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"GitbookLoader\"},\"description\":\"Load `GitBook` data.\",\"base_classes\":[\"Document\"],\"display_name\":\"GitbookLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/gitbook\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"GutenbergLoader\":{\"template\":{\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"web_path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"web_path\",\"display_name\":\"Web Page\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"GutenbergLoader\"},\"description\":\"Load from `Gutenberg.org`.\",\"base_classes\":[\"Document\"],\"display_name\":\"GutenbergLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/gutenberg\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"HNLoader\":{\"template\":{\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"web_path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"web_path\",\"display_name\":\"Web Page\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"HNLoader\"},\"description\":\"Load `Hacker News` data.\",\"base_classes\":[\"Document\"],\"display_name\":\"HNLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/hacker_news\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"IFixitLoader\":{\"template\":{\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"web_path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"web_path\",\"display_name\":\"Web Page\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"IFixitLoader\"},\"description\":\"Load `iFixit` repair guides, device wikis and answers.\",\"base_classes\":[\"Document\"],\"display_name\":\"IFixitLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/ifixit\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"IMSDbLoader\":{\"template\":{\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"web_path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"web_path\",\"display_name\":\"Web Page\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"IMSDbLoader\"},\"description\":\"Load `IMSDb` webpages.\",\"base_classes\":[\"Document\"],\"display_name\":\"IMSDbLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/imsdb\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"NotionDirectoryLoader\":{\"template\":{\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"path\",\"display_name\":\"Local directory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"NotionDirectoryLoader\"},\"description\":\"Load `Notion directory` dump.\",\"base_classes\":[\"Document\"],\"display_name\":\"NotionDirectoryLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/notion\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"PyPDFLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".pdf\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"PyPDFLoader\"},\"description\":\"Load PDF using pypdf into list of documents.\",\"base_classes\":[\"Document\"],\"display_name\":\"PyPDFLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/how_to/pdf\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"PyPDFDirectoryLoader\":{\"template\":{\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"path\",\"display_name\":\"Local directory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"PyPDFDirectoryLoader\"},\"description\":\"Load a directory with `PDF` files using `pypdf` and chunks at character level.\",\"base_classes\":[\"Document\"],\"display_name\":\"PyPDFDirectoryLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/how_to/pdf\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"ReadTheDocsLoader\":{\"template\":{\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"path\",\"display_name\":\"Local directory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"ReadTheDocsLoader\"},\"description\":\"Load `ReadTheDocs` documentation directory.\",\"base_classes\":[\"Document\"],\"display_name\":\"ReadTheDocsLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/readthedocs_documentation\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"SRTLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".srt\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"SRTLoader\"},\"description\":\"Load `.srt` (subtitle) files.\",\"base_classes\":[\"Document\"],\"display_name\":\"SRTLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/subtitle\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"SlackDirectoryLoader\":{\"template\":{\"zip_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".zip\"],\"file_path\":\"\",\"password\":false,\"name\":\"zip_path\",\"display_name\":\"Path to zip file\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"workspace_url\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"workspace_url\",\"display_name\":\"Workspace URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"SlackDirectoryLoader\"},\"description\":\"Load from a `Slack` directory dump.\",\"base_classes\":[\"Document\"],\"display_name\":\"SlackDirectoryLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/slack\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"TextLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".txt\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"TextLoader\"},\"description\":\"Load text file.\",\"base_classes\":[\"Document\"],\"display_name\":\"TextLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"UnstructuredEmailLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".eml\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"UnstructuredEmailLoader\"},\"description\":\"Load email files using `Unstructured`.\",\"base_classes\":[\"Document\"],\"display_name\":\"UnstructuredEmailLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/email\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"UnstructuredHTMLLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".html\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"UnstructuredHTMLLoader\"},\"description\":\"Load `HTML` files using `Unstructured`.\",\"base_classes\":[\"Document\"],\"display_name\":\"UnstructuredHTMLLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/how_to/html\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"UnstructuredMarkdownLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".md\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"UnstructuredMarkdownLoader\"},\"description\":\"Load `Markdown` files using `Unstructured`.\",\"base_classes\":[\"Document\"],\"display_name\":\"UnstructuredMarkdownLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/how_to/markdown\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"UnstructuredPowerPointLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".pptx\",\".ppt\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"UnstructuredPowerPointLoader\"},\"description\":\"Load `Microsoft PowerPoint` files using `Unstructured`.\",\"base_classes\":[\"Document\"],\"display_name\":\"UnstructuredPowerPointLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/microsoft_powerpoint\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"UnstructuredWordDocumentLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".docx\",\".doc\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"UnstructuredWordDocumentLoader\"},\"description\":\"Load `Microsoft Word` file using `Unstructured`.\",\"base_classes\":[\"Document\"],\"display_name\":\"UnstructuredWordDocumentLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/microsoft_word\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"WebBaseLoader\":{\"template\":{\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"web_path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"web_path\",\"display_name\":\"Web Page\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"WebBaseLoader\"},\"description\":\"Load HTML pages using `urllib` and parse them with `BeautifulSoup'.\",\"base_classes\":[\"Document\"],\"display_name\":\"WebBaseLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/web_base\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"FileLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[\"json\",\"txt\",\"csv\",\"jsonl\",\"html\",\"htm\",\"conllu\",\"enex\",\"msg\",\"pdf\",\"srt\",\"eml\",\"md\",\"pptx\",\"docx\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"display_name\":\"File Path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langchain.schema import Document\\n\\nfrom langflow import CustomComponent\\nfrom langflow.utils.constants import LOADERS_INFO\\n\\n\\nclass FileLoaderComponent(CustomComponent):\\n display_name: str = \\\"File Loader\\\"\\n description: str = \\\"Generic File Loader\\\"\\n beta = True\\n\\n def build_config(self):\\n loader_options = [\\\"Automatic\\\"] + [loader_info[\\\"name\\\"] for loader_info in LOADERS_INFO]\\n\\n file_types = []\\n suffixes = []\\n\\n for loader_info in LOADERS_INFO:\\n if \\\"allowedTypes\\\" in loader_info:\\n file_types.extend(loader_info[\\\"allowedTypes\\\"])\\n suffixes.extend([f\\\".{ext}\\\" for ext in loader_info[\\\"allowedTypes\\\"]])\\n\\n return {\\n \\\"file_path\\\": {\\n \\\"display_name\\\": \\\"File Path\\\",\\n \\\"required\\\": True,\\n \\\"field_type\\\": \\\"file\\\",\\n \\\"file_types\\\": [\\n \\\"json\\\",\\n \\\"txt\\\",\\n \\\"csv\\\",\\n \\\"jsonl\\\",\\n \\\"html\\\",\\n \\\"htm\\\",\\n \\\"conllu\\\",\\n \\\"enex\\\",\\n \\\"msg\\\",\\n \\\"pdf\\\",\\n \\\"srt\\\",\\n \\\"eml\\\",\\n \\\"md\\\",\\n \\\"pptx\\\",\\n \\\"docx\\\",\\n ],\\n \\\"suffixes\\\": [\\n \\\".json\\\",\\n \\\".txt\\\",\\n \\\".csv\\\",\\n \\\".jsonl\\\",\\n \\\".html\\\",\\n \\\".htm\\\",\\n \\\".conllu\\\",\\n \\\".enex\\\",\\n \\\".msg\\\",\\n \\\".pdf\\\",\\n \\\".srt\\\",\\n \\\".eml\\\",\\n \\\".md\\\",\\n \\\".pptx\\\",\\n \\\".docx\\\",\\n ],\\n # \\\"file_types\\\" : file_types,\\n # \\\"suffixes\\\": suffixes,\\n },\\n \\\"loader\\\": {\\n \\\"display_name\\\": \\\"Loader\\\",\\n \\\"is_list\\\": True,\\n \\\"required\\\": True,\\n \\\"options\\\": loader_options,\\n \\\"value\\\": \\\"Automatic\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(self, file_path: str, loader: str) -> Document:\\n file_type = file_path.split(\\\".\\\")[-1]\\n\\n # Mapeie o nome do loader selecionado para suas informações\\n selected_loader_info = None\\n for loader_info in LOADERS_INFO:\\n if loader_info[\\\"name\\\"] == loader:\\n selected_loader_info = loader_info\\n break\\n\\n if selected_loader_info is None and loader != \\\"Automatic\\\":\\n raise ValueError(f\\\"Loader {loader} not found in the loader info list\\\")\\n\\n if loader == \\\"Automatic\\\":\\n # Determine o loader automaticamente com base na extensão do arquivo\\n default_loader_info = None\\n for info in LOADERS_INFO:\\n if \\\"defaultFor\\\" in info and file_type in info[\\\"defaultFor\\\"]:\\n default_loader_info = info\\n break\\n\\n if default_loader_info is None:\\n raise ValueError(f\\\"No default loader found for file type: {file_type}\\\")\\n\\n selected_loader_info = default_loader_info\\n if isinstance(selected_loader_info, dict):\\n loader_import: str = selected_loader_info[\\\"import\\\"]\\n else:\\n raise ValueError(f\\\"Loader info for {loader} is not a dict\\\\nLoader info:\\\\n{selected_loader_info}\\\")\\n module_name, class_name = loader_import.rsplit(\\\".\\\", 1)\\n\\n try:\\n # Importe o loader dinamicamente\\n loader_module = __import__(module_name, fromlist=[class_name])\\n loader_instance = getattr(loader_module, class_name)\\n except ImportError as e:\\n raise ValueError(f\\\"Loader {loader} could not be imported\\\\nLoader info:\\\\n{selected_loader_info}\\\") from e\\n\\n result = loader_instance(file_path=file_path)\\n return result.load()\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"loader\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"Automatic\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"Automatic\",\"Airbyte JSON (.jsonl)\",\"JSON (.json)\",\"BeautifulSoup4 HTML (.html, .htm)\",\"CSV (.csv)\",\"CoNLL-U (.conllu)\",\"EverNote (.enex)\",\"Facebook Chat (.json)\",\"Outlook Message (.msg)\",\"PyPDF (.pdf)\",\"Subtitle (.str)\",\"Text (.txt)\",\"Unstructured Email (.eml)\",\"Unstructured HTML (.html, .htm)\",\"Unstructured Markdown (.md)\",\"Unstructured PowerPoint (.pptx)\",\"Unstructured Word (.docx)\"],\"name\":\"loader\",\"display_name\":\"Loader\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"CustomComponent\"},\"description\":\"Generic File Loader\",\"base_classes\":[\"Document\"],\"display_name\":\"File Loader\",\"documentation\":\"\",\"custom_fields\":{\"file_path\":null,\"loader\":null},\"output_types\":[\"FileLoader\"],\"field_formatters\":{},\"beta\":true},\"UrlLoader\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import List\\n\\nfrom langchain import document_loaders\\nfrom langchain.schema import Document\\nfrom langflow import CustomComponent\\n\\n\\nclass UrlLoaderComponent(CustomComponent):\\n display_name: str = \\\"Url Loader\\\"\\n description: str = \\\"Generic Url Loader Component\\\"\\n\\n def build_config(self):\\n return {\\n \\\"web_path\\\": {\\n \\\"display_name\\\": \\\"Url\\\",\\n \\\"required\\\": True,\\n },\\n \\\"loader\\\": {\\n \\\"display_name\\\": \\\"Loader\\\",\\n \\\"is_list\\\": True,\\n \\\"required\\\": True,\\n \\\"options\\\": [\\n \\\"AZLyricsLoader\\\",\\n \\\"CollegeConfidentialLoader\\\",\\n \\\"GitbookLoader\\\",\\n \\\"HNLoader\\\",\\n \\\"IFixitLoader\\\",\\n \\\"IMSDbLoader\\\",\\n \\\"WebBaseLoader\\\",\\n ],\\n \\\"value\\\": \\\"WebBaseLoader\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(self, web_path: str, loader: str) -> List[Document]:\\n try:\\n loader_instance = getattr(document_loaders, loader)(web_path=web_path)\\n except Exception as e:\\n raise ValueError(f\\\"No loader found for: {web_path}\\\") from e\\n docs = loader_instance.load()\\n avg_length = sum(len(doc.page_content) for doc in docs if hasattr(doc, \\\"page_content\\\")) / len(docs)\\n self.status = f\\\"\\\"\\\"{len(docs)} documents)\\n \\\\nAvg. Document Length (characters): {int(avg_length)}\\n Documents: {docs[:3]}...\\\"\\\"\\\"\\n return docs\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"loader\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"WebBaseLoader\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"AZLyricsLoader\",\"CollegeConfidentialLoader\",\"GitbookLoader\",\"HNLoader\",\"IFixitLoader\",\"IMSDbLoader\",\"WebBaseLoader\"],\"name\":\"loader\",\"display_name\":\"Loader\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"web_path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"web_path\",\"display_name\":\"Url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"CustomComponent\"},\"description\":\"Generic Url Loader Component\",\"base_classes\":[\"Document\"],\"display_name\":\"Url Loader\",\"documentation\":\"\",\"custom_fields\":{\"loader\":null,\"web_path\":null},\"output_types\":[\"UrlLoader\"],\"field_formatters\":{},\"beta\":true}},\"textsplitters\":{\"CharacterTextSplitter\":{\"template\":{\"documents\":{\"type\":\"Document\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"chunk_overlap\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":200,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chunk_overlap\",\"display_name\":\"Chunk Overlap\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"chunk_size\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1000,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chunk_size\",\"display_name\":\"Chunk Size\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"separator\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\\\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"separator\",\"display_name\":\"Separator\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"CharacterTextSplitter\"},\"description\":\"Splitting text that looks at characters.\",\"base_classes\":[\"Document\"],\"display_name\":\"CharacterTextSplitter\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_transformers/text_splitters/character_text_splitter\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"beta\":false},\"LanguageRecursiveTextSplitter\":{\"template\":{\"documents\":{\"type\":\"Document\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"The documents to split.\"},\"chunk_overlap\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":200,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chunk_overlap\",\"display_name\":\"Chunk Overlap\",\"advanced\":false,\"dynamic\":false,\"info\":\"The amount of overlap between chunks.\"},\"chunk_size\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":1000,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chunk_size\",\"display_name\":\"Chunk Size\",\"advanced\":false,\"dynamic\":false,\"info\":\"The maximum length of each chunk.\"},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\nfrom langflow import CustomComponent\\nfrom langchain.text_splitter import Language\\nfrom langchain.schema import Document\\n\\n\\nclass LanguageRecursiveTextSplitterComponent(CustomComponent):\\n display_name: str = \\\"Language Recursive Text Splitter\\\"\\n description: str = \\\"Split text into chunks of a specified length based on language.\\\"\\n documentation: str = \\\"https://docs.langflow.org/components/text-splitters#languagerecursivetextsplitter\\\"\\n\\n def build_config(self):\\n options = [x.value for x in Language]\\n return {\\n \\\"documents\\\": {\\n \\\"display_name\\\": \\\"Documents\\\",\\n \\\"info\\\": \\\"The documents to split.\\\",\\n },\\n \\\"separator_type\\\": {\\n \\\"display_name\\\": \\\"Separator Type\\\",\\n \\\"info\\\": \\\"The type of separator to use.\\\",\\n \\\"field_type\\\": \\\"str\\\",\\n \\\"options\\\": options,\\n \\\"value\\\": \\\"Python\\\",\\n },\\n \\\"separators\\\": {\\n \\\"display_name\\\": \\\"Separators\\\",\\n \\\"info\\\": \\\"The characters to split on.\\\",\\n \\\"is_list\\\": True,\\n },\\n \\\"chunk_size\\\": {\\n \\\"display_name\\\": \\\"Chunk Size\\\",\\n \\\"info\\\": \\\"The maximum length of each chunk.\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"value\\\": 1000,\\n },\\n \\\"chunk_overlap\\\": {\\n \\\"display_name\\\": \\\"Chunk Overlap\\\",\\n \\\"info\\\": \\\"The amount of overlap between chunks.\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"value\\\": 200,\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n documents: list[Document],\\n chunk_size: Optional[int] = 1000,\\n chunk_overlap: Optional[int] = 200,\\n separator_type: Optional[str] = \\\"Python\\\",\\n ) -> list[Document]:\\n \\\"\\\"\\\"\\n Split text into chunks of a specified length.\\n\\n Args:\\n separators (list[str]): The characters to split on.\\n chunk_size (int): The maximum length of each chunk.\\n chunk_overlap (int): The amount of overlap between chunks.\\n length_function (function): The function to use to calculate the length of the text.\\n\\n Returns:\\n list[str]: The chunks of text.\\n \\\"\\\"\\\"\\n from langchain.text_splitter import RecursiveCharacterTextSplitter\\n\\n # Make sure chunk_size and chunk_overlap are ints\\n if isinstance(chunk_size, str):\\n chunk_size = int(chunk_size)\\n if isinstance(chunk_overlap, str):\\n chunk_overlap = int(chunk_overlap)\\n\\n splitter = RecursiveCharacterTextSplitter.from_language(\\n language=Language(separator_type),\\n chunk_size=chunk_size,\\n chunk_overlap=chunk_overlap,\\n )\\n\\n docs = splitter.split_documents(documents)\\n return docs\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"separator_type\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"value\":\"Python\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"cpp\",\"go\",\"java\",\"kotlin\",\"js\",\"ts\",\"php\",\"proto\",\"python\",\"rst\",\"ruby\",\"rust\",\"scala\",\"swift\",\"markdown\",\"latex\",\"html\",\"sol\",\"csharp\",\"cobol\"],\"name\":\"separator_type\",\"display_name\":\"Separator Type\",\"advanced\":false,\"dynamic\":false,\"info\":\"The type of separator to use.\"},\"_type\":\"CustomComponent\"},\"description\":\"Split text into chunks of a specified length based on language.\",\"base_classes\":[\"Document\"],\"display_name\":\"Language Recursive Text Splitter\",\"documentation\":\"https://docs.langflow.org/components/text-splitters#languagerecursivetextsplitter\",\"custom_fields\":{\"chunk_overlap\":null,\"chunk_size\":null,\"documents\":null,\"separator_type\":null},\"output_types\":[\"LanguageRecursiveTextSplitter\"],\"field_formatters\":{},\"beta\":true},\"RecursiveCharacterTextSplitter\":{\"template\":{\"documents\":{\"type\":\"Document\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"The documents to split.\"},\"chunk_overlap\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":200,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chunk_overlap\",\"display_name\":\"Chunk Overlap\",\"advanced\":false,\"dynamic\":false,\"info\":\"The amount of overlap between chunks.\"},\"chunk_size\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":1000,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chunk_size\",\"display_name\":\"Chunk Size\",\"advanced\":false,\"dynamic\":false,\"info\":\"The maximum length of each chunk.\"},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\nfrom langflow import CustomComponent\\nfrom langchain.schema import Document\\nfrom langflow.utils.util import build_loader_repr_from_documents\\n\\n\\nclass RecursiveCharacterTextSplitterComponent(CustomComponent):\\n display_name: str = \\\"Recursive Character Text Splitter\\\"\\n description: str = \\\"Split text into chunks of a specified length.\\\"\\n documentation: str = \\\"https://docs.langflow.org/components/text-splitters#recursivecharactertextsplitter\\\"\\n\\n def build_config(self):\\n return {\\n \\\"documents\\\": {\\n \\\"display_name\\\": \\\"Documents\\\",\\n \\\"info\\\": \\\"The documents to split.\\\",\\n },\\n \\\"separators\\\": {\\n \\\"display_name\\\": \\\"Separators\\\",\\n \\\"info\\\": 'The characters to split on.\\\\nIf left empty defaults to [\\\"\\\\\\\\n\\\\\\\\n\\\", \\\"\\\\\\\\n\\\", \\\" \\\", \\\"\\\"].',\\n \\\"is_list\\\": True,\\n },\\n \\\"chunk_size\\\": {\\n \\\"display_name\\\": \\\"Chunk Size\\\",\\n \\\"info\\\": \\\"The maximum length of each chunk.\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"value\\\": 1000,\\n },\\n \\\"chunk_overlap\\\": {\\n \\\"display_name\\\": \\\"Chunk Overlap\\\",\\n \\\"info\\\": \\\"The amount of overlap between chunks.\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"value\\\": 200,\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n documents: list[Document],\\n separators: Optional[list[str]] = None,\\n chunk_size: Optional[int] = 1000,\\n chunk_overlap: Optional[int] = 200,\\n ) -> list[Document]:\\n \\\"\\\"\\\"\\n Split text into chunks of a specified length.\\n\\n Args:\\n separators (list[str]): The characters to split on.\\n chunk_size (int): The maximum length of each chunk.\\n chunk_overlap (int): The amount of overlap between chunks.\\n length_function (function): The function to use to calculate the length of the text.\\n\\n Returns:\\n list[str]: The chunks of text.\\n \\\"\\\"\\\"\\n from langchain.text_splitter import RecursiveCharacterTextSplitter\\n\\n if separators == \\\"\\\":\\n separators = None\\n elif separators:\\n # check if the separators list has escaped characters\\n # if there are escaped characters, unescape them\\n separators = [x.encode().decode(\\\"unicode-escape\\\") for x in separators]\\n\\n # Make sure chunk_size and chunk_overlap are ints\\n if isinstance(chunk_size, str):\\n chunk_size = int(chunk_size)\\n if isinstance(chunk_overlap, str):\\n chunk_overlap = int(chunk_overlap)\\n splitter = RecursiveCharacterTextSplitter(\\n separators=separators,\\n chunk_size=chunk_size,\\n chunk_overlap=chunk_overlap,\\n )\\n\\n docs = splitter.split_documents(documents)\\n self.repr_value = build_loader_repr_from_documents(docs)\\n return docs\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"separators\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"separators\",\"display_name\":\"Separators\",\"advanced\":false,\"dynamic\":false,\"info\":\"The characters to split on.\\nIf left empty defaults to [\\\"\\\\n\\\\n\\\", \\\"\\\\n\\\", \\\" \\\", \\\"\\\"].\"},\"_type\":\"CustomComponent\"},\"description\":\"Split text into chunks of a specified length.\",\"base_classes\":[\"Document\"],\"display_name\":\"Recursive Character Text Splitter\",\"documentation\":\"https://docs.langflow.org/components/text-splitters#recursivecharactertextsplitter\",\"custom_fields\":{\"chunk_overlap\":null,\"chunk_size\":null,\"documents\":null,\"separators\":null},\"output_types\":[\"RecursiveCharacterTextSplitter\"],\"field_formatters\":{},\"beta\":true}},\"utilities\":{\"BingSearchAPIWrapper\":{\"template\":{\"bing_search_url\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"bing_search_url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"bing_subscription_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":true,\"name\":\"bing_subscription_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"k\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":10,\"fileTypes\":[],\"password\":false,\"name\":\"k\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"search_kwargs\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"search_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\"},\"_type\":\"BingSearchAPIWrapper\"},\"description\":\"Wrapper for Bing Search API.\",\"base_classes\":[\"BingSearchAPIWrapper\"],\"display_name\":\"BingSearchAPIWrapper\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"GoogleSearchAPIWrapper\":{\"template\":{\"google_api_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":true,\"name\":\"google_api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"google_cse_id\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"google_cse_id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"k\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":10,\"fileTypes\":[],\"password\":false,\"name\":\"k\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"search_engine\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"search_engine\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"siterestrict\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"siterestrict\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"GoogleSearchAPIWrapper\"},\"description\":\"Wrapper for Google Search API.\",\"base_classes\":[\"GoogleSearchAPIWrapper\"],\"display_name\":\"GoogleSearchAPIWrapper\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"GoogleSerperAPIWrapper\":{\"template\":{\"aiosession\":{\"type\":\"ClientSession\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"aiosession\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"gl\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"us\",\"fileTypes\":[],\"password\":false,\"name\":\"gl\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"hl\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"en\",\"fileTypes\":[],\"password\":false,\"name\":\"hl\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"k\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":10,\"fileTypes\":[],\"password\":false,\"name\":\"k\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"result_key_for_type\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"{\\n \\\"news\\\": \\\"news\\\",\\n \\\"places\\\": \\\"places\\\",\\n \\\"images\\\": \\\"images\\\",\\n \\\"search\\\": \\\"organic\\\"\\n}\",\"fileTypes\":[],\"password\":true,\"name\":\"result_key_for_type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"serper_api_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":true,\"name\":\"serper_api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"tbs\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"tbs\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"type\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"search\",\"fileTypes\":[],\"password\":false,\"name\":\"type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"GoogleSerperAPIWrapper\"},\"description\":\"Wrapper around the Serper.dev Google Search API.\",\"base_classes\":[\"GoogleSerperAPIWrapper\"],\"display_name\":\"GoogleSerperAPIWrapper\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"SearxSearchWrapper\":{\"template\":{\"aiosession\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"aiosession\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"categories\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"value\":[],\"fileTypes\":[],\"password\":false,\"name\":\"categories\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"engines\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"value\":[],\"fileTypes\":[],\"password\":false,\"name\":\"engines\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"headers\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"{\\\"Authorization\\\": \\\"Bearer \\\"}\",\"fileTypes\":[],\"password\":false,\"name\":\"headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"k\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":10,\"fileTypes\":[],\"password\":false,\"name\":\"k\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"params\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"params\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"query_suffix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"password\":false,\"name\":\"query_suffix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"searx_host\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"password\":false,\"name\":\"searx_host\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"unsecure\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"unsecure\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"SearxSearchWrapper\"},\"description\":\"Wrapper for Searx API.\",\"base_classes\":[\"SearxSearchWrapper\"],\"display_name\":\"SearxSearchWrapper\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"SerpAPIWrapper\":{\"template\":{\"aiosession\":{\"type\":\"ClientSession\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"aiosession\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"params\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"{\\n \\\"engine\\\": \\\"google\\\",\\n \\\"google_domain\\\": \\\"google.com\\\",\\n \\\"gl\\\": \\\"us\\\",\\n \\\"hl\\\": \\\"en\\\"\\n}\",\"fileTypes\":[],\"password\":false,\"name\":\"params\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"search_engine\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"search_engine\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"serpapi_api_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":true,\"name\":\"serpapi_api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"SerpAPIWrapper\"},\"description\":\"Wrapper around SerpAPI.\",\"base_classes\":[\"SerpAPIWrapper\"],\"display_name\":\"SerpAPIWrapper\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"WikipediaAPIWrapper\":{\"template\":{\"doc_content_chars_max\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":4000,\"fileTypes\":[],\"password\":false,\"name\":\"doc_content_chars_max\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"lang\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"en\",\"fileTypes\":[],\"password\":false,\"name\":\"lang\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"load_all_available_meta\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"load_all_available_meta\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"top_k_results\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":3,\"fileTypes\":[],\"password\":false,\"name\":\"top_k_results\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"wiki_client\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"wiki_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"WikipediaAPIWrapper\"},\"description\":\"Wrapper around WikipediaAPI.\",\"base_classes\":[\"WikipediaAPIWrapper\"],\"display_name\":\"WikipediaAPIWrapper\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"WolframAlphaAPIWrapper\":{\"template\":{\"wolfram_alpha_appid\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"wolfram_alpha_appid\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"wolfram_client\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"wolfram_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"WolframAlphaAPIWrapper\"},\"description\":\"Wrapper for Wolfram Alpha.\",\"base_classes\":[\"WolframAlphaAPIWrapper\"],\"display_name\":\"WolframAlphaAPIWrapper\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"GetRequest\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langchain.schema import Document\\nfrom langflow.services.database.models.base import orjson_dumps\\nimport requests\\nfrom typing import Optional\\n\\n\\nclass GetRequest(CustomComponent):\\n display_name: str = \\\"GET Request\\\"\\n description: str = \\\"Make a GET request to the given URL.\\\"\\n output_types: list[str] = [\\\"Document\\\"]\\n documentation: str = \\\"https://docs.langflow.org/components/utilities#get-request\\\"\\n beta: bool = True\\n field_config = {\\n \\\"url\\\": {\\n \\\"display_name\\\": \\\"URL\\\",\\n \\\"info\\\": \\\"The URL to make the request to\\\",\\n \\\"is_list\\\": True,\\n },\\n \\\"headers\\\": {\\n \\\"display_name\\\": \\\"Headers\\\",\\n \\\"info\\\": \\\"The headers to send with the request.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n \\\"timeout\\\": {\\n \\\"display_name\\\": \\\"Timeout\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"info\\\": \\\"The timeout to use for the request.\\\",\\n \\\"value\\\": 5,\\n },\\n }\\n\\n def get_document(self, session: requests.Session, url: str, headers: Optional[dict], timeout: int) -> Document:\\n try:\\n response = session.get(url, headers=headers, timeout=int(timeout))\\n try:\\n response_json = response.json()\\n result = orjson_dumps(response_json, indent_2=False)\\n except Exception:\\n result = response.text\\n self.repr_value = result\\n return Document(\\n page_content=result,\\n metadata={\\n \\\"source\\\": url,\\n \\\"headers\\\": headers,\\n \\\"status_code\\\": response.status_code,\\n },\\n )\\n except requests.Timeout:\\n return Document(\\n page_content=\\\"Request Timed Out\\\",\\n metadata={\\\"source\\\": url, \\\"headers\\\": headers, \\\"status_code\\\": 408},\\n )\\n except Exception as exc:\\n return Document(\\n page_content=str(exc),\\n metadata={\\\"source\\\": url, \\\"headers\\\": headers, \\\"status_code\\\": 500},\\n )\\n\\n def build(\\n self,\\n url: str,\\n headers: Optional[dict] = None,\\n timeout: int = 5,\\n ) -> list[Document]:\\n if headers is None:\\n headers = {}\\n urls = url if isinstance(url, list) else [url]\\n with requests.Session() as session:\\n documents = [self.get_document(session, u, headers, timeout) for u in urls]\\n self.repr_value = documents\\n return documents\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"headers\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"{\\\"Authorization\\\": \\\"Bearer \\\"}\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"headers\",\"display_name\":\"Headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"The headers to send with the request.\"},\"timeout\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":5,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"timeout\",\"display_name\":\"Timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"The timeout to use for the request.\"},\"url\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"url\",\"display_name\":\"URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"The URL to make the request to\"},\"_type\":\"CustomComponent\"},\"description\":\"Make a GET request to the given URL.\",\"base_classes\":[\"Document\"],\"display_name\":\"GET Request\",\"documentation\":\"https://docs.langflow.org/components/utilities#get-request\",\"custom_fields\":{\"headers\":null,\"timeout\":null,\"url\":null},\"output_types\":[\"GetRequest\"],\"field_formatters\":{},\"beta\":true},\"JSONDocumentBuilder\":{\"template\":{\"document\":{\"type\":\"Document\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"document\",\"display_name\":\"Document\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"### JSON Document Builder\\n\\n# Build a Document containing a JSON object using a key and another Document page content.\\n\\n# **Params**\\n\\n# - **Key:** The key to use for the JSON object.\\n# - **Document:** The Document page to use for the JSON object.\\n\\n# **Output**\\n\\n# - **Document:** The Document containing the JSON object.\\n\\nfrom langchain.schema import Document\\nfrom langflow import CustomComponent\\nfrom langflow.services.database.models.base import orjson_dumps\\n\\n\\nclass JSONDocumentBuilder(CustomComponent):\\n display_name: str = \\\"JSON Document Builder\\\"\\n description: str = \\\"Build a Document containing a JSON object using a key and another Document page content.\\\"\\n output_types: list[str] = [\\\"Document\\\"]\\n beta = True\\n documentation: str = \\\"https://docs.langflow.org/components/utilities#json-document-builder\\\"\\n\\n field_config = {\\n \\\"key\\\": {\\\"display_name\\\": \\\"Key\\\"},\\n \\\"document\\\": {\\\"display_name\\\": \\\"Document\\\"},\\n }\\n\\n def build(\\n self,\\n key: str,\\n document: Document,\\n ) -> Document:\\n documents = None\\n if isinstance(document, list):\\n documents = [\\n Document(page_content=orjson_dumps({key: doc.page_content}, indent_2=False)) for doc in document\\n ]\\n elif isinstance(document, Document):\\n documents = Document(page_content=orjson_dumps({key: document.page_content}, indent_2=False))\\n else:\\n raise TypeError(f\\\"Expected Document or list of Documents, got {type(document)}\\\")\\n self.repr_value = documents\\n return documents\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"key\",\"display_name\":\"Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"CustomComponent\"},\"description\":\"Build a Document containing a JSON object using a key and another Document page content.\",\"base_classes\":[\"Document\"],\"display_name\":\"JSON Document Builder\",\"documentation\":\"https://docs.langflow.org/components/utilities#json-document-builder\",\"custom_fields\":{\"document\":null,\"key\":null},\"output_types\":[\"JSONDocumentBuilder\"],\"field_formatters\":{},\"beta\":true},\"UpdateRequest\":{\"template\":{\"document\":{\"type\":\"Document\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"document\",\"display_name\":\"Document\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import List, Optional\\nimport requests\\nfrom langflow import CustomComponent\\nfrom langchain.schema import Document\\nfrom langflow.services.database.models.base import orjson_dumps\\n\\n\\nclass UpdateRequest(CustomComponent):\\n display_name: str = \\\"Update Request\\\"\\n description: str = \\\"Make a PATCH request to the given URL.\\\"\\n output_types: list[str] = [\\\"Document\\\"]\\n documentation: str = \\\"https://docs.langflow.org/components/utilities#update-request\\\"\\n beta: bool = True\\n field_config = {\\n \\\"url\\\": {\\\"display_name\\\": \\\"URL\\\", \\\"info\\\": \\\"The URL to make the request to.\\\"},\\n \\\"headers\\\": {\\n \\\"display_name\\\": \\\"Headers\\\",\\n \\\"field_type\\\": \\\"NestedDict\\\",\\n \\\"info\\\": \\\"The headers to send with the request.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n \\\"document\\\": {\\\"display_name\\\": \\\"Document\\\"},\\n \\\"method\\\": {\\n \\\"display_name\\\": \\\"Method\\\",\\n \\\"field_type\\\": \\\"str\\\",\\n \\\"info\\\": \\\"The HTTP method to use.\\\",\\n \\\"options\\\": [\\\"PATCH\\\", \\\"PUT\\\"],\\n \\\"value\\\": \\\"PATCH\\\",\\n },\\n }\\n\\n def update_document(\\n self,\\n session: requests.Session,\\n document: Document,\\n url: str,\\n headers: Optional[dict] = None,\\n method: str = \\\"PATCH\\\",\\n ) -> Document:\\n try:\\n if method == \\\"PATCH\\\":\\n response = session.patch(url, headers=headers, data=document.page_content)\\n elif method == \\\"PUT\\\":\\n response = session.put(url, headers=headers, data=document.page_content)\\n else:\\n raise ValueError(f\\\"Unsupported method: {method}\\\")\\n try:\\n response_json = response.json()\\n result = orjson_dumps(response_json, indent_2=False)\\n except Exception:\\n result = response.text\\n self.repr_value = result\\n return Document(\\n page_content=result,\\n metadata={\\n \\\"source\\\": url,\\n \\\"headers\\\": headers,\\n \\\"status_code\\\": response.status_code,\\n },\\n )\\n except Exception as exc:\\n return Document(\\n page_content=str(exc),\\n metadata={\\\"source\\\": url, \\\"headers\\\": headers, \\\"status_code\\\": 500},\\n )\\n\\n def build(\\n self,\\n method: str,\\n document: Document,\\n url: str,\\n headers: Optional[dict] = None,\\n ) -> List[Document]:\\n if headers is None:\\n headers = {}\\n\\n if not isinstance(document, list) and isinstance(document, Document):\\n documents: list[Document] = [document]\\n elif isinstance(document, list) and all(isinstance(doc, Document) for doc in document):\\n documents = document\\n else:\\n raise ValueError(\\\"document must be a Document or a list of Documents\\\")\\n\\n with requests.Session() as session:\\n documents = [self.update_document(session, doc, url, headers, method) for doc in documents]\\n self.repr_value = documents\\n return documents\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"headers\":{\"type\":\"NestedDict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"{\\\"Authorization\\\": \\\"Bearer \\\"}\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"headers\",\"display_name\":\"Headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"The headers to send with the request.\"},\"method\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"PATCH\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"PATCH\",\"PUT\"],\"name\":\"method\",\"display_name\":\"Method\",\"advanced\":false,\"dynamic\":false,\"info\":\"The HTTP method to use.\"},\"url\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"url\",\"display_name\":\"URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"The URL to make the request to.\"},\"_type\":\"CustomComponent\"},\"description\":\"Make a PATCH request to the given URL.\",\"base_classes\":[\"Document\"],\"display_name\":\"Update Request\",\"documentation\":\"https://docs.langflow.org/components/utilities#update-request\",\"custom_fields\":{\"document\":null,\"headers\":null,\"method\":null,\"url\":null},\"output_types\":[\"UpdateRequest\"],\"field_formatters\":{},\"beta\":true},\"PostRequest\":{\"template\":{\"document\":{\"type\":\"Document\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"document\",\"display_name\":\"Document\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langchain.schema import Document\\nfrom langflow.services.database.models.base import orjson_dumps\\nimport requests\\nfrom typing import Optional\\n\\n\\nclass PostRequest(CustomComponent):\\n display_name: str = \\\"POST Request\\\"\\n description: str = \\\"Make a POST request to the given URL.\\\"\\n output_types: list[str] = [\\\"Document\\\"]\\n documentation: str = \\\"https://docs.langflow.org/components/utilities#post-request\\\"\\n beta: bool = True\\n field_config = {\\n \\\"url\\\": {\\\"display_name\\\": \\\"URL\\\", \\\"info\\\": \\\"The URL to make the request to.\\\"},\\n \\\"headers\\\": {\\n \\\"display_name\\\": \\\"Headers\\\",\\n \\\"info\\\": \\\"The headers to send with the request.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n \\\"document\\\": {\\\"display_name\\\": \\\"Document\\\"},\\n }\\n\\n def post_document(\\n self,\\n session: requests.Session,\\n document: Document,\\n url: str,\\n headers: Optional[dict] = None,\\n ) -> Document:\\n try:\\n response = session.post(url, headers=headers, data=document.page_content)\\n try:\\n response_json = response.json()\\n result = orjson_dumps(response_json, indent_2=False)\\n except Exception:\\n result = response.text\\n self.repr_value = result\\n return Document(\\n page_content=result,\\n metadata={\\n \\\"source\\\": url,\\n \\\"headers\\\": headers,\\n \\\"status_code\\\": response,\\n },\\n )\\n except Exception as exc:\\n return Document(\\n page_content=str(exc),\\n metadata={\\n \\\"source\\\": url,\\n \\\"headers\\\": headers,\\n \\\"status_code\\\": 500,\\n },\\n )\\n\\n def build(\\n self,\\n document: Document,\\n url: str,\\n headers: Optional[dict] = None,\\n ) -> list[Document]:\\n if headers is None:\\n headers = {}\\n\\n if not isinstance(document, list) and isinstance(document, Document):\\n documents: list[Document] = [document]\\n elif isinstance(document, list) and all(isinstance(doc, Document) for doc in document):\\n documents = document\\n else:\\n raise ValueError(\\\"document must be a Document or a list of Documents\\\")\\n\\n with requests.Session() as session:\\n documents = [self.post_document(session, doc, url, headers) for doc in documents]\\n self.repr_value = documents\\n return documents\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"headers\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"{\\\"Authorization\\\": \\\"Bearer \\\"}\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"headers\",\"display_name\":\"Headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"The headers to send with the request.\"},\"url\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"url\",\"display_name\":\"URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"The URL to make the request to.\"},\"_type\":\"CustomComponent\"},\"description\":\"Make a POST request to the given URL.\",\"base_classes\":[\"Document\"],\"display_name\":\"POST Request\",\"documentation\":\"https://docs.langflow.org/components/utilities#post-request\",\"custom_fields\":{\"document\":null,\"headers\":null,\"url\":null},\"output_types\":[\"PostRequest\"],\"field_formatters\":{},\"beta\":true}},\"output_parsers\":{\"ResponseSchema\":{\"template\":{\"description\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"fileTypes\":[],\"password\":false,\"name\":\"description\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"type\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"string\",\"fileTypes\":[],\"password\":false,\"name\":\"type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"ResponseSchema\"},\"description\":\"A schema for a response from a structured output parser.\",\"base_classes\":[\"ResponseSchema\"],\"display_name\":\"ResponseSchema\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/output_parsers/structured\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"StructuredOutputParser\":{\"template\":{\"response_schemas\":{\"type\":\"ResponseSchema\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"response_schemas\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"StructuredOutputParser\"},\"description\":\"\",\"base_classes\":[\"BaseLLMOutputParser\",\"BaseOutputParser\",\"StructuredOutputParser\"],\"display_name\":\"StructuredOutputParser\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/output_parsers/structured\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false}},\"retrievers\":{\"MultiQueryRetriever\":{\"template\":{\"llm\":{\"type\":\"BaseLLM\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"prompt\":{\"type\":\"PromptTemplate\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{\"input_variables\":[\"question\"],\"input_types\":{},\"output_parser\":null,\"partial_variables\":{},\"template\":\"You are an AI language model assistant. Your task is \\n to generate 3 different versions of the given user \\n question to retrieve relevant documents from a vector database. \\n By generating multiple perspectives on the user question, \\n your goal is to help the user overcome some of the limitations \\n of distance-based similarity search. Provide these alternative \\n questions separated by newlines. Original question: {question}\",\"template_format\":\"f-string\",\"validate_template\":false},\"fileTypes\":[],\"password\":false,\"name\":\"prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"retriever\":{\"type\":\"BaseRetriever\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"retriever\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"include_original\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"include_original\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"parser_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"lines\",\"fileTypes\":[],\"password\":false,\"name\":\"parser_key\",\"display_name\":\"Parser Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"MultiQueryRetriever\"},\"description\":\"Initialize from llm using default template.\",\"base_classes\":[\"MultiQueryRetriever\",\"BaseRetriever\"],\"display_name\":\"MultiQueryRetriever\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/retrievers/how_to/MultiQueryRetriever\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"beta\":false},\"AmazonKendra\":{\"template\":{\"attribute_filter\":{\"type\":\"code\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"attribute_filter\",\"display_name\":\"Attribute Filter\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\nfrom langflow import CustomComponent\\nfrom langchain.retrievers import AmazonKendraRetriever\\nfrom langchain.schema import BaseRetriever\\n\\n\\nclass AmazonKendraRetrieverComponent(CustomComponent):\\n display_name: str = \\\"Amazon Kendra Retriever\\\"\\n description: str = \\\"Retriever that uses the Amazon Kendra API.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"index_id\\\": {\\\"display_name\\\": \\\"Index ID\\\"},\\n \\\"region_name\\\": {\\\"display_name\\\": \\\"Region Name\\\"},\\n \\\"credentials_profile_name\\\": {\\\"display_name\\\": \\\"Credentials Profile Name\\\"},\\n \\\"attribute_filter\\\": {\\n \\\"display_name\\\": \\\"Attribute Filter\\\",\\n \\\"field_type\\\": \\\"code\\\",\\n },\\n \\\"top_k\\\": {\\\"display_name\\\": \\\"Top K\\\", \\\"field_type\\\": \\\"int\\\"},\\n \\\"user_context\\\": {\\n \\\"display_name\\\": \\\"User Context\\\",\\n \\\"field_type\\\": \\\"code\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n index_id: str,\\n top_k: int = 3,\\n region_name: Optional[str] = None,\\n credentials_profile_name: Optional[str] = None,\\n attribute_filter: Optional[dict] = None,\\n user_context: Optional[dict] = None,\\n ) -> BaseRetriever:\\n try:\\n output = AmazonKendraRetriever(\\n index_id=index_id,\\n top_k=top_k,\\n region_name=region_name,\\n credentials_profile_name=credentials_profile_name,\\n attribute_filter=attribute_filter,\\n user_context=user_context,\\n ) # type: ignore\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to AmazonKendra API.\\\") from e\\n return output\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"credentials_profile_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"credentials_profile_name\",\"display_name\":\"Credentials Profile Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"index_id\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"index_id\",\"display_name\":\"Index ID\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"region_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"region_name\",\"display_name\":\"Region Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"top_k\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":3,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_k\",\"display_name\":\"Top K\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"user_context\":{\"type\":\"code\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"user_context\",\"display_name\":\"User Context\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"CustomComponent\"},\"description\":\"Retriever that uses the Amazon Kendra API.\",\"base_classes\":[\"BaseRetriever\"],\"display_name\":\"Amazon Kendra Retriever\",\"documentation\":\"\",\"custom_fields\":{\"attribute_filter\":null,\"credentials_profile_name\":null,\"index_id\":null,\"region_name\":null,\"top_k\":null,\"user_context\":null},\"output_types\":[\"AmazonKendra\"],\"field_formatters\":{},\"beta\":true},\"MetalRetriever\":{\"template\":{\"api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"api_key\",\"display_name\":\"API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"client_id\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"client_id\",\"display_name\":\"Client ID\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\nfrom langflow import CustomComponent\\nfrom langchain.retrievers import MetalRetriever\\nfrom langchain.schema import BaseRetriever\\nfrom metal_sdk.metal import Metal # type: ignore\\n\\n\\nclass MetalRetrieverComponent(CustomComponent):\\n display_name: str = \\\"Metal Retriever\\\"\\n description: str = \\\"Retriever that uses the Metal API.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"api_key\\\": {\\\"display_name\\\": \\\"API Key\\\", \\\"password\\\": True},\\n \\\"client_id\\\": {\\\"display_name\\\": \\\"Client ID\\\", \\\"password\\\": True},\\n \\\"index_id\\\": {\\\"display_name\\\": \\\"Index ID\\\"},\\n \\\"params\\\": {\\\"display_name\\\": \\\"Parameters\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(self, api_key: str, client_id: str, index_id: str, params: Optional[dict] = None) -> BaseRetriever:\\n try:\\n metal = Metal(api_key=api_key, client_id=client_id, index_id=index_id)\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to Metal API.\\\") from e\\n return MetalRetriever(client=metal, params=params or {})\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"index_id\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"index_id\",\"display_name\":\"Index ID\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"params\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"params\",\"display_name\":\"Parameters\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"_type\":\"CustomComponent\"},\"description\":\"Retriever that uses the Metal API.\",\"base_classes\":[\"BaseRetriever\"],\"display_name\":\"Metal Retriever\",\"documentation\":\"\",\"custom_fields\":{\"api_key\":null,\"client_id\":null,\"index_id\":null,\"params\":null},\"output_types\":[\"MetalRetriever\"],\"field_formatters\":{},\"beta\":true}},\"custom_components\":{\"CustomComponent\":{\"template\":{\"param\":{\"type\":\"Data\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"param\",\"display_name\":\"Parameter\",\"advanced\":false,\"dynamic\":false,\"info\":\"\"},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\n\\n\\nclass Component(CustomComponent):\\n documentation: str = \\\"http://docs.langflow.org/components/custom\\\"\\n\\n def build_config(self):\\n return {\\\"param\\\": {\\\"display_name\\\": \\\"Parameter\\\"}}\\n\\n def build(self, param: Data) -> Data:\\n return param\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\"},\"_type\":\"CustomComponent\"},\"base_classes\":[\"Data\"],\"display_name\":\"CustomComponent\",\"documentation\":\"http://docs.langflow.org/components/custom\",\"custom_fields\":{\"param\":null},\"output_types\":[\"CustomComponent\"],\"field_formatters\":{},\"beta\":true}}}" - }, - "headersSize": -1, - "bodySize": -1, - "redirectURL": "" - }, - "cache": {}, - "timings": { "send": -1, "wait": -1, "receive": 0.901 } - }, - { - "startedDateTime": "2023-12-11T18:54:58.423Z", - "time": 0.527, - "request": { - "method": "GET", - "url": "http://localhost:3000/api/v1/auto_login", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Accept", "value": "application/json, text/plain, */*" }, - { "name": "Accept-Encoding", "value": "gzip, deflate, br" }, - { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, - { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20" }, - { "name": "Connection", "value": "keep-alive" }, - { "name": "Cookie", "value": "access_token_lf=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20; refresh_tkn_lflw=auto" }, - { "name": "Host", "value": "localhost:3000" }, - { "name": "Referer", "value": "http://localhost:3000/flows" }, - { "name": "Sec-Fetch-Dest", "value": "empty" }, - { "name": "Sec-Fetch-Mode", "value": "cors" }, - { "name": "Sec-Fetch-Site", "value": "same-origin" }, - { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" }, - { "name": "sec-ch-ua", "value": "\"Chromium\";v=\"119\", \"Not?A_Brand\";v=\"24\"" }, - { "name": "sec-ch-ua-mobile", "value": "?0" }, - { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } - ], - "queryString": [], - "headersSize": -1, - "bodySize": -1 - }, - "response": { - "status": 200, - "statusText": "OK", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Access-Control-Allow-Origin", "value": "*" }, - { "name": "connection", "value": "close" }, - { "name": "content-length", "value": "227" }, - { "name": "content-type", "value": "application/json" }, - { "name": "date", "value": "Mon, 11 Dec 2023 18:54:58 GMT" }, - { "name": "server", "value": "uvicorn" } - ], - "content": { - "size": -1, - "mimeType": "application/json", - "text": "{\"access_token\":\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20\",\"refresh_token\":null,\"token_type\":\"bearer\"}" - }, - "headersSize": -1, - "bodySize": -1, - "redirectURL": "" - }, - "cache": {}, - "timings": { "send": -1, "wait": -1, "receive": 0.527 } - }, - { - "startedDateTime": "2023-12-11T18:55:08.881Z", - "time": 0.635, - "request": { - "method": "GET", - "url": "http://localhost:3000/api/v1/build/2920dde2-5c24-4fe0-9c06-ef86b5a16a99/status", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Accept", "value": "application/json, text/plain, */*" }, - { "name": "Accept-Encoding", "value": "gzip, deflate, br" }, - { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, - { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20" }, - { "name": "Connection", "value": "keep-alive" }, - { "name": "Cookie", "value": "access_token_lf=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20; refresh_tkn_lflw=auto" }, - { "name": "Host", "value": "localhost:3000" }, - { "name": "Referer", "value": "http://localhost:3000/flow/2920dde2-5c24-4fe0-9c06-ef86b5a16a99" }, - { "name": "Sec-Fetch-Dest", "value": "empty" }, - { "name": "Sec-Fetch-Mode", "value": "cors" }, - { "name": "Sec-Fetch-Site", "value": "same-origin" }, - { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" }, - { "name": "sec-ch-ua", "value": "\"Chromium\";v=\"119\", \"Not?A_Brand\";v=\"24\"" }, - { "name": "sec-ch-ua-mobile", "value": "?0" }, - { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } - ], - "queryString": [], - "headersSize": -1, - "bodySize": -1 - }, - "response": { - "status": 200, - "statusText": "OK", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Access-Control-Allow-Origin", "value": "*" }, - { "name": "connection", "value": "close" }, - { "name": "content-length", "value": "15" }, - { "name": "content-type", "value": "application/json" }, - { "name": "date", "value": "Mon, 11 Dec 2023 18:55:08 GMT" }, - { "name": "server", "value": "uvicorn" } - ], - "content": { - "size": -1, - "mimeType": "application/json", - "text": "{\"built\":false}" - }, - "headersSize": -1, - "bodySize": -1, - "redirectURL": "" - }, - "cache": {}, - "timings": { "send": -1, "wait": -1, "receive": 0.635 } - }, - { - "startedDateTime": "2023-12-11T18:55:08.881Z", - "time": 1.309, - "request": { - "method": "GET", - "url": "http://localhost:3000/api/v1/flows/", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Accept", "value": "application/json, text/plain, */*" }, - { "name": "Accept-Encoding", "value": "gzip, deflate, br" }, - { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, - { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20" }, - { "name": "Connection", "value": "keep-alive" }, - { "name": "Cookie", "value": "access_token_lf=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20; refresh_tkn_lflw=auto" }, - { "name": "Host", "value": "localhost:3000" }, - { "name": "Referer", "value": "http://localhost:3000/flow/2920dde2-5c24-4fe0-9c06-ef86b5a16a99" }, - { "name": "Sec-Fetch-Dest", "value": "empty" }, - { "name": "Sec-Fetch-Mode", "value": "cors" }, - { "name": "Sec-Fetch-Site", "value": "same-origin" }, - { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" }, - { "name": "sec-ch-ua", "value": "\"Chromium\";v=\"119\", \"Not?A_Brand\";v=\"24\"" }, - { "name": "sec-ch-ua-mobile", "value": "?0" }, - { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } - ], - "queryString": [], - "headersSize": -1, - "bodySize": -1 - }, - "response": { - "status": 200, - "statusText": "OK", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Access-Control-Allow-Origin", "value": "*" }, - { "name": "connection", "value": "close" }, - { "name": "content-length", "value": "375696" }, - { "name": "content-type", "value": "application/json" }, - { "name": "date", "value": "Mon, 11 Dec 2023 18:55:08 GMT" }, - { "name": "server", "value": "uvicorn" } - ], - "content": { - "size": -1, - "mimeType": "application/json", - "text": "[{\"name\":\"Awesome Euclid\",\"description\":\"Language Models, Mapped and Mastered.\",\"data\":{\"nodes\":[{\"width\":384,\"height\":374,\"id\":\"PromptTemplate-m2yFu\",\"type\":\"genericNode\",\"position\":{\"x\":462.6456058272081,\"y\":1033.9314297130313},\"data\":{\"type\":\"PromptTemplate\",\"node\":{\"template\":{\"output_parser\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"BaseOutputParser\",\"list\":false},\"input_types\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_types\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"input_variables\":{\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":true,\"value\":[\"transcription\"]},\"partial_variables\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"partial_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"template\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"password\":false,\"name\":\"template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"prompt\",\"list\":false,\"value\":\"create an image prompt based on the song's lyrics to be used as the album cover of this song:\\n\\nlyrics:\\n{transcription}\"},\"template_format\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"f-string\",\"password\":false,\"name\":\"template_format\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":false},\"validate_template\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"validate_template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"PromptTemplate\",\"transcription\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"transcription\",\"display_name\":\"transcription\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"A prompt template for a language model.\",\"base_classes\":[\"PromptTemplate\",\"StringPromptTemplate\",\"BasePromptTemplate\"],\"name\":\"\",\"display_name\":\"PromptTemplate\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/\",\"custom_fields\":{\"\":[\"transcription\"],\"template\":[\"transcription\",\"question\"]},\"output_types\":[],\"full_path\":null,\"field_formatters\":{},\"beta\":false,\"error\":null},\"id\":\"PromptTemplate-m2yFu\"},\"selected\":false,\"positionAbsolute\":{\"x\":462.6456058272081,\"y\":1033.9314297130313},\"dragging\":false},{\"width\":384,\"height\":626,\"id\":\"ChatOpenAI-urapv\",\"type\":\"genericNode\",\"position\":{\"x\":189.94856095084924,\"y\":-85.06556385338186},\"data\":{\"type\":\"ChatOpenAI\",\"node\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"list\":true},\"async_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"async_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"default_headers\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"default_query\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_query\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"http_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"http_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":2,\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"max_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"max_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false,\"value\":\"\"},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"gpt-4-1106-preview\",\"password\":false,\"options\":[\"gpt-4-1106-preview\",\"gpt-4\",\"gpt-4-32k\",\"gpt-3.5-turbo\",\"gpt-3.5-turbo-16k\"],\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"n\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"n\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":false,\"dynamic\":false,\"info\":\"\\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\\n\",\"type\":\"str\",\"list\":false},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":0.7,\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ChatOpenAI\"},\"description\":\"`OpenAI` Chat large language models API.\",\"base_classes\":[\"ChatOpenAI\",\"BaseChatModel\",\"BaseLanguageModel\",\"BaseLLM\"],\"display_name\":\"ChatOpenAI\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai\",\"beta\":false,\"error\":null},\"id\":\"ChatOpenAI-urapv\"},\"selected\":false,\"positionAbsolute\":{\"x\":189.94856095084924,\"y\":-85.06556385338186},\"dragging\":false},{\"width\":384,\"height\":806,\"id\":\"CustomComponent-IEIUl\",\"type\":\"genericNode\",\"position\":{\"x\":2364.865919667005,\"y\":88.43094097025096},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nfrom platformdirs import user_cache_dir\\nimport base64\\nfrom PIL import Image\\nfrom io import BytesIO\\nfrom openai import OpenAI\\nfrom pathlib import Path\\n\\nclass Component(CustomComponent):\\n display_name: str = \\\"Image generator\\\"\\n description: str = \\\"generate images using Dall-E\\\"\\n documentation: str = \\\"http://docs.langflow.org/components/custom\\\"\\n\\n def build_config(self):\\n return {\\\"prompt\\\": {\\\"display_name\\\": \\\"Prompt\\\",\\\"input_types\\\":[\\\"str\\\"]},\\n \\\"api_key\\\":{\\\"display_name\\\":\\\"OpenAI API key\\\",\\\"password\\\":True},\\n \\\"model\\\":{\\\"display_name\\\":\\\"Model name\\\",\\\"advanced\\\":True,\\\"options\\\":[\\\"dall-e-2\\\",\\\"dall-e-3\\\"], \\\"value\\\":\\\"dall-e-3\\\"},\\n \\\"file_name\\\":{\\\"display_name\\\":\\\"File Name\\\"},\\n \\\"output_format\\\":{\\\"display_name\\\":\\\"Output format\\\",\\\"options\\\":[\\\"jpeg\\\",\\\"png\\\"],\\\"value\\\":\\\"jpeg\\\"},\\n \\\"width\\\":{\\\"display_name\\\":\\\"Width\\\" ,\\\"value\\\":1024},\\n \\\"height\\\":{\\\"display_name\\\":\\\"Height\\\", \\\"value\\\":1024}\\n }\\n\\n def build(self, prompt:str,api_key:str,model:str,file_name:str,output_format:str,width:int,height:int):\\n client = OpenAI(api_key=api_key)\\n cache_dir = Path(user_cache_dir(\\\"langflow\\\"))\\n images_dir = cache_dir / \\\"images\\\"\\n images_dir.mkdir(parents=True, exist_ok=True)\\n image_path = images_dir / f\\\"{file_name}.{output_format}\\\"\\n response = client.images.generate(\\n model=model,\\n prompt=prompt,\\n size=f\\\"{height}x{width}\\\",\\n response_format=\\\"b64_json\\\",\\n n=1,\\n )\\n # Decode base64-encoded image string\\n binary_data = base64.b64decode(response.data[0].b64_json)\\n # Create PIL Image object from binary image data\\n image_pil = Image.open(BytesIO(binary_data))\\n image_pil.save(image_path, format=output_format.upper())\\n return \\\"\\\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"api_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"api_key\",\"display_name\":\"OpenAI API key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"},\"file_name\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"file_name\",\"display_name\":\"File Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"album\"},\"height\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":1024,\"password\":false,\"name\":\"height\",\"display_name\":\"Height\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"model\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"dall-e-3\",\"password\":false,\"options\":[\"dall-e-2\",\"dall-e-3\"],\"name\":\"model\",\"display_name\":\"Model name\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"output_format\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"jpeg\",\"password\":false,\"options\":[\"jpeg\",\"png\"],\"name\":\"output_format\",\"display_name\":\"Output format\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"prompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"prompt\",\"display_name\":\"Prompt\",\"advanced\":false,\"input_types\":[\"str\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"},\"width\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":1024,\"password\":false,\"name\":\"width\",\"display_name\":\"Width\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false}},\"description\":\"generate images using Dall-E\",\"base_classes\":[\"Data\"],\"display_name\":\"Image generator\",\"custom_fields\":{\"api_key\":null,\"file_name\":null,\"height\":null,\"model\":null,\"output_format\":null,\"prompt\":null,\"width\":null},\"output_types\":[\"Data\"],\"documentation\":\"http://docs.langflow.org/components/custom\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-IEIUl\"},\"selected\":false,\"positionAbsolute\":{\"x\":2364.865919667005,\"y\":88.43094097025096}},{\"width\":384,\"height\":338,\"id\":\"LLMChain-KlJb3\",\"type\":\"genericNode\",\"position\":{\"x\":1242.9851164540805,\"y\":-139.74634696823108},\"data\":{\"type\":\"LLMChain\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Callable, Optional, Union\\n\\nfrom langchain.chains import LLMChain\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import (\\n BaseLanguageModel,\\n BaseMemory,\\n BasePromptTemplate,\\n Chain,\\n)\\n\\n\\nclass LLMChainComponent(CustomComponent):\\n display_name = \\\"LLMChain\\\"\\n description = \\\"Chain to run queries against LLMs\\\"\\n\\n def build_config(self):\\n return {\\n \\\"prompt\\\": {\\\"display_name\\\": \\\"Prompt\\\"},\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"memory\\\": {\\\"display_name\\\": \\\"Memory\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n prompt: BasePromptTemplate,\\n llm: BaseLanguageModel,\\n memory: Optional[BaseMemory] = None,\\n ) -> Union[Chain, Callable]:\\n return LLMChain(prompt=prompt, llm=llm, memory=memory)\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"display_name\":\"code\"},\"_type\":\"CustomComponent\",\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseMemory\",\"list\":false},\"prompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"prompt\",\"display_name\":\"Prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BasePromptTemplate\",\"list\":false}},\"description\":\"Chain to run queries against LLMs\",\"base_classes\":[\"Chain\",\"Callable\"],\"display_name\":\"LLMChain\",\"custom_fields\":{\"llm\":null,\"memory\":null,\"prompt\":null},\"output_types\":[\"LLMChain\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"LLMChain-KlJb3\"},\"selected\":false,\"positionAbsolute\":{\"x\":1242.9851164540805,\"y\":-139.74634696823108},\"dragging\":false},{\"width\":384,\"height\":328,\"id\":\"CustomComponent-bCuc0\",\"type\":\"genericNode\",\"position\":{\"x\":1747.8107777342625,\"y\":319.13729017446667},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\n\\n\\nclass Component(CustomComponent):\\n display_name: str = \\\"Custom Component\\\"\\n description: str = \\\"Create any custom component you want!\\\"\\n documentation: str = \\\"http://docs.langflow.org/components/custom\\\"\\n\\n def build_config(self):\\n return {\\\"param\\\": {\\\"display_name\\\": \\\"Parameter\\\"}}\\n\\n def build(self, param: Chain) -> str:\\n result = param.run({})\\n self.status = result\\n return result\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"param\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"param\",\"display_name\":\"Parameter\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Chain\",\"list\":false}},\"description\":\"Create any custom component you want!\",\"base_classes\":[\"str\"],\"display_name\":\"Custom Component\",\"custom_fields\":{\"param\":null},\"output_types\":[\"str\"],\"documentation\":\"http://docs.langflow.org/components/custom\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-bCuc0\"},\"selected\":false,\"positionAbsolute\":{\"x\":1747.8107777342625,\"y\":319.13729017446667}}],\"edges\":[{\"source\":\"LLMChain-KlJb3\",\"target\":\"CustomComponent-bCuc0\",\"sourceHandle\":\"{œbaseClassesœ:[œChainœ,œCallableœ],œdataTypeœ:œLLMChainœ,œidœ:œLLMChain-KlJb3œ}\",\"targetHandle\":\"{œfieldNameœ:œparamœ,œidœ:œCustomComponent-bCuc0œ,œinputTypesœ:null,œtypeœ:œChainœ}\",\"id\":\"reactflow__edge-LLMChain-KlJb3{œbaseClassesœ:[œChainœ,œCallableœ],œdataTypeœ:œLLMChainœ,œidœ:œLLMChain-KlJb3œ}-CustomComponent-bCuc0{œfieldNameœ:œparamœ,œidœ:œCustomComponent-bCuc0œ,œinputTypesœ:null,œtypeœ:œChainœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"param\",\"id\":\"CustomComponent-bCuc0\",\"inputTypes\":null,\"type\":\"Chain\"},\"sourceHandle\":{\"baseClasses\":[\"Chain\",\"Callable\"],\"dataType\":\"LLMChain\",\"id\":\"LLMChain-KlJb3\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"selected\":false},{\"source\":\"ChatOpenAI-urapv\",\"target\":\"LLMChain-KlJb3\",\"sourceHandle\":\"{œbaseClassesœ:[œChatOpenAIœ,œBaseChatModelœ,œBaseLanguageModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-urapvœ}\",\"targetHandle\":\"{œfieldNameœ:œllmœ,œidœ:œLLMChain-KlJb3œ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\",\"id\":\"reactflow__edge-ChatOpenAI-urapv{œbaseClassesœ:[œChatOpenAIœ,œBaseChatModelœ,œBaseLanguageModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-urapvœ}-LLMChain-KlJb3{œfieldNameœ:œllmœ,œidœ:œLLMChain-KlJb3œ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"llm\",\"id\":\"LLMChain-KlJb3\",\"inputTypes\":null,\"type\":\"BaseLanguageModel\"},\"sourceHandle\":{\"baseClasses\":[\"ChatOpenAI\",\"BaseChatModel\",\"BaseLanguageModel\",\"BaseLLM\"],\"dataType\":\"ChatOpenAI\",\"id\":\"ChatOpenAI-urapv\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"selected\":false},{\"source\":\"PromptTemplate-m2yFu\",\"target\":\"LLMChain-KlJb3\",\"sourceHandle\":\"{œbaseClassesœ:[œPromptTemplateœ,œStringPromptTemplateœ,œBasePromptTemplateœ],œdataTypeœ:œPromptTemplateœ,œidœ:œPromptTemplate-m2yFuœ}\",\"targetHandle\":\"{œfieldNameœ:œpromptœ,œidœ:œLLMChain-KlJb3œ,œinputTypesœ:null,œtypeœ:œBasePromptTemplateœ}\",\"id\":\"reactflow__edge-PromptTemplate-m2yFu{œbaseClassesœ:[œPromptTemplateœ,œStringPromptTemplateœ,œBasePromptTemplateœ],œdataTypeœ:œPromptTemplateœ,œidœ:œPromptTemplate-m2yFuœ}-LLMChain-KlJb3{œfieldNameœ:œpromptœ,œidœ:œLLMChain-KlJb3œ,œinputTypesœ:null,œtypeœ:œBasePromptTemplateœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"prompt\",\"id\":\"LLMChain-KlJb3\",\"inputTypes\":null,\"type\":\"BasePromptTemplate\"},\"sourceHandle\":{\"baseClasses\":[\"PromptTemplate\",\"StringPromptTemplate\",\"BasePromptTemplate\"],\"dataType\":\"PromptTemplate\",\"id\":\"PromptTemplate-m2yFu\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"selected\":false},{\"source\":\"CustomComponent-bCuc0\",\"target\":\"CustomComponent-IEIUl\",\"sourceHandle\":\"{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-bCuc0œ}\",\"targetHandle\":\"{œfieldNameœ:œpromptœ,œidœ:œCustomComponent-IEIUlœ,œinputTypesœ:[œstrœ],œtypeœ:œstrœ}\",\"id\":\"reactflow__edge-CustomComponent-bCuc0{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-bCuc0œ}-CustomComponent-IEIUl{œfieldNameœ:œpromptœ,œidœ:œCustomComponent-IEIUlœ,œinputTypesœ:[œstrœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"prompt\",\"id\":\"CustomComponent-IEIUl\",\"inputTypes\":[\"str\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"str\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-bCuc0\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"selected\":false}],\"viewport\":{\"x\":92.23454077990459,\"y\":183.8125619056221,\"zoom\":0.6070974421975234}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:33:18.503954\",\"folder\":null,\"id\":\"fe142ce5-32dc-4955-b186-672ced662f13\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Goofy Darwin\",\"description\":\"Conversation Catalyst Engine.\",\"data\":{\"nodes\":[{\"width\":384,\"height\":626,\"id\":\"OpenAI-3ZVDh\",\"type\":\"genericNode\",\"position\":{\"x\":-4.0041891741949485,\"y\":-114.02615182719649},\"data\":{\"type\":\"OpenAI\",\"node\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"list\":true},\"allowed_special\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":[],\"password\":false,\"name\":\"allowed_special\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"async_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"async_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"batch_size\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":20,\"password\":false,\"name\":\"batch_size\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"best_of\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"best_of\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"default_headers\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"default_query\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_query\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"disallowed_special\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"all\",\"password\":false,\"name\":\"disallowed_special\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"frequency_penalty\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":0,\"password\":false,\"name\":\"frequency_penalty\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"http_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"http_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"logit_bias\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"logit_bias\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":2,\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"max_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":256,\"password\":true,\"name\":\"max_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"text-davinci-003\",\"password\":false,\"options\":[\"text-davinci-003\",\"text-davinci-002\",\"text-curie-001\",\"text-babbage-001\",\"text-ada-001\"],\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"n\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"n\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":false,\"dynamic\":false,\"info\":\"\\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\\n\",\"type\":\"str\",\"list\":false},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"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\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"presence_penalty\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":0,\"password\":false,\"name\":\"presence_penalty\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":0.7,\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"top_p\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"top_p\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"OpenAI\"},\"description\":\"OpenAI large language models.\",\"base_classes\":[\"OpenAI\",\"BaseLLM\",\"BaseOpenAI\",\"BaseLanguageModel\"],\"display_name\":\"OpenAI\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/openai\",\"beta\":false,\"error\":null},\"id\":\"OpenAI-3ZVDh\"},\"selected\":true,\"positionAbsolute\":{\"x\":-4.0041891741949485,\"y\":-114.02615182719649},\"dragging\":false},{\"width\":384,\"height\":338,\"id\":\"LLMChain-RFYXY\",\"type\":\"genericNode\",\"position\":{\"x\":586.672100458868,\"y\":10.967049167706678},\"data\":{\"type\":\"LLMChain\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Callable, Optional, Union\\n\\nfrom langchain.chains import LLMChain\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import (\\n BaseLanguageModel,\\n BaseMemory,\\n BasePromptTemplate,\\n Chain,\\n)\\n\\n\\nclass LLMChainComponent(CustomComponent):\\n display_name = \\\"LLMChain\\\"\\n description = \\\"Chain to run queries against LLMs\\\"\\n\\n def build_config(self):\\n return {\\n \\\"prompt\\\": {\\\"display_name\\\": \\\"Prompt\\\"},\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"memory\\\": {\\\"display_name\\\": \\\"Memory\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n prompt: BasePromptTemplate,\\n llm: BaseLanguageModel,\\n memory: Optional[BaseMemory] = None,\\n ) -> Union[Chain, Callable]:\\n return LLMChain(prompt=prompt, llm=llm, memory=memory)\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseMemory\",\"list\":false},\"prompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"prompt\",\"display_name\":\"Prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BasePromptTemplate\",\"list\":false}},\"description\":\"Chain to run queries against LLMs\",\"base_classes\":[\"Chain\",\"Callable\"],\"display_name\":\"LLMChain\",\"custom_fields\":{\"llm\":null,\"memory\":null,\"prompt\":null},\"output_types\":[\"LLMChain\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"LLMChain-RFYXY\"},\"positionAbsolute\":{\"x\":586.672100458868,\"y\":10.967049167706678}},{\"width\":384,\"height\":242,\"id\":\"ChatPromptTemplate-ce1sg\",\"type\":\"genericNode\",\"position\":{\"x\":395.598984452791,\"y\":612.188491773035},\"data\":{\"type\":\"ChatPromptTemplate\",\"node\":{\"template\":{\"messages\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"messages\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"BaseMessagePromptTemplate\",\"list\":true},\"output_parser\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"BaseOutputParser\",\"list\":false},\"input_types\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_types\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"input_variables\":{\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":true},\"partial_variables\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"partial_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"validate_template\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"validate_template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ChatPromptTemplate\"},\"description\":\"A prompt template for chat models.\",\"base_classes\":[\"ChatPromptTemplate\",\"BaseChatPromptTemplate\",\"BasePromptTemplate\"],\"display_name\":\"ChatPromptTemplate\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/how_to/prompts\",\"beta\":false,\"error\":null},\"id\":\"ChatPromptTemplate-ce1sg\"},\"selected\":false,\"positionAbsolute\":{\"x\":395.598984452791,\"y\":612.188491773035},\"dragging\":false}],\"edges\":[{\"source\":\"OpenAI-3ZVDh\",\"sourceHandle\":\"{œbaseClassesœ:[œOpenAIœ,œBaseLLMœ,œBaseOpenAIœ,œBaseLanguageModelœ],œdataTypeœ:œOpenAIœ,œidœ:œOpenAI-3ZVDhœ}\",\"target\":\"LLMChain-RFYXY\",\"targetHandle\":\"{œfieldNameœ:œllmœ,œidœ:œLLMChain-RFYXYœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"llm\",\"id\":\"LLMChain-RFYXY\",\"inputTypes\":null,\"type\":\"BaseLanguageModel\"},\"sourceHandle\":{\"baseClasses\":[\"OpenAI\",\"BaseLLM\",\"BaseOpenAI\",\"BaseLanguageModel\"],\"dataType\":\"OpenAI\",\"id\":\"OpenAI-3ZVDh\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-OpenAI-3ZVDh{œbaseClassesœ:[œOpenAIœ,œBaseLLMœ,œBaseOpenAIœ,œBaseLanguageModelœ],œdataTypeœ:œOpenAIœ,œidœ:œOpenAI-3ZVDhœ}-LLMChain-RFYXY{œfieldNameœ:œllmœ,œidœ:œLLMChain-RFYXYœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\"},{\"source\":\"ChatPromptTemplate-ce1sg\",\"sourceHandle\":\"{œbaseClassesœ:[œChatPromptTemplateœ,œBaseChatPromptTemplateœ,œBasePromptTemplateœ],œdataTypeœ:œChatPromptTemplateœ,œidœ:œChatPromptTemplate-ce1sgœ}\",\"target\":\"LLMChain-RFYXY\",\"targetHandle\":\"{œfieldNameœ:œpromptœ,œidœ:œLLMChain-RFYXYœ,œinputTypesœ:null,œtypeœ:œBasePromptTemplateœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"prompt\",\"id\":\"LLMChain-RFYXY\",\"inputTypes\":null,\"type\":\"BasePromptTemplate\"},\"sourceHandle\":{\"baseClasses\":[\"ChatPromptTemplate\",\"BaseChatPromptTemplate\",\"BasePromptTemplate\"],\"dataType\":\"ChatPromptTemplate\",\"id\":\"ChatPromptTemplate-ce1sg\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-ChatPromptTemplate-ce1sg{œbaseClassesœ:[œChatPromptTemplateœ,œBaseChatPromptTemplateœ,œBasePromptTemplateœ],œdataTypeœ:œChatPromptTemplateœ,œidœ:œChatPromptTemplate-ce1sgœ}-LLMChain-RFYXY{œfieldNameœ:œpromptœ,œidœ:œLLMChain-RFYXYœ,œinputTypesœ:null,œtypeœ:œBasePromptTemplateœ}\"}],\"viewport\":{\"x\":8.832868402772647,\"y\":189.85443326477025,\"zoom\":0.6070974421975235}},\"is_component\":false,\"updated_at\":\"2023-12-04T22:50:19.584160\",\"folder\":null,\"id\":\"103766f0-1f50-427a-9ba7-2ab73343c524\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Perky Easley\",\"description\":\"Your Toolkit for Text Generation.\",\"data\":{\"nodes\":[{\"width\":384,\"height\":626,\"id\":\"ChatOpenAI-VPh47\",\"type\":\"genericNode\",\"position\":{\"x\":-328.5742193020408,\"y\":-420.1025929438987},\"data\":{\"type\":\"ChatOpenAI\",\"node\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"list\":true},\"async_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"async_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"default_headers\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"default_query\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_query\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"http_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"http_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":2,\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"max_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"max_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"gpt-3.5-turbo\",\"password\":false,\"options\":[\"gpt-4-1106-preview\",\"gpt-4\",\"gpt-4-32k\",\"gpt-3.5-turbo\",\"gpt-3.5-turbo-16k\"],\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"n\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"n\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":false,\"dynamic\":false,\"info\":\"\\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\\n\",\"type\":\"str\",\"list\":false},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"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\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":0.7,\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ChatOpenAI\"},\"description\":\"`OpenAI` Chat large language models API.\",\"base_classes\":[\"BaseChatModel\",\"ChatOpenAI\",\"BaseLanguageModel\",\"BaseLLM\"],\"display_name\":\"ChatOpenAI\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai\",\"beta\":false,\"error\":null},\"id\":\"ChatOpenAI-VPh47\"},\"selected\":false,\"positionAbsolute\":{\"x\":-328.5742193020408,\"y\":-420.1025929438987},\"dragging\":false},{\"width\":384,\"height\":338,\"id\":\"LLMChain-NgFyo\",\"type\":\"genericNode\",\"position\":{\"x\":225.3113389084088,\"y\":-193.3520019494289},\"data\":{\"type\":\"LLMChain\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Callable, Optional, Union\\n\\nfrom langchain.chains import LLMChain\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import (\\n BaseLanguageModel,\\n BaseMemory,\\n BasePromptTemplate,\\n Chain,\\n)\\n\\n\\nclass LLMChainComponent(CustomComponent):\\n display_name = \\\"LLMChain\\\"\\n description = \\\"Chain to run queries against LLMs\\\"\\n\\n def build_config(self):\\n return {\\n \\\"prompt\\\": {\\\"display_name\\\": \\\"Prompt\\\"},\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"memory\\\": {\\\"display_name\\\": \\\"Memory\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n prompt: BasePromptTemplate,\\n llm: BaseLanguageModel,\\n memory: Optional[BaseMemory] = None,\\n ) -> Union[Chain, Callable]:\\n return LLMChain(prompt=prompt, llm=llm, memory=memory)\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseMemory\",\"list\":false},\"prompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"prompt\",\"display_name\":\"Prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BasePromptTemplate\",\"list\":false}},\"description\":\"Chain to run queries against LLMs\",\"base_classes\":[\"Chain\",\"Callable\"],\"display_name\":\"LLMChain\",\"custom_fields\":{\"llm\":null,\"memory\":null,\"prompt\":null},\"output_types\":[\"LLMChain\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"LLMChain-NgFyo\"},\"selected\":false,\"positionAbsolute\":{\"x\":225.3113389084088,\"y\":-193.3520019494289},\"dragging\":false},{\"width\":384,\"height\":374,\"id\":\"PromptTemplate-oAFjh\",\"type\":\"genericNode\",\"position\":{\"x\":-342.62522294052764,\"y\":391.20629510686103},\"data\":{\"type\":\"PromptTemplate\",\"node\":{\"template\":{\"output_parser\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"BaseOutputParser\",\"list\":false},\"input_types\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_types\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"input_variables\":{\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":true,\"value\":[\"links\"]},\"partial_variables\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"partial_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"template\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"password\":false,\"name\":\"template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"prompt\",\"list\":false,\"value\":\"Answer everything with links\\n{links}\"},\"template_format\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"f-string\",\"password\":false,\"name\":\"template_format\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":false},\"validate_template\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"validate_template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"PromptTemplate\",\"links\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"links\",\"display_name\":\"links\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"A prompt template for a language model.\",\"base_classes\":[\"BasePromptTemplate\",\"StringPromptTemplate\",\"PromptTemplate\"],\"name\":\"\",\"display_name\":\"PromptTemplate\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/\",\"custom_fields\":{\"\":[\"links\"]},\"output_types\":[],\"full_path\":null,\"field_formatters\":{},\"beta\":false,\"error\":null},\"id\":\"PromptTemplate-oAFjh\"},\"selected\":true,\"dragging\":false,\"positionAbsolute\":{\"x\":-342.62522294052764,\"y\":391.20629510686103}}],\"edges\":[{\"source\":\"ChatOpenAI-VPh47\",\"sourceHandle\":\"{œbaseClassesœ:[œBaseChatModelœ,œChatOpenAIœ,œBaseLanguageModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-VPh47œ}\",\"target\":\"LLMChain-NgFyo\",\"targetHandle\":\"{œfieldNameœ:œllmœ,œidœ:œLLMChain-NgFyoœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"llm\",\"id\":\"LLMChain-NgFyo\",\"inputTypes\":null,\"type\":\"BaseLanguageModel\"},\"sourceHandle\":{\"baseClasses\":[\"BaseChatModel\",\"ChatOpenAI\",\"BaseLanguageModel\",\"BaseLLM\"],\"dataType\":\"ChatOpenAI\",\"id\":\"ChatOpenAI-VPh47\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-ChatOpenAI-VPh47{œbaseClassesœ:[œBaseChatModelœ,œChatOpenAIœ,œBaseLanguageModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-VPh47œ}-LLMChain-NgFyo{œfieldNameœ:œllmœ,œidœ:œLLMChain-NgFyoœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\"},{\"source\":\"PromptTemplate-oAFjh\",\"sourceHandle\":\"{œbaseClassesœ:[œBasePromptTemplateœ,œStringPromptTemplateœ,œPromptTemplateœ],œdataTypeœ:œPromptTemplateœ,œidœ:œPromptTemplate-oAFjhœ}\",\"target\":\"LLMChain-NgFyo\",\"targetHandle\":\"{œfieldNameœ:œpromptœ,œidœ:œLLMChain-NgFyoœ,œinputTypesœ:null,œtypeœ:œBasePromptTemplateœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"prompt\",\"id\":\"LLMChain-NgFyo\",\"inputTypes\":null,\"type\":\"BasePromptTemplate\"},\"sourceHandle\":{\"baseClasses\":[\"BasePromptTemplate\",\"StringPromptTemplate\",\"PromptTemplate\"],\"dataType\":\"PromptTemplate\",\"id\":\"PromptTemplate-oAFjh\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-PromptTemplate-oAFjh{œbaseClassesœ:[œBasePromptTemplateœ,œStringPromptTemplateœ,œPromptTemplateœ],œdataTypeœ:œPromptTemplateœ,œidœ:œPromptTemplate-oAFjhœ}-LLMChain-NgFyo{œfieldNameœ:œpromptœ,œidœ:œLLMChain-NgFyoœ,œinputTypesœ:null,œtypeœ:œBasePromptTemplateœ}\"}],\"viewport\":{\"x\":338.6546182690814,\"y\":53.026340800283265,\"zoom\":0.7169776240079143}},\"is_component\":false,\"updated_at\":\"2023-12-04T22:53:25.148460\",\"folder\":null,\"id\":\"a794fc48-5e9b-42a3-924f-7fe610500035\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"(D) Basic Chat (1) (4)\",\"description\":\"Simplest possible chat model\",\"data\":{\"nodes\":[{\"width\":384,\"height\":626,\"id\":\"ChatOpenAI-fBcfh\",\"type\":\"genericNode\",\"position\":{\"x\":228.87326389541306,\"y\":465.8628482073749},\"data\":{\"type\":\"ChatOpenAI\",\"node\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":true},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":6,\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"max_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"max_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"gpt-3.5-turbo\",\"password\":false,\"options\":[\"gpt-3.5-turbo-0613\",\"gpt-3.5-turbo\",\"gpt-3.5-turbo-16k-0613\",\"gpt-3.5-turbo-16k\",\"gpt-4-0613\",\"gpt-4-32k-0613\",\"gpt-4\",\"gpt-4-32k\"],\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"n\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"n\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":false,\"dynamic\":false,\"info\":\"\\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\\n\",\"type\":\"str\",\"list\":false},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"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\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false,\"value\":60},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":0.7,\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ChatOpenAI\"},\"description\":\"`OpenAI` Chat large language models API.\",\"base_classes\":[\"BaseChatModel\",\"BaseLanguageModel\",\"ChatOpenAI\",\"BaseLLM\"],\"display_name\":\"ChatOpenAI\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai\"},\"id\":\"ChatOpenAI-fBcfh\",\"value\":null},\"selected\":false,\"dragging\":false,\"positionAbsolute\":{\"x\":228.87326389541306,\"y\":465.8628482073749}},{\"width\":384,\"height\":310,\"id\":\"ConversationChain-bVNex\",\"type\":\"genericNode\",\"position\":{\"x\":806,\"y\":554},\"data\":{\"type\":\"ConversationChain\",\"node\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":true},\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseMemory\",\"list\":false},\"output_parser\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":{\"_type\":\"default\"},\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLLMOutputParser\",\"list\":false},\"prompt\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":{\"input_variables\":[\"history\",\"input\"],\"output_parser\":null,\"partial_variables\":{},\"template\":\"The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\\n\\nCurrent conversation:\\n{history}\\nHuman: {input}\\nAI:\",\"template_format\":\"f-string\",\"validate_template\":true,\"_type\":\"prompt\"},\"password\":false,\"name\":\"prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BasePromptTemplate\",\"list\":false},\"input_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"input\",\"password\":false,\"name\":\"input_key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"llm_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"llm_kwargs\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"output_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"response\",\"password\":false,\"name\":\"output_key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"return_final_only\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":true,\"password\":false,\"name\":\"return_final_only\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ConversationChain\"},\"description\":\"Chain to have a conversation and load context from memory.\",\"base_classes\":[\"ConversationChain\",\"Chain\",\"LLMChain\",\"function\"],\"display_name\":\"ConversationChain\",\"documentation\":\"\"},\"id\":\"ConversationChain-bVNex\",\"value\":null},\"selected\":false,\"dragging\":false,\"positionAbsolute\":{\"x\":806,\"y\":554}}],\"edges\":[{\"source\":\"ChatOpenAI-fBcfh\",\"sourceHandle\":\"{œbaseClassesœ:[œBaseChatModelœ,œBaseLanguageModelœ,œChatOpenAIœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-fBcfhœ}\",\"target\":\"ConversationChain-bVNex\",\"targetHandle\":\"{œfieldNameœ:œllmœ,œidœ:œConversationChain-bVNexœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\",\"className\":\"stroke-gray-900 stroke-connection\",\"id\":\"reactflow__edge-ChatOpenAI-fBcfh{œbaseClassesœ:[œBaseChatModelœ,œBaseLanguageModelœ,œChatOpenAIœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-fBcfhœ}-ConversationChain-bVNex{œfieldNameœ:œllmœ,œidœ:œConversationChain-bVNexœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\",\"data\":{\"sourceHandle\":{\"baseClasses\":[\"BaseChatModel\",\"BaseLanguageModel\",\"ChatOpenAI\",\"BaseLLM\"],\"dataType\":\"ChatOpenAI\",\"id\":\"ChatOpenAI-fBcfh\"},\"targetHandle\":{\"fieldName\":\"llm\",\"id\":\"ConversationChain-bVNex\",\"inputTypes\":null,\"type\":\"BaseLanguageModel\"}},\"style\":{\"stroke\":\"#555\"},\"animated\":false}],\"viewport\":{\"x\":-118.21416568593895,\"y\":-240.64815770363373,\"zoom\":0.7642485855675408}},\"is_component\":false,\"updated_at\":\"2023-12-04T22:57:55.879806\",\"folder\":null,\"id\":\"bddebeea-b80a-4b28-8895-c4425687dcce\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Directory Loader\",\"description\":\"Generic File Loader\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"import os\\n\\nfrom langchain.schema import Document\\nfrom langflow import CustomComponent\\nimport glob\\n\\nclass DirectoryLoaderComponent(CustomComponent):\\n display_name: str = \\\"Directory Loader\\\"\\n description: str = \\\"Generic File Loader\\\"\\n beta = True\\n loaders_info = [\\n {\\n \\\"loader\\\": \\\"AirbyteJSONLoader\\\",\\n \\\"name\\\": \\\"Airbyte JSON (.jsonl)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.AirbyteJSONLoader\\\",\\n \\\"defaultFor\\\": [\\\"jsonl\\\"],\\n \\\"allowdTypes\\\": [\\\"jsonl\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"JSONLoader\\\",\\n \\\"name\\\": \\\"JSON (.json)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.JSONLoader\\\",\\n \\\"defaultFor\\\": [\\\"json\\\"],\\n \\\"allowdTypes\\\": [\\\"json\\\"],\\n \\\"kwargs\\\": {\\\"jq_schema\\\": \\\".\\\", \\\"text_content\\\": False}\\n },\\n {\\n \\\"loader\\\": \\\"BSHTMLLoader\\\",\\n \\\"name\\\": \\\"BeautifulSoup4 HTML (.html, .htm)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.BSHTMLLoader\\\",\\n \\\"allowdTypes\\\": [\\\"html\\\", \\\"htm\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"CSVLoader\\\",\\n \\\"name\\\": \\\"CSV (.csv)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.CSVLoader\\\",\\n \\\"defaultFor\\\": [\\\"csv\\\"],\\n \\\"allowdTypes\\\": [\\\"csv\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"CoNLLULoader\\\",\\n \\\"name\\\": \\\"CoNLL-U (.conllu)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.CoNLLULoader\\\",\\n \\\"defaultFor\\\": [\\\"conllu\\\"],\\n \\\"allowdTypes\\\": [\\\"conllu\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"EverNoteLoader\\\",\\n \\\"name\\\": \\\"EverNote (.enex)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.EverNoteLoader\\\",\\n \\\"defaultFor\\\": [\\\"enex\\\"],\\n \\\"allowdTypes\\\": [\\\"enex\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"FacebookChatLoader\\\",\\n \\\"name\\\": \\\"Facebook Chat (.json)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.FacebookChatLoader\\\",\\n \\\"allowdTypes\\\": [\\\"json\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"OutlookMessageLoader\\\",\\n \\\"name\\\": \\\"Outlook Message (.msg)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.OutlookMessageLoader\\\",\\n \\\"defaultFor\\\": [\\\"msg\\\"],\\n \\\"allowdTypes\\\": [\\\"msg\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"PyPDFLoader\\\",\\n \\\"name\\\": \\\"PyPDF (.pdf)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.PyPDFLoader\\\",\\n \\\"defaultFor\\\": [\\\"pdf\\\"],\\n \\\"allowdTypes\\\": [\\\"pdf\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"STRLoader\\\",\\n \\\"name\\\": \\\"Subtitle (.str)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.STRLoader\\\",\\n \\\"defaultFor\\\": [\\\"str\\\"],\\n \\\"allowdTypes\\\": [\\\"str\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"TextLoader\\\",\\n \\\"name\\\": \\\"Text (.txt)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.TextLoader\\\",\\n \\\"defaultFor\\\": [\\\"txt\\\"],\\n \\\"allowdTypes\\\": [\\\"txt\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"UnstructuredEmailLoader\\\",\\n \\\"name\\\": \\\"Unstructured Email (.eml)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.UnstructuredEmailLoader\\\",\\n \\\"defaultFor\\\": [\\\"eml\\\"],\\n \\\"allowdTypes\\\": [\\\"eml\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"UnstructuredHTMLLoader\\\",\\n \\\"name\\\": \\\"Unstructured HTML (.html, .htm)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.UnstructuredHTMLLoader\\\",\\n \\\"defaultFor\\\": [\\\"html\\\", \\\"htm\\\"],\\n \\\"allowdTypes\\\": [\\\"html\\\", \\\"htm\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"UnstructuredMarkdownLoader\\\",\\n \\\"name\\\": \\\"Unstructured Markdown (.md)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.UnstructuredMarkdownLoader\\\",\\n \\\"defaultFor\\\": [\\\"md\\\"],\\n \\\"allowdTypes\\\": [\\\"md\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"UnstructuredPowerPointLoader\\\",\\n \\\"name\\\": \\\"Unstructured PowerPoint (.pptx)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.UnstructuredPowerPointLoader\\\",\\n \\\"defaultFor\\\": [\\\"pptx\\\"],\\n \\\"allowdTypes\\\": [\\\"pptx\\\"],\\n },\\n {\\n \\\"loader\\\": \\\"UnstructuredWordLoader\\\",\\n \\\"name\\\": \\\"Unstructured Word (.docx)\\\",\\n \\\"import\\\": \\\"langchain.document_loaders.UnstructuredWordLoader\\\",\\n \\\"defaultFor\\\": [\\\"docx\\\"],\\n \\\"allowdTypes\\\": [\\\"docx\\\"],\\n },\\n]\\n\\n\\n def build_config(self):\\n loader_options = [\\\"Automatic\\\"] + [\\n loader_info[\\\"name\\\"] for loader_info in self.loaders_info\\n ]\\n\\n file_types = []\\n suffixes = []\\n\\n for loader_info in self.loaders_info:\\n if \\\"allowedTypes\\\" in loader_info:\\n file_types.extend(loader_info[\\\"allowedTypes\\\"])\\n suffixes.extend([f\\\".{ext}\\\" for ext in loader_info[\\\"allowedTypes\\\"]])\\n\\n return {\\n \\\"directory_path\\\": {\\n \\\"display_name\\\": \\\"Directory Path\\\",\\n \\\"required\\\": True,\\n },\\n \\\"loader\\\": {\\n \\\"display_name\\\": \\\"Loader\\\",\\n \\\"is_list\\\": True,\\n \\\"required\\\": True,\\n \\\"options\\\": loader_options,\\n \\\"value\\\": \\\"Automatic\\\",\\n },\\n }\\n\\n def build(self, directory_path: str, loader: str) -> Document:\\n # Verifique se o diretório existe\\n if not os.path.exists(directory_path):\\n raise ValueError(f\\\"Directory not found: {directory_path}\\\")\\n\\n files = glob.glob(directory_path + \\\"/*.*\\\")\\n\\n\\n loader_info = None\\n if loader == \\\"Automatic\\\":\\n for file in files:\\n file_type = file.split(\\\".\\\")[-1]\\n\\n\\n for info in self.loaders_info:\\n if \\\"defaultFor\\\" in info:\\n if file_type in info[\\\"defaultFor\\\"]:\\n loader_info = info\\n break\\n if loader_info:\\n break\\n\\n if not loader_info:\\n raise ValueError(\\n \\\"No default loader found for any file in the directory\\\"\\n )\\n\\n else:\\n for info in self.loaders_info:\\n if info[\\\"name\\\"] == loader:\\n loader_info = info\\n break\\n\\n if not loader_info:\\n raise ValueError(f\\\"Loader {loader} not found in the loader info list\\\")\\n\\n loader_import = loader_info[\\\"import\\\"]\\n module_name, class_name = loader_import.rsplit(\\\".\\\", 1)\\n\\n try:\\n # Importe o loader dinamicamente\\n loader_module = __import__(module_name, fromlist=[class_name])\\n loader_instance = getattr(loader_module, class_name)\\n except ImportError as e:\\n raise ValueError(\\n f\\\"Loader {loader} could not be imported\\\\nLoader info:\\\\n{loader_info}\\\"\\n ) from e\\n\\n results = []\\n for file in files:\\n file_path = os.path.join(directory_path, file)\\n kwargs = loader_info.get(\\\"kwargs\\\", {})\\n result = loader_instance(file_path=file_path, **kwargs).load()\\n results.append(result)\\n self.status = results\\n return results\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"directory_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"directory_path\",\"display_name\":\"Directory Path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"/Users/ogabrielluiz/Projects/langflow2/docs\"},\"loader\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"Automatic\",\"password\":false,\"options\":[\"Automatic\",\"Airbyte JSON (.jsonl)\",\"JSON (.json)\",\"BeautifulSoup4 HTML (.html, .htm)\",\"CSV (.csv)\",\"CoNLL-U (.conllu)\",\"EverNote (.enex)\",\"Facebook Chat (.json)\",\"Outlook Message (.msg)\",\"PyPDF (.pdf)\",\"Subtitle (.str)\",\"Text (.txt)\",\"Unstructured Email (.eml)\",\"Unstructured HTML (.html, .htm)\",\"Unstructured Markdown (.md)\",\"Unstructured PowerPoint (.pptx)\",\"Unstructured Word (.docx)\"],\"name\":\"loader\",\"display_name\":\"Loader\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true}},\"description\":\"Generic File Loader\",\"base_classes\":[\"Document\"],\"display_name\":\"Directory Loader\",\"custom_fields\":{\"directory_path\":null,\"loader\":null},\"output_types\":[\"Document\"],\"documentation\":\"\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"CustomComponent-Ip6tG\"},\"id\":\"CustomComponent-Ip6tG\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-04T22:58:38.570303\",\"folder\":null,\"id\":\"5fe4debc-b6a7-45d4-a694-c02d8aa93b08\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Whisper Transcriber\",\"description\":\"Converts audio to text using OpenAI's Whisper.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom typing import Optional, List, Dict, Union\\nfrom langflow.field_typing import (\\n AgentExecutor,\\n BaseChatMemory,\\n BaseLanguageModel,\\n BaseLLM,\\n BaseLoader,\\n BaseMemory,\\n BaseOutputParser,\\n BasePromptTemplate,\\n BaseRetriever,\\n Callable,\\n Chain,\\n ChatPromptTemplate,\\n Data,\\n Document,\\n Embeddings,\\n NestedDict,\\n Object,\\n PromptTemplate,\\n TextSplitter,\\n Tool,\\n VectorStore,\\n)\\n\\nfrom openai import OpenAI\\nclass Component(CustomComponent):\\n display_name: str = \\\"Whisper Transcriber\\\"\\n description: str = \\\"Converts audio to text using OpenAI's Whisper.\\\"\\n\\n def build_config(self):\\n return {\\\"audio\\\":{\\\"field_type\\\":\\\"file\\\",\\\"suffixes\\\":[\\\".mp3\\\", \\\".mp4\\\", \\\".m4a\\\"]},\\\"OpenAIKey\\\":{\\\"field_type\\\":\\\"str\\\",\\\"password\\\":True}}\\n\\n def build(self, audio:str, OpenAIKey:str) -> str:\\n \\n # TODO: if output path, persist & load it instead\\n \\n client = OpenAI(api_key=OpenAIKey)\\n \\n audio_file= open(audio, \\\"rb\\\")\\n transcript = client.audio.transcriptions.create(\\n model=\\\"whisper-1\\\", \\n file=audio_file,\\n response_format=\\\"text\\\"\\n )\\n \\n \\n self.status = transcript\\n return transcript\\n\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"OpenAIKey\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"OpenAIKey\",\"display_name\":\"OpenAIKey\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"},\"audio\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"suffixes\":[\".mp3\",\".mp4\",\".m4a\"],\"password\":false,\"name\":\"audio\",\"display_name\":\"audio\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"file_path\":\"/Users/rodrigonader/Library/Caches/langflow/19b3e1c9-90bf-405f-898a-e982f47adf76/a3308ce7e9b10088fcd985aabb6d17b012c6b6e81ff8806356574474c9d10229.m4a\",\"value\":\"Audio Recording 2023-11-29 at 12.12.04.m4a\"}},\"description\":\"Converts audio to text using OpenAI's Whisper.\",\"base_classes\":[\"str\"],\"display_name\":\"Whisper Transcriber\",\"custom_fields\":{\"OpenAIKey\":null,\"audio\":null},\"output_types\":[\"str\"],\"documentation\":\"\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"CustomComponent-GJRrs\"},\"id\":\"CustomComponent-GJRrs\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-04T22:58:39.710502\",\"folder\":null,\"id\":\"bd9e911d-46bd-429f-aa75-dd740430695e\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Youtube Conversation\",\"description\":\"Craft Meaningful Interactions, Generate Value.\",\"data\":{\"nodes\":[{\"width\":384,\"height\":589,\"id\":\"CustomComponent-h0NSI\",\"type\":\"genericNode\",\"position\":{\"x\":714.9531293402755,\"y\":0.4994374160582993},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"import requests\\nfrom langflow import CustomComponent\\nfrom langchain.llms.base import BaseLLM\\nfrom langchain.schema import Document\\nfrom langchain.document_loaders import YoutubeLoader\\n\\n# Example usage:\\n\\nclass YourComponent(CustomComponent):\\n display_name: str = \\\"YouTube Transcript\\\"\\n description: str = \\\"YouTube transcripts refer to the written text versions of the spoken content in a video uploaded to the YouTube platform.\\\"\\n\\n def build_config(self):\\n return {\\\"url\\\": {\\\"multiline\\\": True, \\\"required\\\": True}}\\n\\n def build(self, url: str, llm: BaseLLM, dependencies: Document, language: str = \\\"en\\\") -> Document:\\n dependencies\\n response = requests.get(url)\\n loader = YoutubeLoader.from_youtube_url(url, add_video_info=True, language=[language])\\n result = loader.load()\\n self.repr_value = str(result)\\n return result\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"dependencies\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"dependencies\",\"display_name\":\"dependencies\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Document\",\"list\":false},\"language\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"en\",\"password\":false,\"name\":\"language\",\"display_name\":\"language\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLLM\",\"list\":false},\"url\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"password\":false,\"name\":\"url\",\"display_name\":\"url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"YouTube transcripts refer to the written text versions of the spoken content in a video uploaded to the YouTube platform.\",\"base_classes\":[\"Document\"],\"display_name\":\"YouTube Transcript\",\"custom_fields\":{\"dependencies\":null,\"language\":null,\"llm\":null,\"url\":null},\"output_types\":[\"Document\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-h0NSI\"},\"selected\":false,\"dragging\":false,\"positionAbsolute\":{\"x\":714.9531293402755,\"y\":0.4994374160582993}},{\"width\":384,\"height\":629,\"id\":\"ChatOpenAI-q61Y2\",\"type\":\"genericNode\",\"position\":{\"x\":18,\"y\":625.5521045590924},\"data\":{\"type\":\"ChatOpenAI\",\"node\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":true},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":6,\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"max_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"max_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false,\"value\":\"\"},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"gpt-3.5-turbo-16k\",\"password\":false,\"options\":[\"gpt-3.5-turbo-0613\",\"gpt-3.5-turbo\",\"gpt-3.5-turbo-16k-0613\",\"gpt-3.5-turbo-16k\",\"gpt-4-0613\",\"gpt-4-32k-0613\",\"gpt-4\",\"gpt-4-32k\"],\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"n\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"n\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":false,\"dynamic\":false,\"info\":\"\\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\\n\",\"type\":\"str\",\"list\":false},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":0.7,\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ChatOpenAI\"},\"description\":\"`OpenAI` Chat large language models API.\",\"base_classes\":[\"ChatOpenAI\",\"BaseChatModel\",\"BaseLanguageModel\",\"BaseLLM\"],\"display_name\":\"ChatOpenAI\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai\",\"beta\":false,\"error\":null},\"id\":\"ChatOpenAI-q61Y2\"},\"selected\":false,\"positionAbsolute\":{\"x\":18,\"y\":625.5521045590924},\"dragging\":false},{\"width\":384,\"height\":539,\"id\":\"Chroma-gVhy7\",\"type\":\"genericNode\",\"position\":{\"x\":2110.365967257855,\"y\":805.0149521868784},\"data\":{\"type\":\"Chroma\",\"node\":{\"template\":{\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"chromadb.Client\",\"list\":false},\"client_settings\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client_settings\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"chromadb.config.Setting\",\"list\":true},\"documents\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Document\",\"list\":true},\"embedding\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Embeddings\",\"list\":false},\"chroma_server_cors_allow_origins\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"chroma_server_cors_allow_origins\",\"display_name\":\"Chroma Server CORS Allow Origins\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"chroma_server_grpc_port\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"chroma_server_grpc_port\",\"display_name\":\"Chroma Server GRPC Port\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"chroma_server_host\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"chroma_server_host\",\"display_name\":\"Chroma Server Host\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"chroma_server_http_port\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"chroma_server_http_port\",\"display_name\":\"Chroma Server HTTP Port\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"chroma_server_ssl_enabled\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"chroma_server_ssl_enabled\",\"display_name\":\"Chroma Server SSL Enabled\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"collection_metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"collection_metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"collection_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"langchain\",\"password\":false,\"name\":\"collection_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"ids\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"ids\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"metadatas\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadatas\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":true},\"persist\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"persist\",\"display_name\":\"Persist\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"persist_directory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"persist_directory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"search_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"{}\",\"password\":false,\"name\":\"search_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"NestedDict\",\"list\":false},\"_type\":\"Chroma\"},\"description\":\"Create a Chroma vectorstore from a raw documents.\",\"base_classes\":[\"VectorStore\",\"Chroma\",\"BaseRetriever\",\"VectorStoreRetriever\"],\"display_name\":\"Chroma\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/chroma\",\"beta\":false,\"error\":null},\"id\":\"Chroma-gVhy7\"},\"selected\":false,\"positionAbsolute\":{\"x\":2110.365967257855,\"y\":805.0149521868784},\"dragging\":false},{\"width\":384,\"height\":501,\"id\":\"RecursiveCharacterTextSplitter-1eaOX\",\"type\":\"genericNode\",\"position\":{\"x\":1409.2872773444874,\"y\":19.45456141103284},\"data\":{\"type\":\"RecursiveCharacterTextSplitter\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Optional\\nfrom langflow import CustomComponent\\nfrom langchain.schema import Document\\nfrom langflow.utils.util import build_loader_repr_from_documents\\n\\n\\nclass RecursiveCharacterTextSplitterComponent(CustomComponent):\\n display_name: str = \\\"Recursive Character Text Splitter\\\"\\n description: str = \\\"Split text into chunks of a specified length.\\\"\\n documentation: str = \\\"https://docs.langflow.org/components/text-splitters#recursivecharactertextsplitter\\\"\\n\\n def build_config(self):\\n return {\\n \\\"documents\\\": {\\n \\\"display_name\\\": \\\"Documents\\\",\\n \\\"info\\\": \\\"The documents to split.\\\",\\n },\\n \\\"separators\\\": {\\n \\\"display_name\\\": \\\"Separators\\\",\\n \\\"info\\\": 'The characters to split on.\\\\nIf left empty defaults to [\\\"\\\\\\\\n\\\\\\\\n\\\", \\\"\\\\\\\\n\\\", \\\" \\\", \\\"\\\"].',\\n \\\"is_list\\\": True,\\n },\\n \\\"chunk_size\\\": {\\n \\\"display_name\\\": \\\"Chunk Size\\\",\\n \\\"info\\\": \\\"The maximum length of each chunk.\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"value\\\": 1000,\\n },\\n \\\"chunk_overlap\\\": {\\n \\\"display_name\\\": \\\"Chunk Overlap\\\",\\n \\\"info\\\": \\\"The amount of overlap between chunks.\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"value\\\": 200,\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n documents: list[Document],\\n separators: Optional[list[str]] = None,\\n chunk_size: Optional[int] = 1000,\\n chunk_overlap: Optional[int] = 200,\\n ) -> list[Document]:\\n \\\"\\\"\\\"\\n Split text into chunks of a specified length.\\n\\n Args:\\n separators (list[str]): The characters to split on.\\n chunk_size (int): The maximum length of each chunk.\\n chunk_overlap (int): The amount of overlap between chunks.\\n length_function (function): The function to use to calculate the length of the text.\\n\\n Returns:\\n list[str]: The chunks of text.\\n \\\"\\\"\\\"\\n from langchain.text_splitter import RecursiveCharacterTextSplitter\\n\\n if separators == \\\"\\\":\\n separators = None\\n elif separators:\\n # check if the separators list has escaped characters\\n # if there are escaped characters, unescape them\\n separators = [x.encode().decode(\\\"unicode-escape\\\") for x in separators]\\n\\n # Make sure chunk_size and chunk_overlap are ints\\n if isinstance(chunk_size, str):\\n chunk_size = int(chunk_size)\\n if isinstance(chunk_overlap, str):\\n chunk_overlap = int(chunk_overlap)\\n splitter = RecursiveCharacterTextSplitter(\\n separators=separators,\\n chunk_size=chunk_size,\\n chunk_overlap=chunk_overlap,\\n )\\n\\n docs = splitter.split_documents(documents)\\n self.repr_value = build_loader_repr_from_documents(docs)\\n return docs\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"chunk_overlap\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"50\",\"password\":false,\"name\":\"chunk_overlap\",\"display_name\":\"Chunk Overlap\",\"advanced\":false,\"dynamic\":false,\"info\":\"The amount of overlap between chunks.\",\"type\":\"int\",\"list\":false},\"chunk_size\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"400\",\"password\":false,\"name\":\"chunk_size\",\"display_name\":\"Chunk Size\",\"advanced\":false,\"dynamic\":false,\"info\":\"The maximum length of each chunk.\",\"type\":\"int\",\"list\":false},\"documents\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"The documents to split.\",\"type\":\"Document\",\"list\":true},\"separators\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"separators\",\"display_name\":\"Separators\",\"advanced\":false,\"dynamic\":false,\"info\":\"The characters to split on.\\nIf left empty defaults to [\\\"\\\\n\\\\n\\\", \\\"\\\\n\\\", \\\" \\\", \\\"\\\"].\",\"type\":\"str\",\"list\":true,\"value\":[\" \"]}},\"description\":\"Split text into chunks of a specified length.\",\"base_classes\":[\"Document\"],\"display_name\":\"Recursive Character Text Splitter\",\"custom_fields\":{\"chunk_overlap\":null,\"chunk_size\":null,\"documents\":null,\"separators\":null},\"output_types\":[\"RecursiveCharacterTextSplitter\"],\"documentation\":\"https://docs.langflow.org/components/text-splitters#recursivecharactertextsplitter\",\"beta\":true,\"error\":null},\"id\":\"RecursiveCharacterTextSplitter-1eaOX\"},\"selected\":false,\"positionAbsolute\":{\"x\":1409.2872773444874,\"y\":19.45456141103284},\"dragging\":false},{\"width\":384,\"height\":367,\"id\":\"OpenAIEmbeddings-cduOO\",\"type\":\"genericNode\",\"position\":{\"x\":1405.1176670984544,\"y\":1029.459061269321},\"data\":{\"type\":\"OpenAIEmbeddings\",\"node\":{\"template\":{\"allowed_special\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[],\"password\":false,\"name\":\"allowed_special\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Literal'all'\",\"list\":true},\"disallowed_special\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"all\",\"password\":false,\"name\":\"disallowed_special\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Literal'all'\",\"list\":true},\"chunk_size\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":1000,\"password\":false,\"name\":\"chunk_size\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"deployment\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"text-embedding-ada-002\",\"password\":false,\"name\":\"deployment\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"embedding_ctx_length\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":8191,\"password\":false,\"name\":\"embedding_ctx_length\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"headers\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"{'Authorization': 'Bearer '}\",\"password\":false,\"name\":\"headers\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":6,\"password\":false,\"name\":\"max_retries\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"model\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"text-embedding-ada-002\",\"password\":false,\"name\":\"model\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_api_type\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"openai_api_type\",\"display_name\":\"OpenAI API Type\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"},\"openai_api_version\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"openai_api_version\",\"display_name\":\"OpenAI API Version\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"show_progress_bar\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"show_progress_bar\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"skip_empty\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"skip_empty\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"},\"_type\":\"OpenAIEmbeddings\"},\"description\":\"OpenAI embedding models.\",\"base_classes\":[\"Embeddings\",\"OpenAIEmbeddings\"],\"display_name\":\"OpenAIEmbeddings\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/openai\",\"beta\":false,\"error\":null},\"id\":\"OpenAIEmbeddings-cduOO\"},\"selected\":false,\"positionAbsolute\":{\"x\":1405.1176670984544,\"y\":1029.459061269321}},{\"width\":384,\"height\":339,\"id\":\"RetrievalQA-4PmTB\",\"type\":\"genericNode\",\"position\":{\"x\":2711.7786966415715,\"y\":709.4450828605463},\"data\":{\"type\":\"RetrievalQA\",\"node\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":true},\"combine_documents_chain\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"combine_documents_chain\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseCombineDocumentsChain\",\"list\":false},\"memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseMemory\",\"list\":false},\"retriever\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"retriever\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseRetriever\",\"list\":false},\"input_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"query\",\"password\":false,\"name\":\"input_key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"output_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"result\",\"password\":false,\"name\":\"output_key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"return_source_documents\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":true,\"password\":false,\"name\":\"return_source_documents\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"RetrievalQA\"},\"description\":\"Chain for question-answering against an index.\",\"base_classes\":[\"RetrievalQA\",\"Chain\",\"BaseRetrievalQA\",\"function\"],\"display_name\":\"RetrievalQA\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/chains/popular/vector_db_qa\",\"beta\":false,\"error\":null},\"id\":\"RetrievalQA-4PmTB\"},\"selected\":false,\"positionAbsolute\":{\"x\":2711.7786966415715,\"y\":709.4450828605463}},{\"width\":384,\"height\":333,\"id\":\"CombineDocsChain-yk0JF\",\"type\":\"genericNode\",\"position\":{\"x\":2125.6202053356537,\"y\":199.07708924409633},\"data\":{\"type\":\"CombineDocsChain\",\"node\":{\"template\":{\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"chain_type\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"stuff\",\"password\":false,\"options\":[\"stuff\",\"map_reduce\",\"map_rerank\",\"refine\"],\"name\":\"chain_type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"_type\":\"load_qa_chain\"},\"description\":\"Load question answering chain.\",\"base_classes\":[\"BaseCombineDocumentsChain\",\"function\"],\"display_name\":\"CombineDocsChain\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"id\":\"CombineDocsChain-yk0JF\"},\"selected\":false,\"positionAbsolute\":{\"x\":2125.6202053356537,\"y\":199.07708924409633},\"dragging\":false},{\"width\":384,\"height\":417,\"id\":\"CustomComponent-y6Wg0\",\"type\":\"genericNode\",\"position\":{\"x\":39.400034102832365,\"y\":-499.03551482195707},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\n\\nimport subprocess\\n\\nfrom langchain.llms.base import BaseLLM\\nfrom langchain.chains import LLMChain\\nfrom langchain.prompts import PromptTemplate\\nfrom langchain.schema import Document\\n\\nfrom typing import List\\n\\n\\nclass YourComponent(CustomComponent):\\n display_name: str = \\\"PIP Install\\\"\\n description: str = \\\"Create any custom component you want!\\\"\\n\\n def build(self, libs: List[str]) -> Document:\\n def install_package(package_name):\\n subprocess.check_call([\\\"pip\\\", \\\"install\\\", package_name])\\n for lib in libs:\\n install_package(lib)\\n return \\\"\\\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"libs\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"libs\",\"display_name\":\"libs\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true,\"value\":[\"requests\",\"pytube\"]}},\"description\":\"Create any custom component you want!\",\"base_classes\":[\"Document\"],\"display_name\":\"PIP Install\",\"custom_fields\":{\"libs\":null},\"output_types\":[],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-y6Wg0\"},\"selected\":false,\"dragging\":false,\"positionAbsolute\":{\"x\":39.400034102832365,\"y\":-499.03551482195707}}],\"edges\":[{\"source\":\"ChatOpenAI-q61Y2\",\"sourceHandle\":\"{œbaseClassesœ:[œChatOpenAIœ,œBaseChatModelœ,œBaseLanguageModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-q61Y2œ}\",\"target\":\"CustomComponent-h0NSI\",\"targetHandle\":\"{œfieldNameœ:œllmœ,œidœ:œCustomComponent-h0NSIœ,œinputTypesœ:null,œtypeœ:œBaseLLMœ}\",\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-ChatOpenAI-q61Y2{œbaseClassesœ:[œChatOpenAIœ,œBaseChatModelœ,œBaseLanguageModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-q61Y2œ}-CustomComponent-h0NSI{œfieldNameœ:œllmœ,œidœ:œCustomComponent-h0NSIœ,œinputTypesœ:null,œtypeœ:œBaseLLMœ}\",\"data\":{\"sourceHandle\":{\"baseClasses\":[\"ChatOpenAI\",\"BaseChatModel\",\"BaseLanguageModel\",\"BaseLLM\"],\"dataType\":\"ChatOpenAI\",\"id\":\"ChatOpenAI-q61Y2\"},\"targetHandle\":{\"fieldName\":\"llm\",\"id\":\"CustomComponent-h0NSI\",\"inputTypes\":null,\"type\":\"BaseLLM\"}}},{\"source\":\"CustomComponent-y6Wg0\",\"sourceHandle\":\"{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-y6Wg0œ}\",\"target\":\"CustomComponent-h0NSI\",\"targetHandle\":\"{œfieldNameœ:œdependenciesœ,œidœ:œCustomComponent-h0NSIœ,œinputTypesœ:null,œtypeœ:œDocumentœ}\",\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-y6Wg0{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-y6Wg0œ}-CustomComponent-h0NSI{œfieldNameœ:œdependenciesœ,œidœ:œCustomComponent-h0NSIœ,œinputTypesœ:null,œtypeœ:œDocumentœ}\",\"data\":{\"sourceHandle\":{\"baseClasses\":[\"Document\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-y6Wg0\"},\"targetHandle\":{\"fieldName\":\"dependencies\",\"id\":\"CustomComponent-h0NSI\",\"inputTypes\":null,\"type\":\"Document\"}}},{\"source\":\"CustomComponent-h0NSI\",\"sourceHandle\":\"{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-h0NSIœ}\",\"target\":\"RecursiveCharacterTextSplitter-1eaOX\",\"targetHandle\":\"{œfieldNameœ:œdocumentsœ,œidœ:œRecursiveCharacterTextSplitter-1eaOXœ,œinputTypesœ:null,œtypeœ:œDocumentœ}\",\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-h0NSI{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-h0NSIœ}-RecursiveCharacterTextSplitter-1eaOX{œfieldNameœ:œdocumentsœ,œidœ:œRecursiveCharacterTextSplitter-1eaOXœ,œinputTypesœ:null,œtypeœ:œDocumentœ}\",\"data\":{\"sourceHandle\":{\"baseClasses\":[\"Document\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-h0NSI\"},\"targetHandle\":{\"fieldName\":\"documents\",\"id\":\"RecursiveCharacterTextSplitter-1eaOX\",\"inputTypes\":null,\"type\":\"Document\"}},\"selected\":false},{\"source\":\"OpenAIEmbeddings-cduOO\",\"sourceHandle\":\"{œbaseClassesœ:[œEmbeddingsœ,œOpenAIEmbeddingsœ],œdataTypeœ:œOpenAIEmbeddingsœ,œidœ:œOpenAIEmbeddings-cduOOœ}\",\"target\":\"Chroma-gVhy7\",\"targetHandle\":\"{œfieldNameœ:œembeddingœ,œidœ:œChroma-gVhy7œ,œinputTypesœ:null,œtypeœ:œEmbeddingsœ}\",\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-OpenAIEmbeddings-cduOO{œbaseClassesœ:[œEmbeddingsœ,œOpenAIEmbeddingsœ],œdataTypeœ:œOpenAIEmbeddingsœ,œidœ:œOpenAIEmbeddings-cduOOœ}-Chroma-gVhy7{œfieldNameœ:œembeddingœ,œidœ:œChroma-gVhy7œ,œinputTypesœ:null,œtypeœ:œEmbeddingsœ}\",\"data\":{\"sourceHandle\":{\"baseClasses\":[\"Embeddings\",\"OpenAIEmbeddings\"],\"dataType\":\"OpenAIEmbeddings\",\"id\":\"OpenAIEmbeddings-cduOO\"},\"targetHandle\":{\"fieldName\":\"embedding\",\"id\":\"Chroma-gVhy7\",\"inputTypes\":null,\"type\":\"Embeddings\"}}},{\"source\":\"RecursiveCharacterTextSplitter-1eaOX\",\"sourceHandle\":\"{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œRecursiveCharacterTextSplitterœ,œidœ:œRecursiveCharacterTextSplitter-1eaOXœ}\",\"target\":\"Chroma-gVhy7\",\"targetHandle\":\"{œfieldNameœ:œdocumentsœ,œidœ:œChroma-gVhy7œ,œinputTypesœ:null,œtypeœ:œDocumentœ}\",\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-RecursiveCharacterTextSplitter-1eaOX{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œRecursiveCharacterTextSplitterœ,œidœ:œRecursiveCharacterTextSplitter-1eaOXœ}-Chroma-gVhy7{œfieldNameœ:œdocumentsœ,œidœ:œChroma-gVhy7œ,œinputTypesœ:null,œtypeœ:œDocumentœ}\",\"data\":{\"sourceHandle\":{\"baseClasses\":[\"Document\"],\"dataType\":\"RecursiveCharacterTextSplitter\",\"id\":\"RecursiveCharacterTextSplitter-1eaOX\"},\"targetHandle\":{\"fieldName\":\"documents\",\"id\":\"Chroma-gVhy7\",\"inputTypes\":null,\"type\":\"Document\"}}},{\"source\":\"ChatOpenAI-q61Y2\",\"sourceHandle\":\"{œbaseClassesœ:[œChatOpenAIœ,œBaseChatModelœ,œBaseLanguageModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-q61Y2œ}\",\"target\":\"CombineDocsChain-yk0JF\",\"targetHandle\":\"{œfieldNameœ:œllmœ,œidœ:œCombineDocsChain-yk0JFœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\",\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-ChatOpenAI-q61Y2{œbaseClassesœ:[œChatOpenAIœ,œBaseChatModelœ,œBaseLanguageModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-q61Y2œ}-CombineDocsChain-yk0JF{œfieldNameœ:œllmœ,œidœ:œCombineDocsChain-yk0JFœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\",\"data\":{\"sourceHandle\":{\"baseClasses\":[\"ChatOpenAI\",\"BaseChatModel\",\"BaseLanguageModel\",\"BaseLLM\"],\"dataType\":\"ChatOpenAI\",\"id\":\"ChatOpenAI-q61Y2\"},\"targetHandle\":{\"fieldName\":\"llm\",\"id\":\"CombineDocsChain-yk0JF\",\"inputTypes\":null,\"type\":\"BaseLanguageModel\"}}},{\"source\":\"CombineDocsChain-yk0JF\",\"sourceHandle\":\"{œbaseClassesœ:[œBaseCombineDocumentsChainœ,œfunctionœ],œdataTypeœ:œCombineDocsChainœ,œidœ:œCombineDocsChain-yk0JFœ}\",\"target\":\"RetrievalQA-4PmTB\",\"targetHandle\":\"{œfieldNameœ:œcombine_documents_chainœ,œidœ:œRetrievalQA-4PmTBœ,œinputTypesœ:null,œtypeœ:œBaseCombineDocumentsChainœ}\",\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CombineDocsChain-yk0JF{œbaseClassesœ:[œBaseCombineDocumentsChainœ,œfunctionœ],œdataTypeœ:œCombineDocsChainœ,œidœ:œCombineDocsChain-yk0JFœ}-RetrievalQA-4PmTB{œfieldNameœ:œcombine_documents_chainœ,œidœ:œRetrievalQA-4PmTBœ,œinputTypesœ:null,œtypeœ:œBaseCombineDocumentsChainœ}\",\"data\":{\"sourceHandle\":{\"baseClasses\":[\"BaseCombineDocumentsChain\",\"function\"],\"dataType\":\"CombineDocsChain\",\"id\":\"CombineDocsChain-yk0JF\"},\"targetHandle\":{\"fieldName\":\"combine_documents_chain\",\"id\":\"RetrievalQA-4PmTB\",\"inputTypes\":null,\"type\":\"BaseCombineDocumentsChain\"}}},{\"source\":\"Chroma-gVhy7\",\"sourceHandle\":\"{œbaseClassesœ:[œVectorStoreœ,œChromaœ,œBaseRetrieverœ,œVectorStoreRetrieverœ],œdataTypeœ:œChromaœ,œidœ:œChroma-gVhy7œ}\",\"target\":\"RetrievalQA-4PmTB\",\"targetHandle\":\"{œfieldNameœ:œretrieverœ,œidœ:œRetrievalQA-4PmTBœ,œinputTypesœ:null,œtypeœ:œBaseRetrieverœ}\",\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-Chroma-gVhy7{œbaseClassesœ:[œVectorStoreœ,œChromaœ,œBaseRetrieverœ,œVectorStoreRetrieverœ],œdataTypeœ:œChromaœ,œidœ:œChroma-gVhy7œ}-RetrievalQA-4PmTB{œfieldNameœ:œretrieverœ,œidœ:œRetrievalQA-4PmTBœ,œinputTypesœ:null,œtypeœ:œBaseRetrieverœ}\",\"data\":{\"sourceHandle\":{\"baseClasses\":[\"VectorStore\",\"Chroma\",\"BaseRetriever\",\"VectorStoreRetriever\"],\"dataType\":\"Chroma\",\"id\":\"Chroma-gVhy7\"},\"targetHandle\":{\"fieldName\":\"retriever\",\"id\":\"RetrievalQA-4PmTB\",\"inputTypes\":null,\"type\":\"BaseRetriever\"}}}],\"viewport\":{\"x\":189.54413265004274,\"y\":259.89949657174975,\"zoom\":0.291027508374689}},\"is_component\":false,\"updated_at\":\"2023-12-04T22:59:08.830269\",\"folder\":null,\"id\":\"bc7eb94b-6fc6-49cb-9b19-35347ba51afa\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Web Scraper - Content & Links\",\"description\":\"Fetch and parse text and links from a given URL.\",\"data\":{\"nodes\":[{\"width\":384,\"height\":338,\"id\":\"LLMChain-H7PBy\",\"type\":\"genericNode\",\"position\":{\"x\":1682.494010974207,\"y\":275.5701585623092},\"data\":{\"type\":\"LLMChain\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Callable, Optional, Union\\n\\nfrom langchain.chains import LLMChain\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import (\\n BaseLanguageModel,\\n BaseMemory,\\n BasePromptTemplate,\\n Chain,\\n)\\n\\n\\nclass LLMChainComponent(CustomComponent):\\n display_name = \\\"LLMChain\\\"\\n description = \\\"Chain to run queries against LLMs\\\"\\n\\n def build_config(self):\\n return {\\n \\\"prompt\\\": {\\\"display_name\\\": \\\"Prompt\\\"},\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"memory\\\": {\\\"display_name\\\": \\\"Memory\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n prompt: BasePromptTemplate,\\n llm: BaseLanguageModel,\\n memory: Optional[BaseMemory] = None,\\n ) -> Union[Chain, Callable]:\\n return LLMChain(prompt=prompt, llm=llm, memory=memory)\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseMemory\",\"list\":false},\"prompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"prompt\",\"display_name\":\"Prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BasePromptTemplate\",\"list\":false}},\"description\":\"Chain to run queries against LLMs\",\"base_classes\":[\"Chain\",\"Callable\"],\"display_name\":\"LLMChain\",\"custom_fields\":{\"llm\":null,\"memory\":null,\"prompt\":null},\"output_types\":[\"LLMChain\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"LLMChain-H7PBy\"},\"selected\":false,\"positionAbsolute\":{\"x\":1682.494010974207,\"y\":275.5701585623092},\"dragging\":false},{\"width\":384,\"height\":626,\"id\":\"ChatOpenAI-VSAdc\",\"type\":\"genericNode\",\"position\":{\"x\":1002.4263147022411,\"y\":-198.2305006886859},\"data\":{\"type\":\"ChatOpenAI\",\"node\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"list\":true},\"async_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"async_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"default_headers\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"default_query\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_query\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"http_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"http_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":2,\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"max_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"max_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false,\"value\":\"\"},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"gpt-4-1106-preview\",\"password\":false,\"options\":[\"gpt-4-1106-preview\",\"gpt-4\",\"gpt-4-32k\",\"gpt-3.5-turbo\",\"gpt-3.5-turbo-16k\"],\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"n\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"n\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":false,\"dynamic\":false,\"info\":\"\\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\\n\",\"type\":\"str\",\"list\":false},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"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\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"0.1\",\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ChatOpenAI\"},\"description\":\"`OpenAI` Chat large language models API.\",\"base_classes\":[\"BaseLanguageModel\",\"ChatOpenAI\",\"BaseChatModel\",\"BaseLLM\"],\"display_name\":\"ChatOpenAI\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai\",\"beta\":false,\"error\":null},\"id\":\"ChatOpenAI-VSAdc\"},\"selected\":false,\"dragging\":false,\"positionAbsolute\":{\"x\":1002.4263147022411,\"y\":-198.2305006886859}},{\"width\":384,\"height\":374,\"data\":{\"id\":\"GroupNode-WXPMk\",\"type\":\"PromptTemplate\",\"node\":{\"output_types\":[],\"display_name\":\"Web Scraper\",\"documentation\":\"\",\"base_classes\":[\"StringPromptTemplate\",\"BasePromptTemplate\",\"PromptTemplate\"],\"description\":\"Fetch and parse text and links from a given URL.\",\"template\":{\"code_CustomComponent-f6nOg\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport html2text\\n\\nclass ConvertHTMLToMarkdown(CustomComponent):\\n display_name: str = \\\"HTML to Markdown\\\"\\n description: str = \\\"Converts HTML content to Markdown format.\\\"\\n\\n def build(self, html_content: Data, ignore_links: bool = False) -> str:\\n converter = html2text.HTML2Text()\\n converter.ignore_links = ignore_links\\n markdown_text = converter.handle(html_content)\\n self.status = markdown_text\\n return markdown_text\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-f6nOg\",\"field\":\"code\"},\"display_name\":\"Code\"},\"ignore_links_CustomComponent-f6nOg\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"ignore_links\",\"display_name\":\"ignore_links\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-f6nOg\",\"field\":\"ignore_links\"}},\"code_CustomComponent-FGzJJ\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport requests\\n\\nclass FetchHTMLContent(CustomComponent):\\n display_name: str = \\\"Fetch HTML\\\"\\n description: str = \\\"Fetches HTML content from a specified URL.\\\"\\n \\n def build_config(self):\\n return {\\\"url\\\": {\\\"input_types\\\": [\\\"Data\\\", \\\"str\\\"]}} \\n\\n def build(self, url: str) -> Data:\\n response = requests.get(url)\\n self.status = str(response) + \\\"\\\\n\\\\n\\\" + response.text\\n return response.text\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-FGzJJ\",\"field\":\"code\"},\"display_name\":\"Code\"},\"code_CustomComponent-0XtUN\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from bs4 import BeautifulSoup\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Data\\n\\nclass ParseHTMLContent(CustomComponent):\\n display_name: str = \\\"Parse HTML\\\"\\n description: str = \\\"Parses HTML content using Beautiful Soup.\\\"\\n\\n def build(self, html_content: Data) -> Data:\\n soup = BeautifulSoup(html_content, 'html.parser')\\n self.status = soup\\n return soup\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-0XtUN\",\"field\":\"code\"},\"display_name\":\"Code\"},\"code_CustomComponent-ODIcp\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\n\\nclass ExtractHyperlinks(CustomComponent):\\n display_name: str = \\\"Extract Hyperlinks\\\"\\n description: str = \\\"Extracts hyperlinks from parsed HTML content.\\\"\\n\\n def build(self, soup: Data) -> list:\\n links = [link.get('href') for link in soup.find_all('a')]\\n self.status = links\\n return links\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-ODIcp\",\"field\":\"code\"},\"display_name\":\"Code\"},\"output_parser_PromptTemplate-H9Udy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"BaseOutputParser\",\"list\":false,\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"output_parser\"},\"display_name\":\"Output Parser\"},\"input_types_PromptTemplate-H9Udy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_types\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false,\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"input_types\"},\"display_name\":\"Input Types\"},\"input_variables_PromptTemplate-H9Udy\":{\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":true,\"value\":[\"url\",\"html_markdown\",\"html_links\",\"query\"],\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"input_variables\"},\"display_name\":\"Input Variables\"},\"partial_variables_PromptTemplate-H9Udy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"partial_variables\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false,\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"partial_variables\"},\"display_name\":\"Partial Variables\"},\"template_PromptTemplate-H9Udy\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"password\":false,\"name\":\"template\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"type\":\"prompt\",\"list\":false,\"value\":\"Below is the HTML content (as markdown) and hyperlinks extracted from {url}\\n\\n---\\n\\nContent:\\n\\n{html_markdown}\\n\\n---\\n\\nLinks:\\n\\n{html_links}\\n\\n---\\n\\nAnswer the user query as best as possible.\\n\\nUser query:\\n\\n{query}\\n\\nAnswer:\\n\",\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"template\"},\"display_name\":\"Template\"},\"template_format_PromptTemplate-H9Udy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"f-string\",\"password\":false,\"name\":\"template_format\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":false,\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"template_format\"},\"display_name\":\"Template Format\"},\"validate_template_PromptTemplate-H9Udy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"validate_template\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"type\":\"bool\",\"list\":false,\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"validate_template\"},\"display_name\":\"Validate Template\"},\"query_PromptTemplate-H9Udy\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"give me links\",\"password\":false,\"name\":\"query\",\"display_name\":\"query\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"query\"}},\"code_CustomComponent-OACE0\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport requests\\n\\nclass FetchHTMLContent(CustomComponent):\\n display_name: str = \\\"URL Input\\\"\\n\\n def build(self, url: str) -> str:\\n return url\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-OACE0\",\"field\":\"code\"},\"display_name\":\"Code\"},\"url_CustomComponent-OACE0\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"url\",\"display_name\":\"url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-OACE0\",\"field\":\"url\"},\"value\":\"https://paperswithcode.com/\"},\"code_CustomComponent-whsQ5\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\n\\nclass ListToMarkdownBullets(CustomComponent):\\n display_name: str = \\\"List to Bullets\\\"\\n description: str = \\\"Converts a Python list into Markdown bullet points.\\\"\\n\\n def build(self, items: list) -> str:\\n markdown_bullets = '\\\\n'.join(f'* {item}' for item in items)\\n return markdown_bullets\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-whsQ5\",\"field\":\"code\"},\"display_name\":\"Code\"}},\"flow\":{\"data\":{\"nodes\":[{\"width\":384,\"height\":405,\"id\":\"CustomComponent-f6nOg\",\"type\":\"genericNode\",\"position\":{\"x\":665.2835942536854,\"y\":-371.7823429271119},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport html2text\\n\\nclass ConvertHTMLToMarkdown(CustomComponent):\\n display_name: str = \\\"HTML to Markdown\\\"\\n description: str = \\\"Converts HTML content to Markdown format.\\\"\\n\\n def build(self, html_content: Data, ignore_links: bool = False) -> str:\\n converter = html2text.HTML2Text()\\n converter.ignore_links = ignore_links\\n markdown_text = converter.handle(html_content)\\n self.status = markdown_text\\n return markdown_text\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"html_content\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"html_content\",\"display_name\":\"html_content\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Data\",\"list\":false},\"ignore_links\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"ignore_links\",\"display_name\":\"ignore_links\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false}},\"description\":\"Converts HTML content to Markdown format.\",\"base_classes\":[\"str\"],\"display_name\":\"HTML to Markdown\",\"custom_fields\":{\"html_content\":null,\"ignore_links\":null},\"output_types\":[\"str\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-f6nOg\"},\"selected\":true,\"positionAbsolute\":{\"x\":665.2835942536854,\"y\":-371.7823429271119},\"dragging\":false},{\"width\":384,\"height\":375,\"id\":\"CustomComponent-FGzJJ\",\"type\":\"genericNode\",\"position\":{\"x\":-464.4553400967736,\"y\":-225.62715888255525},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport requests\\n\\nclass FetchHTMLContent(CustomComponent):\\n display_name: str = \\\"Fetch HTML\\\"\\n description: str = \\\"Fetches HTML content from a specified URL.\\\"\\n \\n def build_config(self):\\n return {\\\"url\\\": {\\\"input_types\\\": [\\\"Data\\\", \\\"str\\\"]}} \\n\\n def build(self, url: str) -> Data:\\n response = requests.get(url)\\n self.status = str(response) + \\\"\\\\n\\\\n\\\" + response.text\\n return response.text\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"url\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"url\",\"display_name\":\"url\",\"advanced\":false,\"input_types\":[\"Data\",\"str\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"}},\"description\":\"Fetches HTML content from a specified URL.\",\"base_classes\":[\"Data\"],\"display_name\":\"Fetch HTML\",\"custom_fields\":{\"url\":null},\"output_types\":[\"Data\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-FGzJJ\"},\"selected\":true,\"dragging\":false,\"positionAbsolute\":{\"x\":-464.4553400967736,\"y\":-225.62715888255525}},{\"width\":384,\"height\":329,\"id\":\"CustomComponent-0XtUN\",\"type\":\"genericNode\",\"position\":{\"x\":214.00059169497604,\"y\":177.27071061129823},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from bs4 import BeautifulSoup\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Data\\n\\nclass ParseHTMLContent(CustomComponent):\\n display_name: str = \\\"Parse HTML\\\"\\n description: str = \\\"Parses HTML content using Beautiful Soup.\\\"\\n\\n def build(self, html_content: Data) -> Data:\\n soup = BeautifulSoup(html_content, 'html.parser')\\n self.status = soup\\n return soup\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"html_content\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"html_content\",\"display_name\":\"html_content\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Data\",\"list\":false}},\"description\":\"Parses HTML content using Beautiful Soup.\",\"base_classes\":[\"Data\"],\"display_name\":\"Parse HTML\",\"custom_fields\":{\"html_content\":null},\"output_types\":[\"Data\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-0XtUN\"},\"selected\":true,\"dragging\":false,\"positionAbsolute\":{\"x\":214.00059169497604,\"y\":177.27071061129823}},{\"width\":384,\"height\":329,\"id\":\"CustomComponent-ODIcp\",\"type\":\"genericNode\",\"position\":{\"x\":845.0502195222412,\"y\":366.54344452019404},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\n\\nclass ExtractHyperlinks(CustomComponent):\\n display_name: str = \\\"Extract Hyperlinks\\\"\\n description: str = \\\"Extracts hyperlinks from parsed HTML content.\\\"\\n\\n def build(self, soup: Data) -> list:\\n links = [link.get('href') for link in soup.find_all('a')]\\n self.status = links\\n return links\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"soup\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"soup\",\"display_name\":\"soup\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Data\",\"list\":false}},\"description\":\"Extracts hyperlinks from parsed HTML content.\",\"base_classes\":[\"list\"],\"display_name\":\"Extract Hyperlinks\",\"custom_fields\":{\"soup\":null},\"output_types\":[\"list\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-ODIcp\"},\"selected\":true,\"positionAbsolute\":{\"x\":845.0502195222412,\"y\":366.54344452019404},\"dragging\":false},{\"width\":384,\"height\":657,\"id\":\"PromptTemplate-H9Udy\",\"type\":\"genericNode\",\"position\":{\"x\":2230.389721706283,\"y\":584.4905083765256},\"data\":{\"type\":\"PromptTemplate\",\"node\":{\"template\":{\"output_parser\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"BaseOutputParser\",\"list\":false},\"input_types\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_types\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"input_variables\":{\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":true,\"value\":[\"url\",\"html_markdown\",\"html_links\",\"query\"]},\"partial_variables\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"partial_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"template\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"password\":false,\"name\":\"template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"prompt\",\"list\":false,\"value\":\"Below is the HTML content (as markdown) and hyperlinks extracted from {url}\\n\\n---\\n\\nContent:\\n\\n{html_markdown}\\n\\n---\\n\\nLinks:\\n\\n{html_links}\\n\\n---\\n\\nAnswer the user query as best as possible.\\n\\nUser query:\\n\\n{query}\\n\\nAnswer:\\n\"},\"template_format\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"f-string\",\"password\":false,\"name\":\"template_format\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":false},\"validate_template\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"validate_template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"PromptTemplate\",\"url\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"url\",\"display_name\":\"url\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"html_markdown\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"html_markdown\",\"display_name\":\"html_markdown\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"html_links\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"html_links\",\"display_name\":\"html_links\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"query\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"query\",\"display_name\":\"query\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"A prompt template for a language model.\",\"base_classes\":[\"StringPromptTemplate\",\"BasePromptTemplate\",\"PromptTemplate\"],\"name\":\"\",\"display_name\":\"PromptTemplate\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/\",\"custom_fields\":{\"\":[\"url\",\"html_markdown\",\"html_links\",\"query\"]},\"output_types\":[],\"full_path\":null,\"field_formatters\":{},\"beta\":false,\"error\":null},\"id\":\"PromptTemplate-H9Udy\"},\"selected\":true,\"positionAbsolute\":{\"x\":2230.389721706283,\"y\":584.4905083765256},\"dragging\":false},{\"width\":384,\"height\":347,\"id\":\"CustomComponent-OACE0\",\"type\":\"genericNode\",\"position\":{\"x\":-1155.9497945157625,\"y\":198.13583204151553},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport requests\\n\\nclass FetchHTMLContent(CustomComponent):\\n display_name: str = \\\"URL Input\\\"\\n\\n def build(self, url: str) -> str:\\n return url\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"url\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"url\",\"display_name\":\"url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":null,\"base_classes\":[\"str\"],\"display_name\":\"URL Input\",\"custom_fields\":{\"url\":null},\"output_types\":[\"str\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-OACE0\"},\"selected\":true,\"positionAbsolute\":{\"x\":-1155.9497945157625,\"y\":198.13583204151553},\"dragging\":false},{\"width\":384,\"height\":329,\"id\":\"CustomComponent-whsQ5\",\"type\":\"genericNode\",\"position\":{\"x\":1396.5574076376327,\"y\":694.8308714574463},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\n\\nclass ListToMarkdownBullets(CustomComponent):\\n display_name: str = \\\"List to Bullets\\\"\\n description: str = \\\"Converts a Python list into Markdown bullet points.\\\"\\n\\n def build(self, items: list) -> str:\\n markdown_bullets = '\\\\n'.join(f'* {item}' for item in items)\\n return markdown_bullets\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"items\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"items\",\"display_name\":\"items\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"list\",\"list\":true}},\"description\":\"Converts a Python list into Markdown bullet points.\",\"base_classes\":[\"str\"],\"display_name\":\"List to Bullets\",\"custom_fields\":{\"items\":null},\"output_types\":[\"str\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-whsQ5\"},\"selected\":true,\"positionAbsolute\":{\"x\":1396.5574076376327,\"y\":694.8308714574463},\"dragging\":false}],\"edges\":[{\"source\":\"CustomComponent-FGzJJ\",\"sourceHandle\":\"{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-FGzJJœ}\",\"target\":\"CustomComponent-f6nOg\",\"targetHandle\":\"{œfieldNameœ:œhtml_contentœ,œidœ:œCustomComponent-f6nOgœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"html_content\",\"id\":\"CustomComponent-f6nOg\",\"inputTypes\":null,\"type\":\"Data\"},\"sourceHandle\":{\"baseClasses\":[\"Data\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-FGzJJ\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-FGzJJ{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-FGzJJœ}-CustomComponent-f6nOg{œfieldNameœ:œhtml_contentœ,œidœ:œCustomComponent-f6nOgœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"selected\":true},{\"source\":\"CustomComponent-FGzJJ\",\"sourceHandle\":\"{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-FGzJJœ}\",\"target\":\"CustomComponent-0XtUN\",\"targetHandle\":\"{œfieldNameœ:œhtml_contentœ,œidœ:œCustomComponent-0XtUNœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"html_content\",\"id\":\"CustomComponent-0XtUN\",\"inputTypes\":null,\"type\":\"Data\"},\"sourceHandle\":{\"baseClasses\":[\"Data\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-FGzJJ\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-FGzJJ{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-FGzJJœ}-CustomComponent-0XtUN{œfieldNameœ:œhtml_contentœ,œidœ:œCustomComponent-0XtUNœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"selected\":true},{\"source\":\"CustomComponent-0XtUN\",\"sourceHandle\":\"{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-0XtUNœ}\",\"target\":\"CustomComponent-ODIcp\",\"targetHandle\":\"{œfieldNameœ:œsoupœ,œidœ:œCustomComponent-ODIcpœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"soup\",\"id\":\"CustomComponent-ODIcp\",\"inputTypes\":null,\"type\":\"Data\"},\"sourceHandle\":{\"baseClasses\":[\"Data\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-0XtUN\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-0XtUN{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-0XtUNœ}-CustomComponent-ODIcp{œfieldNameœ:œsoupœ,œidœ:œCustomComponent-ODIcpœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"selected\":true},{\"source\":\"CustomComponent-OACE0\",\"sourceHandle\":\"{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-OACE0œ}\",\"target\":\"CustomComponent-FGzJJ\",\"targetHandle\":\"{œfieldNameœ:œurlœ,œidœ:œCustomComponent-FGzJJœ,œinputTypesœ:[œDataœ,œstrœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"url\",\"id\":\"CustomComponent-FGzJJ\",\"inputTypes\":[\"Data\",\"str\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"str\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-OACE0\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-OACE0{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-OACE0œ}-CustomComponent-FGzJJ{œfieldNameœ:œurlœ,œidœ:œCustomComponent-FGzJJœ,œinputTypesœ:[œDataœ,œstrœ],œtypeœ:œstrœ}\",\"selected\":true},{\"source\":\"CustomComponent-OACE0\",\"sourceHandle\":\"{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-OACE0œ}\",\"target\":\"PromptTemplate-H9Udy\",\"targetHandle\":\"{œfieldNameœ:œurlœ,œidœ:œPromptTemplate-H9Udyœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"url\",\"id\":\"PromptTemplate-H9Udy\",\"inputTypes\":[\"Document\",\"BaseOutputParser\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"str\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-OACE0\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-OACE0{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-OACE0œ}-PromptTemplate-H9Udy{œfieldNameœ:œurlœ,œidœ:œPromptTemplate-H9Udyœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"selected\":true},{\"source\":\"CustomComponent-ODIcp\",\"sourceHandle\":\"{œbaseClassesœ:[œlistœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-ODIcpœ}\",\"target\":\"CustomComponent-whsQ5\",\"targetHandle\":\"{œfieldNameœ:œitemsœ,œidœ:œCustomComponent-whsQ5œ,œinputTypesœ:null,œtypeœ:œlistœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"items\",\"id\":\"CustomComponent-whsQ5\",\"inputTypes\":null,\"type\":\"list\"},\"sourceHandle\":{\"baseClasses\":[\"list\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-ODIcp\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-ODIcp{œbaseClassesœ:[œlistœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-ODIcpœ}-CustomComponent-whsQ5{œfieldNameœ:œitemsœ,œidœ:œCustomComponent-whsQ5œ,œinputTypesœ:null,œtypeœ:œlistœ}\",\"selected\":true},{\"source\":\"CustomComponent-whsQ5\",\"sourceHandle\":\"{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-whsQ5œ}\",\"target\":\"PromptTemplate-H9Udy\",\"targetHandle\":\"{œfieldNameœ:œhtml_linksœ,œidœ:œPromptTemplate-H9Udyœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"html_links\",\"id\":\"PromptTemplate-H9Udy\",\"inputTypes\":[\"Document\",\"BaseOutputParser\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"str\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-whsQ5\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-whsQ5{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-whsQ5œ}-PromptTemplate-H9Udy{œfieldNameœ:œhtml_linksœ,œidœ:œPromptTemplate-H9Udyœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"selected\":true},{\"source\":\"CustomComponent-f6nOg\",\"sourceHandle\":\"{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-f6nOgœ}\",\"target\":\"PromptTemplate-H9Udy\",\"targetHandle\":\"{œfieldNameœ:œhtml_markdownœ,œidœ:œPromptTemplate-H9Udyœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"html_markdown\",\"id\":\"PromptTemplate-H9Udy\",\"inputTypes\":[\"Document\",\"BaseOutputParser\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"str\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-f6nOg\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-f6nOg{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-f6nOgœ}-PromptTemplate-H9Udy{œfieldNameœ:œhtml_markdownœ,œidœ:œPromptTemplate-H9Udyœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"selected\":true}],\"viewport\":{\"x\":343.0346131188585,\"y\":341.89843948642147,\"zoom\":0.24148408223121196}},\"is_component\":false,\"name\":\"Fluffy Ptolemy\",\"description\":\"\",\"id\":\"W5oNW\"}}},\"id\":\"GroupNode-WXPMk\",\"position\":{\"x\":873.0737834322758,\"y\":598.8401015776466},\"type\":\"genericNode\",\"selected\":true,\"dragging\":false,\"positionAbsolute\":{\"x\":873.0737834322758,\"y\":598.8401015776466}}],\"edges\":[{\"source\":\"ChatOpenAI-VSAdc\",\"sourceHandle\":\"{œbaseClassesœ:[œBaseLanguageModelœ,œChatOpenAIœ,œBaseChatModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-VSAdcœ}\",\"target\":\"LLMChain-H7PBy\",\"targetHandle\":\"{œfieldNameœ:œllmœ,œidœ:œLLMChain-H7PByœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"llm\",\"id\":\"LLMChain-H7PBy\",\"inputTypes\":null,\"type\":\"BaseLanguageModel\"},\"sourceHandle\":{\"baseClasses\":[\"BaseLanguageModel\",\"ChatOpenAI\",\"BaseChatModel\",\"BaseLLM\"],\"dataType\":\"ChatOpenAI\",\"id\":\"ChatOpenAI-VSAdc\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-ChatOpenAI-VSAdc{œbaseClassesœ:[œBaseLanguageModelœ,œChatOpenAIœ,œBaseChatModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-VSAdcœ}-LLMChain-H7PBy{œfieldNameœ:œllmœ,œidœ:œLLMChain-H7PByœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\"},{\"source\":\"GroupNode-WXPMk\",\"sourceHandle\":\"{œbaseClassesœ:[œStringPromptTemplateœ,œBasePromptTemplateœ,œPromptTemplateœ],œdataTypeœ:œPromptTemplateœ,œidœ:œGroupNode-WXPMkœ}\",\"target\":\"LLMChain-H7PBy\",\"targetHandle\":\"{œfieldNameœ:œpromptœ,œidœ:œLLMChain-H7PByœ,œinputTypesœ:null,œtypeœ:œBasePromptTemplateœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"prompt\",\"id\":\"LLMChain-H7PBy\",\"inputTypes\":null,\"type\":\"BasePromptTemplate\"},\"sourceHandle\":{\"baseClasses\":[\"StringPromptTemplate\",\"BasePromptTemplate\",\"PromptTemplate\"],\"dataType\":\"PromptTemplate\",\"id\":\"GroupNode-WXPMk\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-GroupNode-WXPMk{œbaseClassesœ:[œStringPromptTemplateœ,œBasePromptTemplateœ,œPromptTemplateœ],œdataTypeœ:œPromptTemplateœ,œidœ:œGroupNode-WXPMkœ}-LLMChain-H7PBy{œfieldNameœ:œpromptœ,œidœ:œLLMChain-H7PByœ,œinputTypesœ:null,œtypeœ:œBasePromptTemplateœ}\"}],\"viewport\":{\"x\":-348.6161822813733,\"y\":121.40545291211492,\"zoom\":0.6801854262029781}},\"is_component\":false,\"updated_at\":\"2023-12-04T23:22:27.784647\",\"folder\":null,\"id\":\"efc3bf27-3cf1-4561-9a83-3df347572440\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Sad Joliot\",\"description\":\"Navigate the Networks of Conversation.\",\"data\":{\"nodes\":[{\"width\":384,\"height\":338,\"id\":\"LLMChain-RQsU1\",\"type\":\"genericNode\",\"position\":{\"x\":514.4440482813261,\"y\":528.164086188516},\"data\":{\"type\":\"LLMChain\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Callable, Optional, Union\\n\\nfrom langchain.chains import LLMChain\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import (\\n BaseLanguageModel,\\n BaseMemory,\\n BasePromptTemplate,\\n Chain,\\n)\\n\\n\\nclass LLMChainComponent(CustomComponent):\\n display_name = \\\"LLMChain\\\"\\n description = \\\"Chain to run queries against LLMs\\\"\\n\\n def build_config(self):\\n return {\\n \\\"prompt\\\": {\\\"display_name\\\": \\\"Prompt\\\"},\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"memory\\\": {\\\"display_name\\\": \\\"Memory\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n prompt: BasePromptTemplate,\\n llm: BaseLanguageModel,\\n memory: Optional[BaseMemory] = None,\\n ) -> Union[Chain, Callable]:\\n return LLMChain(prompt=prompt, llm=llm, memory=memory)\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseMemory\",\"list\":false},\"prompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"prompt\",\"display_name\":\"Prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BasePromptTemplate\",\"list\":false}},\"description\":\"Chain to run queries against LLMs\",\"base_classes\":[\"Chain\",\"Callable\"],\"display_name\":\"LLMChain\",\"custom_fields\":{\"llm\":null,\"memory\":null,\"prompt\":null},\"output_types\":[\"LLMChain\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"LLMChain-RQsU1\"},\"selected\":false,\"positionAbsolute\":{\"x\":514.4440482813261,\"y\":528.164086188516}},{\"width\":384,\"height\":626,\"id\":\"ChatOpenAI-NTTcv\",\"type\":\"genericNode\",\"position\":{\"x\":-221.33853765781578,\"y\":-35.48749923706055},\"data\":{\"type\":\"ChatOpenAI\",\"node\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"list\":true},\"async_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"async_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"default_headers\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"default_query\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_query\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"http_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"http_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":2,\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"max_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"max_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"gpt-4-1106-preview\",\"password\":false,\"options\":[\"gpt-4-1106-preview\",\"gpt-4\",\"gpt-4-32k\",\"gpt-3.5-turbo\",\"gpt-3.5-turbo-16k\"],\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"n\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"n\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":false,\"dynamic\":false,\"info\":\"\\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\\n\",\"type\":\"str\",\"list\":false},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"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\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"0.1\",\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ChatOpenAI\"},\"description\":\"`OpenAI` Chat large language models API.\",\"base_classes\":[\"BaseLanguageModel\",\"ChatOpenAI\",\"BaseChatModel\",\"BaseLLM\"],\"display_name\":\"ChatOpenAI\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai\",\"beta\":false,\"error\":null},\"id\":\"ChatOpenAI-NTTcv\"},\"selected\":false,\"positionAbsolute\":{\"x\":-221.33853765781578,\"y\":-35.48749923706055}},{\"width\":384,\"height\":374,\"id\":\"PromptTemplate-VELMV\",\"type\":\"genericNode\",\"position\":{\"x\":-222,\"y\":682.560723386973},\"data\":{\"id\":\"PromptTemplate-VELMV\",\"type\":\"PromptTemplate\",\"node\":{\"output_types\":[],\"display_name\":\"Web Scraper\",\"documentation\":\"\",\"base_classes\":[\"StringPromptTemplate\",\"BasePromptTemplate\",\"PromptTemplate\"],\"description\":\"Fetch and parse text and links from a given URL.\",\"template\":{\"code_CustomComponent-f6nOg\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport html2text\\n\\nclass ConvertHTMLToMarkdown(CustomComponent):\\n display_name: str = \\\"HTML to Markdown\\\"\\n description: str = \\\"Converts HTML content to Markdown format.\\\"\\n\\n def build(self, html_content: Data, ignore_links: bool = False) -> str:\\n converter = html2text.HTML2Text()\\n converter.ignore_links = ignore_links\\n markdown_text = converter.handle(html_content)\\n self.status = markdown_text\\n return markdown_text\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-f6nOg\",\"field\":\"code\"},\"display_name\":\"Code\"},\"ignore_links_CustomComponent-f6nOg\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"ignore_links\",\"display_name\":\"ignore_links\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-f6nOg\",\"field\":\"ignore_links\"}},\"code_CustomComponent-FGzJJ\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport requests\\n\\nclass FetchHTMLContent(CustomComponent):\\n display_name: str = \\\"Fetch HTML\\\"\\n description: str = \\\"Fetches HTML content from a specified URL.\\\"\\n \\n def build_config(self):\\n return {\\\"url\\\": {\\\"input_types\\\": [\\\"Data\\\", \\\"str\\\"]}} \\n\\n def build(self, url: str) -> Data:\\n response = requests.get(url)\\n self.status = str(response) + \\\"\\\\n\\\\n\\\" + response.text\\n return response.text\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-FGzJJ\",\"field\":\"code\"},\"display_name\":\"Code\"},\"code_CustomComponent-0XtUN\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from bs4 import BeautifulSoup\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Data\\n\\nclass ParseHTMLContent(CustomComponent):\\n display_name: str = \\\"Parse HTML\\\"\\n description: str = \\\"Parses HTML content using Beautiful Soup.\\\"\\n\\n def build(self, html_content: Data) -> Data:\\n soup = BeautifulSoup(html_content, 'html.parser')\\n self.status = soup\\n return soup\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-0XtUN\",\"field\":\"code\"},\"display_name\":\"Code\"},\"code_CustomComponent-ODIcp\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\n\\nclass ExtractHyperlinks(CustomComponent):\\n display_name: str = \\\"Extract Hyperlinks\\\"\\n description: str = \\\"Extracts hyperlinks from parsed HTML content.\\\"\\n\\n def build(self, soup: Data) -> list:\\n links = [link.get('href') for link in soup.find_all('a')]\\n self.status = links\\n return links\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-ODIcp\",\"field\":\"code\"},\"display_name\":\"Code\"},\"output_parser_PromptTemplate-H9Udy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"BaseOutputParser\",\"list\":false,\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"output_parser\"},\"display_name\":\"Output Parser\"},\"input_types_PromptTemplate-H9Udy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_types\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false,\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"input_types\"},\"display_name\":\"Input Types\"},\"input_variables_PromptTemplate-H9Udy\":{\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":true,\"value\":[\"url\",\"html_markdown\",\"html_links\",\"query\"],\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"input_variables\"},\"display_name\":\"Input Variables\"},\"partial_variables_PromptTemplate-H9Udy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"partial_variables\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false,\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"partial_variables\"},\"display_name\":\"Partial Variables\"},\"template_PromptTemplate-H9Udy\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"password\":false,\"name\":\"template\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"type\":\"prompt\",\"list\":false,\"value\":\"Below is the HTML content (as markdown) and hyperlinks extracted from {url}\\n\\n---\\n\\nContent:\\n\\n{html_markdown}\\n\\n---\\n\\nLinks:\\n\\n{html_links}\\n\\n---\\n\\nAnswer the user query as best as possible.\\n\\nUser query:\\n\\n{query}\\n\\nAnswer:\\n\",\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"template\"},\"display_name\":\"Template\"},\"template_format_PromptTemplate-H9Udy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"f-string\",\"password\":false,\"name\":\"template_format\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":false,\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"template_format\"},\"display_name\":\"Template Format\"},\"validate_template_PromptTemplate-H9Udy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"validate_template\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"type\":\"bool\",\"list\":false,\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"validate_template\"},\"display_name\":\"Validate Template\"},\"query_PromptTemplate-H9Udy\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"query\",\"display_name\":\"query\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"proxy\":{\"id\":\"PromptTemplate-H9Udy\",\"field\":\"query\"}},\"code_CustomComponent-OACE0\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport requests\\n\\nclass FetchHTMLContent(CustomComponent):\\n display_name: str = \\\"URL Input\\\"\\n\\n def build(self, url: str) -> str:\\n return url\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-OACE0\",\"field\":\"code\"},\"display_name\":\"Code\"},\"url_CustomComponent-OACE0\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"url\",\"display_name\":\"url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-OACE0\",\"field\":\"url\"},\"value\":\"https://paperswithcode.com/\"},\"code_CustomComponent-whsQ5\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\n\\nclass ListToMarkdownBullets(CustomComponent):\\n display_name: str = \\\"List to Bullets\\\"\\n description: str = \\\"Converts a Python list into Markdown bullet points.\\\"\\n\\n def build(self, items: list) -> str:\\n markdown_bullets = '\\\\n'.join(f'* {item}' for item in items)\\n return markdown_bullets\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"proxy\":{\"id\":\"CustomComponent-whsQ5\",\"field\":\"code\"},\"display_name\":\"Code\"}},\"flow\":{\"data\":{\"nodes\":[{\"width\":384,\"height\":405,\"id\":\"CustomComponent-f6nOg\",\"type\":\"genericNode\",\"position\":{\"x\":665.2835942536854,\"y\":-371.7823429271119},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport html2text\\n\\nclass ConvertHTMLToMarkdown(CustomComponent):\\n display_name: str = \\\"HTML to Markdown\\\"\\n description: str = \\\"Converts HTML content to Markdown format.\\\"\\n\\n def build(self, html_content: Data, ignore_links: bool = False) -> str:\\n converter = html2text.HTML2Text()\\n converter.ignore_links = ignore_links\\n markdown_text = converter.handle(html_content)\\n self.status = markdown_text\\n return markdown_text\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"html_content\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"html_content\",\"display_name\":\"html_content\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Data\",\"list\":false},\"ignore_links\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"ignore_links\",\"display_name\":\"ignore_links\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false}},\"description\":\"Converts HTML content to Markdown format.\",\"base_classes\":[\"str\"],\"display_name\":\"HTML to Markdown\",\"custom_fields\":{\"html_content\":null,\"ignore_links\":null},\"output_types\":[\"str\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-f6nOg\"},\"selected\":true,\"positionAbsolute\":{\"x\":665.2835942536854,\"y\":-371.7823429271119},\"dragging\":false},{\"width\":384,\"height\":375,\"id\":\"CustomComponent-FGzJJ\",\"type\":\"genericNode\",\"position\":{\"x\":-464.4553400967736,\"y\":-225.62715888255525},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport requests\\n\\nclass FetchHTMLContent(CustomComponent):\\n display_name: str = \\\"Fetch HTML\\\"\\n description: str = \\\"Fetches HTML content from a specified URL.\\\"\\n \\n def build_config(self):\\n return {\\\"url\\\": {\\\"input_types\\\": [\\\"Data\\\", \\\"str\\\"]}} \\n\\n def build(self, url: str) -> Data:\\n response = requests.get(url)\\n self.status = str(response) + \\\"\\\\n\\\\n\\\" + response.text\\n return response.text\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"url\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"url\",\"display_name\":\"url\",\"advanced\":false,\"input_types\":[\"Data\",\"str\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"}},\"description\":\"Fetches HTML content from a specified URL.\",\"base_classes\":[\"Data\"],\"display_name\":\"Fetch HTML\",\"custom_fields\":{\"url\":null},\"output_types\":[\"Data\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-FGzJJ\"},\"selected\":true,\"dragging\":false,\"positionAbsolute\":{\"x\":-464.4553400967736,\"y\":-225.62715888255525}},{\"width\":384,\"height\":329,\"id\":\"CustomComponent-0XtUN\",\"type\":\"genericNode\",\"position\":{\"x\":214.00059169497604,\"y\":177.27071061129823},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from bs4 import BeautifulSoup\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Data\\n\\nclass ParseHTMLContent(CustomComponent):\\n display_name: str = \\\"Parse HTML\\\"\\n description: str = \\\"Parses HTML content using Beautiful Soup.\\\"\\n\\n def build(self, html_content: Data) -> Data:\\n soup = BeautifulSoup(html_content, 'html.parser')\\n self.status = soup\\n return soup\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"html_content\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"html_content\",\"display_name\":\"html_content\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Data\",\"list\":false}},\"description\":\"Parses HTML content using Beautiful Soup.\",\"base_classes\":[\"Data\"],\"display_name\":\"Parse HTML\",\"custom_fields\":{\"html_content\":null},\"output_types\":[\"Data\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-0XtUN\"},\"selected\":true,\"dragging\":false,\"positionAbsolute\":{\"x\":214.00059169497604,\"y\":177.27071061129823}},{\"width\":384,\"height\":329,\"id\":\"CustomComponent-ODIcp\",\"type\":\"genericNode\",\"position\":{\"x\":845.0502195222412,\"y\":366.54344452019404},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\n\\nclass ExtractHyperlinks(CustomComponent):\\n display_name: str = \\\"Extract Hyperlinks\\\"\\n description: str = \\\"Extracts hyperlinks from parsed HTML content.\\\"\\n\\n def build(self, soup: Data) -> list:\\n links = [link.get('href') for link in soup.find_all('a')]\\n self.status = links\\n return links\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"soup\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"soup\",\"display_name\":\"soup\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Data\",\"list\":false}},\"description\":\"Extracts hyperlinks from parsed HTML content.\",\"base_classes\":[\"list\"],\"display_name\":\"Extract Hyperlinks\",\"custom_fields\":{\"soup\":null},\"output_types\":[\"list\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-ODIcp\"},\"selected\":true,\"positionAbsolute\":{\"x\":845.0502195222412,\"y\":366.54344452019404},\"dragging\":false},{\"width\":384,\"height\":657,\"id\":\"PromptTemplate-H9Udy\",\"type\":\"genericNode\",\"position\":{\"x\":2230.389721706283,\"y\":584.4905083765256},\"data\":{\"type\":\"PromptTemplate\",\"node\":{\"template\":{\"output_parser\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"BaseOutputParser\",\"list\":false},\"input_types\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_types\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"input_variables\":{\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":true,\"value\":[\"url\",\"html_markdown\",\"html_links\",\"query\"]},\"partial_variables\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"partial_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"template\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"password\":false,\"name\":\"template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"prompt\",\"list\":false,\"value\":\"Below is the HTML content (as markdown) and hyperlinks extracted from {url}\\n\\n---\\n\\nContent:\\n\\n{html_markdown}\\n\\n---\\n\\nLinks:\\n\\n{html_links}\\n\\n---\\n\\nAnswer the user query as best as possible.\\n\\nUser query:\\n\\n{query}\\n\\nAnswer:\\n\"},\"template_format\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"f-string\",\"password\":false,\"name\":\"template_format\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":false},\"validate_template\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"validate_template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"PromptTemplate\",\"url\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"url\",\"display_name\":\"url\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"html_markdown\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"html_markdown\",\"display_name\":\"html_markdown\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"html_links\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"html_links\",\"display_name\":\"html_links\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"query\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"query\",\"display_name\":\"query\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"A prompt template for a language model.\",\"base_classes\":[\"StringPromptTemplate\",\"BasePromptTemplate\",\"PromptTemplate\"],\"name\":\"\",\"display_name\":\"PromptTemplate\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/\",\"custom_fields\":{\"\":[\"url\",\"html_markdown\",\"html_links\",\"query\"]},\"output_types\":[],\"full_path\":null,\"field_formatters\":{},\"beta\":false,\"error\":null},\"id\":\"PromptTemplate-H9Udy\"},\"selected\":true,\"positionAbsolute\":{\"x\":2230.389721706283,\"y\":584.4905083765256},\"dragging\":false},{\"width\":384,\"height\":347,\"id\":\"CustomComponent-OACE0\",\"type\":\"genericNode\",\"position\":{\"x\":-1155.9497945157625,\"y\":198.13583204151553},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport requests\\n\\nclass FetchHTMLContent(CustomComponent):\\n display_name: str = \\\"URL Input\\\"\\n\\n def build(self, url: str) -> str:\\n return url\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"url\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"url\",\"display_name\":\"url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":null,\"base_classes\":[\"str\"],\"display_name\":\"URL Input\",\"custom_fields\":{\"url\":null},\"output_types\":[\"str\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-OACE0\"},\"selected\":true,\"positionAbsolute\":{\"x\":-1155.9497945157625,\"y\":198.13583204151553},\"dragging\":false},{\"width\":384,\"height\":329,\"id\":\"CustomComponent-whsQ5\",\"type\":\"genericNode\",\"position\":{\"x\":1396.5574076376327,\"y\":694.8308714574463},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\n\\nclass ListToMarkdownBullets(CustomComponent):\\n display_name: str = \\\"List to Bullets\\\"\\n description: str = \\\"Converts a Python list into Markdown bullet points.\\\"\\n\\n def build(self, items: list) -> str:\\n markdown_bullets = '\\\\n'.join(f'* {item}' for item in items)\\n return markdown_bullets\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"items\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"items\",\"display_name\":\"items\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"list\",\"list\":true}},\"description\":\"Converts a Python list into Markdown bullet points.\",\"base_classes\":[\"str\"],\"display_name\":\"List to Bullets\",\"custom_fields\":{\"items\":null},\"output_types\":[\"str\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-whsQ5\"},\"selected\":true,\"positionAbsolute\":{\"x\":1396.5574076376327,\"y\":694.8308714574463},\"dragging\":false}],\"edges\":[{\"source\":\"CustomComponent-FGzJJ\",\"sourceHandle\":\"{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-FGzJJœ}\",\"target\":\"CustomComponent-f6nOg\",\"targetHandle\":\"{œfieldNameœ:œhtml_contentœ,œidœ:œCustomComponent-f6nOgœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"html_content\",\"id\":\"CustomComponent-f6nOg\",\"inputTypes\":null,\"type\":\"Data\"},\"sourceHandle\":{\"baseClasses\":[\"Data\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-FGzJJ\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-FGzJJ{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-FGzJJœ}-CustomComponent-f6nOg{œfieldNameœ:œhtml_contentœ,œidœ:œCustomComponent-f6nOgœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"selected\":true},{\"source\":\"CustomComponent-FGzJJ\",\"sourceHandle\":\"{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-FGzJJœ}\",\"target\":\"CustomComponent-0XtUN\",\"targetHandle\":\"{œfieldNameœ:œhtml_contentœ,œidœ:œCustomComponent-0XtUNœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"html_content\",\"id\":\"CustomComponent-0XtUN\",\"inputTypes\":null,\"type\":\"Data\"},\"sourceHandle\":{\"baseClasses\":[\"Data\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-FGzJJ\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-FGzJJ{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-FGzJJœ}-CustomComponent-0XtUN{œfieldNameœ:œhtml_contentœ,œidœ:œCustomComponent-0XtUNœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"selected\":true},{\"source\":\"CustomComponent-0XtUN\",\"sourceHandle\":\"{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-0XtUNœ}\",\"target\":\"CustomComponent-ODIcp\",\"targetHandle\":\"{œfieldNameœ:œsoupœ,œidœ:œCustomComponent-ODIcpœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"soup\",\"id\":\"CustomComponent-ODIcp\",\"inputTypes\":null,\"type\":\"Data\"},\"sourceHandle\":{\"baseClasses\":[\"Data\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-0XtUN\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-0XtUN{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-0XtUNœ}-CustomComponent-ODIcp{œfieldNameœ:œsoupœ,œidœ:œCustomComponent-ODIcpœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"selected\":true},{\"source\":\"CustomComponent-OACE0\",\"sourceHandle\":\"{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-OACE0œ}\",\"target\":\"CustomComponent-FGzJJ\",\"targetHandle\":\"{œfieldNameœ:œurlœ,œidœ:œCustomComponent-FGzJJœ,œinputTypesœ:[œDataœ,œstrœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"url\",\"id\":\"CustomComponent-FGzJJ\",\"inputTypes\":[\"Data\",\"str\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"str\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-OACE0\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-OACE0{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-OACE0œ}-CustomComponent-FGzJJ{œfieldNameœ:œurlœ,œidœ:œCustomComponent-FGzJJœ,œinputTypesœ:[œDataœ,œstrœ],œtypeœ:œstrœ}\",\"selected\":true},{\"source\":\"CustomComponent-OACE0\",\"sourceHandle\":\"{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-OACE0œ}\",\"target\":\"PromptTemplate-H9Udy\",\"targetHandle\":\"{œfieldNameœ:œurlœ,œidœ:œPromptTemplate-H9Udyœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"url\",\"id\":\"PromptTemplate-H9Udy\",\"inputTypes\":[\"Document\",\"BaseOutputParser\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"str\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-OACE0\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-OACE0{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-OACE0œ}-PromptTemplate-H9Udy{œfieldNameœ:œurlœ,œidœ:œPromptTemplate-H9Udyœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"selected\":true},{\"source\":\"CustomComponent-ODIcp\",\"sourceHandle\":\"{œbaseClassesœ:[œlistœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-ODIcpœ}\",\"target\":\"CustomComponent-whsQ5\",\"targetHandle\":\"{œfieldNameœ:œitemsœ,œidœ:œCustomComponent-whsQ5œ,œinputTypesœ:null,œtypeœ:œlistœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"items\",\"id\":\"CustomComponent-whsQ5\",\"inputTypes\":null,\"type\":\"list\"},\"sourceHandle\":{\"baseClasses\":[\"list\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-ODIcp\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-ODIcp{œbaseClassesœ:[œlistœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-ODIcpœ}-CustomComponent-whsQ5{œfieldNameœ:œitemsœ,œidœ:œCustomComponent-whsQ5œ,œinputTypesœ:null,œtypeœ:œlistœ}\",\"selected\":true},{\"source\":\"CustomComponent-whsQ5\",\"sourceHandle\":\"{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-whsQ5œ}\",\"target\":\"PromptTemplate-H9Udy\",\"targetHandle\":\"{œfieldNameœ:œhtml_linksœ,œidœ:œPromptTemplate-H9Udyœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"html_links\",\"id\":\"PromptTemplate-H9Udy\",\"inputTypes\":[\"Document\",\"BaseOutputParser\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"str\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-whsQ5\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-whsQ5{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-whsQ5œ}-PromptTemplate-H9Udy{œfieldNameœ:œhtml_linksœ,œidœ:œPromptTemplate-H9Udyœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"selected\":true},{\"source\":\"CustomComponent-f6nOg\",\"sourceHandle\":\"{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-f6nOgœ}\",\"target\":\"PromptTemplate-H9Udy\",\"targetHandle\":\"{œfieldNameœ:œhtml_markdownœ,œidœ:œPromptTemplate-H9Udyœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"html_markdown\",\"id\":\"PromptTemplate-H9Udy\",\"inputTypes\":[\"Document\",\"BaseOutputParser\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"str\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-f6nOg\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-foreground stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-f6nOg{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-f6nOgœ}-PromptTemplate-H9Udy{œfieldNameœ:œhtml_markdownœ,œidœ:œPromptTemplate-H9Udyœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"selected\":true}],\"viewport\":{\"x\":343.0346131188585,\"y\":341.89843948642147,\"zoom\":0.24148408223121196}},\"is_component\":false,\"name\":\"Fluffy Ptolemy\",\"description\":\"\",\"id\":\"W5oNW\"}}},\"selected\":false,\"positionAbsolute\":{\"x\":-222,\"y\":682.560723386973}}],\"edges\":[{\"source\":\"ChatOpenAI-NTTcv\",\"target\":\"LLMChain-RQsU1\",\"sourceHandle\":\"{œbaseClassesœ:[œBaseLanguageModelœ,œChatOpenAIœ,œBaseChatModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-NTTcvœ}\",\"targetHandle\":\"{œfieldNameœ:œllmœ,œidœ:œLLMChain-RQsU1œ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\",\"id\":\"reactflow__edge-ChatOpenAI-NTTcv{œbaseClassesœ:[œBaseLanguageModelœ,œChatOpenAIœ,œBaseChatModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-NTTcvœ}-LLMChain-RQsU1{œfieldNameœ:œllmœ,œidœ:œLLMChain-RQsU1œ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"llm\",\"id\":\"LLMChain-RQsU1\",\"inputTypes\":null,\"type\":\"BaseLanguageModel\"},\"sourceHandle\":{\"baseClasses\":[\"BaseLanguageModel\",\"ChatOpenAI\",\"BaseChatModel\",\"BaseLLM\"],\"dataType\":\"ChatOpenAI\",\"id\":\"ChatOpenAI-NTTcv\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 \",\"animated\":false,\"selected\":false},{\"source\":\"PromptTemplate-VELMV\",\"target\":\"LLMChain-RQsU1\",\"sourceHandle\":\"{œbaseClassesœ:[œStringPromptTemplateœ,œBasePromptTemplateœ,œPromptTemplateœ],œdataTypeœ:œPromptTemplateœ,œidœ:œPromptTemplate-VELMVœ}\",\"targetHandle\":\"{œfieldNameœ:œpromptœ,œidœ:œLLMChain-RQsU1œ,œinputTypesœ:null,œtypeœ:œBasePromptTemplateœ}\",\"id\":\"reactflow__edge-PromptTemplate-VELMV{œbaseClassesœ:[œStringPromptTemplateœ,œBasePromptTemplateœ,œPromptTemplateœ],œdataTypeœ:œPromptTemplateœ,œidœ:œPromptTemplate-VELMVœ}-LLMChain-RQsU1{œfieldNameœ:œpromptœ,œidœ:œLLMChain-RQsU1œ,œinputTypesœ:null,œtypeœ:œBasePromptTemplateœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"prompt\",\"id\":\"LLMChain-RQsU1\",\"inputTypes\":null,\"type\":\"BasePromptTemplate\"},\"sourceHandle\":{\"baseClasses\":[\"StringPromptTemplate\",\"BasePromptTemplate\",\"PromptTemplate\"],\"dataType\":\"PromptTemplate\",\"id\":\"PromptTemplate-VELMV\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 \",\"animated\":false,\"selected\":false}],\"viewport\":{\"x\":298.29888454238517,\"y\":96.95765543775741,\"zoom\":0.5140569133280332}},\"is_component\":false,\"updated_at\":\"2023-12-04T23:23:08.584967\",\"folder\":null,\"id\":\"5df79f1d-f592-4d59-8c0f-9f3c2f6465b1\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Silly Pasteur\",\"description\":\"Nurture NLP Nodes Here.\",\"data\":{\"nodes\":[{\"width\":384,\"height\":338,\"id\":\"LLMChain-cHel8\",\"type\":\"genericNode\",\"position\":{\"x\":547.3876889720291,\"y\":299.2057833881307},\"data\":{\"type\":\"LLMChain\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Callable, Optional, Union\\n\\nfrom langchain.chains import LLMChain\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import (\\n BaseLanguageModel,\\n BaseMemory,\\n BasePromptTemplate,\\n Chain,\\n)\\n\\n\\nclass LLMChainComponent(CustomComponent):\\n display_name = \\\"LLMChain\\\"\\n description = \\\"Chain to run queries against LLMs\\\"\\n\\n def build_config(self):\\n return {\\n \\\"prompt\\\": {\\\"display_name\\\": \\\"Prompt\\\"},\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"memory\\\": {\\\"display_name\\\": \\\"Memory\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n prompt: BasePromptTemplate,\\n llm: BaseLanguageModel,\\n memory: Optional[BaseMemory] = None,\\n ) -> Union[Chain, Callable]:\\n return LLMChain(prompt=prompt, llm=llm, memory=memory)\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseMemory\",\"list\":false},\"prompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"prompt\",\"display_name\":\"Prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BasePromptTemplate\",\"list\":false}},\"description\":\"Chain to run queries against LLMs\",\"base_classes\":[\"Chain\",\"Callable\"],\"display_name\":\"LLMChain\",\"custom_fields\":{\"llm\":null,\"memory\":null,\"prompt\":null},\"output_types\":[\"LLMChain\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"LLMChain-cHel8\"},\"selected\":false,\"positionAbsolute\":{\"x\":547.3876889720291,\"y\":299.2057833881307},\"dragging\":false},{\"width\":384,\"height\":626,\"id\":\"ChatOpenAI-LA6y0\",\"type\":\"genericNode\",\"position\":{\"x\":-272.94405331278074,\"y\":-603.148171441675},\"data\":{\"type\":\"ChatOpenAI\",\"node\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"list\":true},\"async_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"async_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"default_headers\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"default_query\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_query\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"http_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"http_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":2,\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"max_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"max_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"gpt-4-1106-preview\",\"password\":false,\"options\":[\"gpt-4-1106-preview\",\"gpt-4\",\"gpt-4-32k\",\"gpt-3.5-turbo\",\"gpt-3.5-turbo-16k\"],\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"n\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"n\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":false,\"dynamic\":false,\"info\":\"\\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\\n\",\"type\":\"str\",\"list\":false},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"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\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"0.1\",\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ChatOpenAI\"},\"description\":\"`OpenAI` Chat large language models API.\",\"base_classes\":[\"BaseLanguageModel\",\"ChatOpenAI\",\"BaseChatModel\",\"BaseLLM\"],\"display_name\":\"ChatOpenAI\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai\",\"beta\":false,\"error\":null},\"id\":\"ChatOpenAI-LA6y0\"},\"selected\":false,\"dragging\":false,\"positionAbsolute\":{\"x\":-272.94405331278074,\"y\":-603.148171441675}},{\"width\":384,\"height\":404,\"id\":\"CustomComponent-ZNoRM\",\"type\":\"genericNode\",\"position\":{\"x\":-103.65741264289085,\"y\":134.62332404764658},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport html2text\\n\\nclass ConvertHTMLToMarkdown(CustomComponent):\\n display_name: str = \\\"HTML to Markdown\\\"\\n description: str = \\\"Converts HTML content to Markdown format.\\\"\\n\\n def build(self, html_content: Data, ignore_links: bool = False) -> str:\\n converter = html2text.HTML2Text()\\n converter.ignore_links = ignore_links\\n markdown_text = converter.handle(html_content)\\n self.status = markdown_text\\n return markdown_text\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"display_name\":\"code\"},\"_type\":\"CustomComponent\",\"html_content\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"html_content\",\"display_name\":\"html_content\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Data\",\"list\":false},\"ignore_links\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"ignore_links\",\"display_name\":\"ignore_links\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false}},\"description\":\"Converts HTML content to Markdown format.\",\"base_classes\":[\"str\"],\"display_name\":\"HTML to Markdown\",\"custom_fields\":{\"html_content\":null,\"ignore_links\":null},\"output_types\":[\"str\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-ZNoRM\"},\"selected\":false,\"positionAbsolute\":{\"x\":-103.65741264289085,\"y\":134.62332404764658},\"dragging\":false},{\"width\":384,\"height\":374,\"id\":\"CustomComponent-zNSTv\",\"type\":\"genericNode\",\"position\":{\"x\":-1233.3963469933499,\"y\":280.77850809220325},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport requests\\n\\nclass FetchHTMLContent(CustomComponent):\\n display_name: str = \\\"Fetch HTML\\\"\\n description: str = \\\"Fetches HTML content from a specified URL.\\\"\\n \\n def build_config(self):\\n return {\\\"url\\\": {\\\"input_types\\\": [\\\"Data\\\", \\\"str\\\"]}} \\n\\n def build(self, url: str) -> Data:\\n response = requests.get(url)\\n self.status = str(response) + \\\"\\\\n\\\\n\\\" + response.text\\n return response.text\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"display_name\":\"code\"},\"_type\":\"CustomComponent\",\"url\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"url\",\"display_name\":\"url\",\"advanced\":false,\"input_types\":[\"Data\",\"str\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"}},\"description\":\"Fetches HTML content from a specified URL.\",\"base_classes\":[\"Data\"],\"display_name\":\"Fetch HTML\",\"custom_fields\":{\"url\":null},\"output_types\":[\"Data\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-zNSTv\"},\"selected\":false,\"dragging\":false,\"positionAbsolute\":{\"x\":-1233.3963469933499,\"y\":280.77850809220325}},{\"width\":384,\"height\":328,\"id\":\"CustomComponent-Ihm2o\",\"type\":\"genericNode\",\"position\":{\"x\":-554.9404152016002,\"y\":683.6763775860567},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from bs4 import BeautifulSoup\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Data\\n\\nclass ParseHTMLContent(CustomComponent):\\n display_name: str = \\\"Parse HTML\\\"\\n description: str = \\\"Parses HTML content using Beautiful Soup.\\\"\\n\\n def build(self, html_content: Data) -> Data:\\n soup = BeautifulSoup(html_content, 'html.parser')\\n self.status = soup\\n return soup\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"display_name\":\"code\"},\"_type\":\"CustomComponent\",\"html_content\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"html_content\",\"display_name\":\"html_content\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Data\",\"list\":false}},\"description\":\"Parses HTML content using Beautiful Soup.\",\"base_classes\":[\"Data\"],\"display_name\":\"Parse HTML\",\"custom_fields\":{\"html_content\":null},\"output_types\":[\"Data\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-Ihm2o\"},\"selected\":false,\"dragging\":false,\"positionAbsolute\":{\"x\":-554.9404152016002,\"y\":683.6763775860567}},{\"width\":384,\"height\":328,\"id\":\"CustomComponent-6ST9l\",\"type\":\"genericNode\",\"position\":{\"x\":76.10921262566495,\"y\":872.9491114949525},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\n\\nclass ExtractHyperlinks(CustomComponent):\\n display_name: str = \\\"Extract Hyperlinks\\\"\\n description: str = \\\"Extracts hyperlinks from parsed HTML content.\\\"\\n\\n def build(self, soup: Data) -> list:\\n links = [link.get('href') for link in soup.find_all('a')]\\n self.status = links\\n return links\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"display_name\":\"code\"},\"_type\":\"CustomComponent\",\"soup\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"soup\",\"display_name\":\"soup\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Data\",\"list\":false}},\"description\":\"Extracts hyperlinks from parsed HTML content.\",\"base_classes\":[\"list\"],\"display_name\":\"Extract Hyperlinks\",\"custom_fields\":{\"soup\":null},\"output_types\":[\"list\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-6ST9l\"},\"selected\":false,\"positionAbsolute\":{\"x\":76.10921262566495,\"y\":872.9491114949525},\"dragging\":false},{\"width\":384,\"height\":654,\"id\":\"PromptTemplate-l35W1\",\"type\":\"genericNode\",\"position\":{\"x\":1461.4487148097069,\"y\":1090.896175351284},\"data\":{\"type\":\"PromptTemplate\",\"node\":{\"template\":{\"output_parser\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"BaseOutputParser\",\"list\":false,\"display_name\":\"output_parser\"},\"input_types\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_types\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false,\"display_name\":\"input_types\"},\"input_variables\":{\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":true,\"value\":[\"url\",\"html_markdown\",\"html_links\",\"query\"],\"display_name\":\"input_variables\"},\"partial_variables\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"partial_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false,\"display_name\":\"partial_variables\"},\"template\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"password\":false,\"name\":\"template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"prompt\",\"list\":false,\"value\":\"Below is the HTML content (as markdown) and hyperlinks extracted from {url}\\n\\n---\\n\\nContent:\\n\\n{html_markdown}\\n\\n---\\n\\nLinks:\\n\\n{html_links}\\n\\n---\\n\\nAnswer the user query as best as possible.\\n\\nUser query:\\n\\n{query}\\n\\nAnswer:\\n\",\"display_name\":\"template\"},\"template_format\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"f-string\",\"password\":false,\"name\":\"template_format\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":false,\"display_name\":\"template_format\"},\"validate_template\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"validate_template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"bool\",\"list\":false,\"display_name\":\"validate_template\"},\"_type\":\"PromptTemplate\",\"url\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"url\",\"display_name\":\"url\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"html_markdown\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"html_markdown\",\"display_name\":\"html_markdown\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"html_links\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"html_links\",\"display_name\":\"html_links\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"query\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"query\",\"display_name\":\"query\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"A prompt template for a language model.\",\"base_classes\":[\"StringPromptTemplate\",\"BasePromptTemplate\",\"PromptTemplate\"],\"name\":\"\",\"display_name\":\"PromptTemplate\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/\",\"custom_fields\":{\"\":[\"url\",\"html_markdown\",\"html_links\",\"query\"]},\"output_types\":[],\"full_path\":null,\"field_formatters\":{},\"beta\":false,\"error\":null},\"id\":\"PromptTemplate-l35W1\"},\"selected\":false,\"positionAbsolute\":{\"x\":1461.4487148097069,\"y\":1090.896175351284},\"dragging\":false},{\"width\":384,\"height\":346,\"id\":\"CustomComponent-iTLf4\",\"type\":\"genericNode\",\"position\":{\"x\":-1924.8908014123388,\"y\":704.5414990162741},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nimport requests\\n\\nclass FetchHTMLContent(CustomComponent):\\n display_name: str = \\\"URL Input\\\"\\n\\n def build(self, url: str) -> str:\\n return url\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"display_name\":\"code\"},\"_type\":\"CustomComponent\",\"url\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"url\",\"display_name\":\"url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"https://paperswithcode.com/\"}},\"description\":null,\"base_classes\":[\"str\"],\"display_name\":\"URL Input\",\"custom_fields\":{\"url\":null},\"output_types\":[\"str\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-iTLf4\"},\"selected\":false,\"positionAbsolute\":{\"x\":-1924.8908014123388,\"y\":704.5414990162741},\"dragging\":false},{\"width\":384,\"height\":328,\"id\":\"CustomComponent-jWLUz\",\"type\":\"genericNode\",\"position\":{\"x\":627.6164007410564,\"y\":1201.2365384322047},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\n\\nclass ListToMarkdownBullets(CustomComponent):\\n display_name: str = \\\"List to Bullets\\\"\\n description: str = \\\"Converts a Python list into Markdown bullet points.\\\"\\n\\n def build(self, items: list) -> str:\\n markdown_bullets = '\\\\n'.join(f'* {item}' for item in items)\\n return markdown_bullets\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false,\"display_name\":\"code\"},\"_type\":\"CustomComponent\",\"items\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"items\",\"display_name\":\"items\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"list\",\"list\":true}},\"description\":\"Converts a Python list into Markdown bullet points.\",\"base_classes\":[\"str\"],\"display_name\":\"List to Bullets\",\"custom_fields\":{\"items\":null},\"output_types\":[\"str\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"CustomComponent-jWLUz\"},\"selected\":false,\"positionAbsolute\":{\"x\":627.6164007410564,\"y\":1201.2365384322047},\"dragging\":false}],\"edges\":[{\"source\":\"ChatOpenAI-LA6y0\",\"target\":\"LLMChain-cHel8\",\"sourceHandle\":\"{œbaseClassesœ:[œBaseLanguageModelœ,œChatOpenAIœ,œBaseChatModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-LA6y0œ}\",\"targetHandle\":\"{œfieldNameœ:œllmœ,œidœ:œLLMChain-cHel8œ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\",\"id\":\"reactflow__edge-ChatOpenAI-LA6y0{œbaseClassesœ:[œBaseLanguageModelœ,œChatOpenAIœ,œBaseChatModelœ,œBaseLLMœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-LA6y0œ}-LLMChain-cHel8{œfieldNameœ:œllmœ,œidœ:œLLMChain-cHel8œ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"llm\",\"id\":\"LLMChain-cHel8\",\"inputTypes\":null,\"type\":\"BaseLanguageModel\"},\"sourceHandle\":{\"baseClasses\":[\"BaseLanguageModel\",\"ChatOpenAI\",\"BaseChatModel\",\"BaseLLM\"],\"dataType\":\"ChatOpenAI\",\"id\":\"ChatOpenAI-LA6y0\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"selected\":false},{\"source\":\"CustomComponent-zNSTv\",\"sourceHandle\":\"{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-zNSTvœ}\",\"target\":\"CustomComponent-ZNoRM\",\"targetHandle\":\"{œfieldNameœ:œhtml_contentœ,œidœ:œCustomComponent-ZNoRMœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"html_content\",\"id\":\"CustomComponent-ZNoRM\",\"inputTypes\":null,\"type\":\"Data\"},\"sourceHandle\":{\"baseClasses\":[\"Data\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-zNSTv\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-zNSTv{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-zNSTvœ}-CustomComponent-ZNoRM{œfieldNameœ:œhtml_contentœ,œidœ:œCustomComponent-ZNoRMœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"selected\":false},{\"source\":\"CustomComponent-zNSTv\",\"sourceHandle\":\"{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-zNSTvœ}\",\"target\":\"CustomComponent-Ihm2o\",\"targetHandle\":\"{œfieldNameœ:œhtml_contentœ,œidœ:œCustomComponent-Ihm2oœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"html_content\",\"id\":\"CustomComponent-Ihm2o\",\"inputTypes\":null,\"type\":\"Data\"},\"sourceHandle\":{\"baseClasses\":[\"Data\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-zNSTv\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-zNSTv{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-zNSTvœ}-CustomComponent-Ihm2o{œfieldNameœ:œhtml_contentœ,œidœ:œCustomComponent-Ihm2oœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"selected\":false},{\"source\":\"CustomComponent-Ihm2o\",\"sourceHandle\":\"{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-Ihm2oœ}\",\"target\":\"CustomComponent-6ST9l\",\"targetHandle\":\"{œfieldNameœ:œsoupœ,œidœ:œCustomComponent-6ST9lœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"soup\",\"id\":\"CustomComponent-6ST9l\",\"inputTypes\":null,\"type\":\"Data\"},\"sourceHandle\":{\"baseClasses\":[\"Data\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-Ihm2o\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-Ihm2o{œbaseClassesœ:[œDataœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-Ihm2oœ}-CustomComponent-6ST9l{œfieldNameœ:œsoupœ,œidœ:œCustomComponent-6ST9lœ,œinputTypesœ:null,œtypeœ:œDataœ}\",\"selected\":false},{\"source\":\"CustomComponent-iTLf4\",\"sourceHandle\":\"{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-iTLf4œ}\",\"target\":\"CustomComponent-zNSTv\",\"targetHandle\":\"{œfieldNameœ:œurlœ,œidœ:œCustomComponent-zNSTvœ,œinputTypesœ:[œDataœ,œstrœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"url\",\"id\":\"CustomComponent-zNSTv\",\"inputTypes\":[\"Data\",\"str\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"str\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-iTLf4\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-iTLf4{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-iTLf4œ}-CustomComponent-zNSTv{œfieldNameœ:œurlœ,œidœ:œCustomComponent-zNSTvœ,œinputTypesœ:[œDataœ,œstrœ],œtypeœ:œstrœ}\",\"selected\":false},{\"source\":\"CustomComponent-iTLf4\",\"sourceHandle\":\"{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-iTLf4œ}\",\"target\":\"PromptTemplate-l35W1\",\"targetHandle\":\"{œfieldNameœ:œurlœ,œidœ:œPromptTemplate-l35W1œ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"url\",\"id\":\"PromptTemplate-l35W1\",\"inputTypes\":[\"Document\",\"BaseOutputParser\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"str\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-iTLf4\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-iTLf4{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-iTLf4œ}-PromptTemplate-l35W1{œfieldNameœ:œurlœ,œidœ:œPromptTemplate-l35W1œ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"selected\":false},{\"source\":\"CustomComponent-6ST9l\",\"sourceHandle\":\"{œbaseClassesœ:[œlistœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-6ST9lœ}\",\"target\":\"CustomComponent-jWLUz\",\"targetHandle\":\"{œfieldNameœ:œitemsœ,œidœ:œCustomComponent-jWLUzœ,œinputTypesœ:null,œtypeœ:œlistœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"items\",\"id\":\"CustomComponent-jWLUz\",\"inputTypes\":null,\"type\":\"list\"},\"sourceHandle\":{\"baseClasses\":[\"list\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-6ST9l\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-6ST9l{œbaseClassesœ:[œlistœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-6ST9lœ}-CustomComponent-jWLUz{œfieldNameœ:œitemsœ,œidœ:œCustomComponent-jWLUzœ,œinputTypesœ:null,œtypeœ:œlistœ}\",\"selected\":false},{\"source\":\"CustomComponent-jWLUz\",\"sourceHandle\":\"{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-jWLUzœ}\",\"target\":\"PromptTemplate-l35W1\",\"targetHandle\":\"{œfieldNameœ:œhtml_linksœ,œidœ:œPromptTemplate-l35W1œ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"html_links\",\"id\":\"PromptTemplate-l35W1\",\"inputTypes\":[\"Document\",\"BaseOutputParser\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"str\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-jWLUz\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-jWLUz{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-jWLUzœ}-PromptTemplate-l35W1{œfieldNameœ:œhtml_linksœ,œidœ:œPromptTemplate-l35W1œ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"selected\":false},{\"source\":\"CustomComponent-ZNoRM\",\"sourceHandle\":\"{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-ZNoRMœ}\",\"target\":\"PromptTemplate-l35W1\",\"targetHandle\":\"{œfieldNameœ:œhtml_markdownœ,œidœ:œPromptTemplate-l35W1œ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"html_markdown\",\"id\":\"PromptTemplate-l35W1\",\"inputTypes\":[\"Document\",\"BaseOutputParser\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"str\"],\"dataType\":\"CustomComponent\",\"id\":\"CustomComponent-ZNoRM\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-CustomComponent-ZNoRM{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-ZNoRMœ}-PromptTemplate-l35W1{œfieldNameœ:œhtml_markdownœ,œidœ:œPromptTemplate-l35W1œ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"selected\":false},{\"source\":\"PromptTemplate-l35W1\",\"sourceHandle\":\"{œbaseClassesœ:[œStringPromptTemplateœ,œBasePromptTemplateœ,œPromptTemplateœ],œdataTypeœ:œPromptTemplateœ,œidœ:œPromptTemplate-l35W1œ}\",\"target\":\"LLMChain-cHel8\",\"targetHandle\":\"{œfieldNameœ:œpromptœ,œidœ:œLLMChain-cHel8œ,œinputTypesœ:null,œtypeœ:œBasePromptTemplateœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"prompt\",\"id\":\"LLMChain-cHel8\",\"inputTypes\":null,\"type\":\"BasePromptTemplate\"},\"sourceHandle\":{\"baseClasses\":[\"StringPromptTemplate\",\"BasePromptTemplate\",\"PromptTemplate\"],\"dataType\":\"PromptTemplate\",\"id\":\"PromptTemplate-l35W1\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-PromptTemplate-mJqEg{œbaseClassesœ:[œStringPromptTemplateœ,œBasePromptTemplateœ,œPromptTemplateœ],œdataTypeœ:œPromptTemplateœ,œidœ:œPromptTemplate-mJqEgœ}-LLMChain-cHel8{œfieldNameœ:œpromptœ,œidœ:œLLMChain-cHel8œ,œinputTypesœ:null,œtypeœ:œBasePromptTemplateœ}\"}],\"viewport\":{\"x\":206.6159172940935,\"y\":79.94375811155385,\"zoom\":0.5140569133280333}},\"is_component\":false,\"updated_at\":\"2023-12-06T00:23:04.515144\",\"folder\":null,\"id\":\"ecfb377a-7e88-405d-8d66-7560735ce446\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Lonely Lovelace\",\"description\":\"Smart Chains, Smarter Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-04T23:43:25.925753\",\"folder\":null,\"id\":\"30e71767-6128-40e4-9a6d-b9197b679971\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Custom Component\",\"description\":\"Create any custom component you want!\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\n\\n\\nclass Component(CustomComponent):\\n display_name: str = \\\"Custom Component\\\"\\n description: str = \\\"Create any custom component you want!\\\"\\n documentation: str = \\\"http://docs.langflow.org/components/custom\\\"\\n\\n def build_config(self):\\n return {\\\"param\\\": {\\\"display_name\\\": \\\"Parameter\\\"}}\\n\\n def build(self, param: Data) -> Data:\\n return param\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"param\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"param\",\"display_name\":\"Parameter\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Data\",\"list\":false}},\"description\":\"Create any custom component you want!\",\"base_classes\":[\"Data\"],\"display_name\":\"Custom Component\",\"custom_fields\":{\"param\":null},\"output_types\":[\"CustomComponent\"],\"documentation\":\"http://docs.langflow.org/components/custom\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"CustomComponent-IxJqc\"},\"id\":\"CustomComponent-IxJqc\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-05T22:08:27.080204\",\"folder\":null,\"id\":\"f3c56abb-96d8-4a09-80d3-f60181661b3c\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Amazing Wilson\",\"description\":\"Unfolding Linguistic Possibilities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-05T23:49:58.272677\",\"folder\":null,\"id\":\"324499a6-17a6-49de-96b1-b88955ed2c3d\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Nauseous Kowalevski\",\"description\":\"Create, Curate, Communicate with Langflow.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:45:27.084387\",\"folder\":null,\"id\":\"e3168485-d31b-472a-907f-faf833bf7824\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Silly Fermi\",\"description\":\"Craft Meaningful Interactions, Generate Value.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:45:57.134463\",\"folder\":null,\"id\":\"d0ecea5d-bcf9-4b8e-88f0-3c243d309336\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Friendly Ardinghelli\",\"description\":\"Smart Chains, Smarter Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:45:57.138184\",\"folder\":null,\"id\":\"a406912d-b0e2-4954-bef3-ee80c29eca3c\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Gleeful Easley\",\"description\":\"Bridging Prompts for Brilliance.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:45:57.162908\",\"folder\":null,\"id\":\"57b32155-4c6e-4823-ad03-8dd09d8abc62\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Effervescent Varahamihira\",\"description\":\"Create, Chain, Communicate.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:45:57.135644\",\"folder\":null,\"id\":\"18daa0ff-2e5d-457a-95d7-710affec5c4d\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Jubilant Joliot\",\"description\":\"Language Architect at Work!\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:45:57.139496\",\"folder\":null,\"id\":\"9255e938-280e-4ce7-91cd-8622126a7d02\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Adoring Carroll\",\"description\":\"Nurture NLP Nodes Here.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:45:57.162240\",\"folder\":null,\"id\":\"a7a680b9-30b1-4438-ac24-da597de443aa\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Berserk Herschel\",\"description\":\"Your Hub for Text Generation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:46:02.593504\",\"folder\":null,\"id\":\"37a439b0-7b1d-45e3-b4fa-5c73669bae3b\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Distracted Joliot\",\"description\":\"Conversational Cartography Unlocked.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:47:04.845238\",\"folder\":null,\"id\":\"4d23fd0a-8ad5-46b9-bb99-eed4138e7426\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Happy Babbage\",\"description\":\"Flow into the Future of Language.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:47:41.899665\",\"folder\":null,\"id\":\"1c8ad5b9-5524-41fe-a762-52c75126b832\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Adoring Brown\",\"description\":\"Unlock the Power of AI in Your Business Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:47:42.702031\",\"folder\":null,\"id\":\"9d4c8e79-4904-4a51-a4bb-146c3d8db10e\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Focused Mahavira\",\"description\":\"Design, Develop, Dialogize.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:47:42.786331\",\"folder\":null,\"id\":\"4ba370d1-1f8e-4a23-99aa-99e2cd9b7cbf\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Mad Gates\",\"description\":\"Where Language Meets Logic.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:47:42.838989\",\"folder\":null,\"id\":\"992c3cd3-1d79-4986-8c04-88a34130fa30\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Serene Mcclintock\",\"description\":\"Unlock the Power of AI in Your Business Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:47:42.932723\",\"folder\":null,\"id\":\"a65bfd13-44df-4090-aca0-5057e21e9997\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Berserk Feynman\",\"description\":\"Text Generation Meets Business Transformation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:47:42.931359\",\"folder\":null,\"id\":\"7a05dac5-c005-411d-9994-19d61e71ce78\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Sprightly Perlman\",\"description\":\"Interactive Language Weaving.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:47:43.054687\",\"folder\":null,\"id\":\"6db24541-7211-48e6-a792-1a4a99a0ef90\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Jolly Colden\",\"description\":\"Flow into the Future of Language.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:47:43.078384\",\"folder\":null,\"id\":\"13ac42e8-9124-4bf4-9ea2-28671ef2d9a4\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Gleeful Kaku\",\"description\":\"The Power of Language at Your Fingertips.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:50:33.156776\",\"folder\":null,\"id\":\"79262d75-5c62-4b14-b067-f4297f5c912f\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Jovial Khayyam\",\"description\":\"Empowering Communication, Enabling Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:51:13.295375\",\"folder\":null,\"id\":\"3b397e74-d8be-4728-9d6c-05f7c78106a7\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Goofy Mccarthy\",\"description\":\"Building Powerful Solutions with Language Models.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:51:27.632685\",\"folder\":null,\"id\":\"13f4e1fd-45eb-4271-92fd-0d70a31c61d2\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Cocky Lalande\",\"description\":\"Building Intelligent Interactions.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:51:54.628983\",\"folder\":null,\"id\":\"9cfd60d8-9311-47b0-b71b-f488f1940bc7\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Romantic Mirzakhani\",\"description\":\"Innovation in Interaction with Langflow.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:52:52.622698\",\"folder\":null,\"id\":\"0d849403-0f75-455d-b4e4-0d622ee3305a\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Grinning Brown\",\"description\":\"Building Powerful Solutions with Language Models.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:53:06.056636\",\"folder\":null,\"id\":\"8643ba14-52d6-4d36-9981-5fd37de5dd76\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Kickass Watt\",\"description\":\"Transform Your Business with Smart Dialogues.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:53:23.338727\",\"folder\":null,\"id\":\"818d3066-bf08-4bf9-adcd-739f8abbfa5d\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Goofy Bose\",\"description\":\"Unravel the Art of Articulation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:53:41.218861\",\"folder\":null,\"id\":\"28eff43e-0ecf-47bf-9851-f1492589978e\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Optimistic Jennings\",\"description\":\"Create Powerful Connections, Boost Business Value.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:55:03.681106\",\"folder\":null,\"id\":\"68f59069-bc2a-464f-a983-4b61e32e01af\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Pedantic Mirzakhani\",\"description\":\"Language Chainlink Master.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:55:31.761949\",\"folder\":null,\"id\":\"5d981c0e-81b3-44cc-a5be-8f55b92bfed5\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Peppy Murdock\",\"description\":\"Create Powerful Connections, Boost Business Value.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:56:45.548598\",\"folder\":null,\"id\":\"e812ad47-47e8-422b-b94c-84fd0263c9c8\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Berserk Fermat\",\"description\":\"Maximize Impact with Intelligent Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:58:50.234270\",\"folder\":null,\"id\":\"82aaf449-e737-4699-9360-929ab6108dc7\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Tiny Albattani\",\"description\":\"Your Toolkit for Text Generation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T22:59:53.946035\",\"folder\":null,\"id\":\"097cb080-274b-40ca-8dde-7900a949568a\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Cranky Kirch\",\"description\":\"Sculpting Language with Precision.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T23:00:51.745350\",\"folder\":null,\"id\":\"837d7b5f-8495-46a9-b00e-ad1b7ebb52f4\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Effervescent Kowalevski\",\"description\":\"Empowering Language Engineering.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T23:02:53.336102\",\"folder\":null,\"id\":\"3ff079c2-d9f9-4da6-a22a-423fa35670ff\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Radiant Stallman\",\"description\":\"Navigate the Linguistic Landscape, Discover Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T23:03:28.268357\",\"folder\":null,\"id\":\"c8b204dd-3d57-4bc8-aa13-1d559672e75b\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Grinning Swirles\",\"description\":\"Unleashing Linguistic Creativity.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T23:03:51.194455\",\"folder\":null,\"id\":\"a097f083-5880-4cf7-986b-51898bc68e11\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Dreamy Williams\",\"description\":\"Interactive Language Weaving.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T23:04:36.678251\",\"folder\":null,\"id\":\"d9585f63-ce76-42ce-87bc-8e69601ea5c6\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Zany Hawking\",\"description\":\"Flow into the Future of Language.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T23:05:13.672479\",\"folder\":null,\"id\":\"612a01d5-8c8d-4cc1-8c54-35626b7f4a6d\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Amazing Kilby\",\"description\":\"Your Toolkit for Text Generation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T23:10:37.047955\",\"folder\":null,\"id\":\"2d05a598-3cdf-452a-bd5d-b0e569e562e3\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Insane Cori\",\"description\":\"Empowering Communication, Enabling Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T23:18:12.426578\",\"folder\":null,\"id\":\"d1769a4a-c1e9-4d74-9273-1e76cfcf21f3\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Compassionate Tesla\",\"description\":\"Graph Your Way to Great Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T23:18:52.806238\",\"folder\":null,\"id\":\"28c5d9dd-0466-4c80-9e58-b1e061cd358d\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Jubilant Goldstine\",\"description\":\"Harness the Power of Conversational AI.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-06T23:21:44.488510\",\"folder\":null,\"id\":\"b3c57e4f-28a1-4580-bf08-a9484bdd66e8\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Elegant Curie\",\"description\":\"Building Intelligent Interactions.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:23:47.610237\",\"folder\":null,\"id\":\"28fb024e-6ba1-4f5b-83b3-4742b3b8117c\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Twinkly Chandrasekhar\",\"description\":\"Maximize Impact with Intelligent Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:24:29.824530\",\"folder\":null,\"id\":\"d2b87cf7-9167-4030-8e9f-b8d9aa0cadee\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Pensive Nobel\",\"description\":\"Crafting Dialogues that Drive Business Success.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:26:51.210699\",\"folder\":null,\"id\":\"c2c9fbac-7d97-40c2-8055-dff608df9414\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Elated Edison\",\"description\":\"Advanced NLP for Groundbreaking Business Solutions.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:27:35.822482\",\"folder\":null,\"id\":\"a55561cd-4b25-473f-bde5-884cbabb0d24\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Dazzling Lichterman\",\"description\":\"Building Linguistic Labyrinths.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:29:09.259381\",\"folder\":null,\"id\":\"9c6fe6d4-8311-4fc6-8b02-2a816d7c059d\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Distracted Bhaskara\",\"description\":\"Navigate the Networks of Conversation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:31:36.053452\",\"folder\":null,\"id\":\"ef6fc1ab-aff8-45a1-8cd5-bc8e38565e4d\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Evil Watt\",\"description\":\"Building Intelligent Interactions.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:32:26.765250\",\"folder\":null,\"id\":\"499b5351-9c09-4934-9f9d-a24be2fd8b24\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Jolly Wien\",\"description\":\"Bridging Prompts for Brilliance.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:33:23.648859\",\"folder\":null,\"id\":\"a57eda91-7f6e-410d-9990-385fe0c724f3\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Nostalgic Spence\",\"description\":\"Mapping Meaningful Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:34:22.576407\",\"folder\":null,\"id\":\"685f685e-8a1b-4b7e-9e21-6cdd72163c91\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Comical Fermat\",\"description\":\"Create, Connect, Converse.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:35:44.920540\",\"folder\":null,\"id\":\"3e061766-b834-4fa4-ba9c-b060925d9703\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Grave Volta\",\"description\":\"Maximize Impact with Intelligent Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:36:33.001572\",\"folder\":null,\"id\":\"135f2fd9-e005-40bc-a9bf-c25107388415\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Gleeful Davinci\",\"description\":\"Create Powerful Connections, Boost Business Value.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:37:16.208823\",\"folder\":null,\"id\":\"167cdb24-7e1c-475b-893a-cca2f125426c\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Hilarious Sinoussi\",\"description\":\"Language Chainlink Master.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:38:07.215401\",\"folder\":null,\"id\":\"48113cab-2c04-493f-8c2e-c8d067826aa2\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Grave Sagan\",\"description\":\"Connect the Dots, Craft Language.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:39:19.479656\",\"folder\":null,\"id\":\"28d292dc-e094-4ffe-a657-178892933267\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Cranky Hoover\",\"description\":\"Crafting Dialogues that Drive Business Success.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:40:02.895859\",\"folder\":null,\"id\":\"0c9849b7-b2d6-4d0e-8334-abfb3ae183dd\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Evil Mendeleev\",\"description\":\"Unfolding Linguistic Possibilities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:40:27.867247\",\"folder\":null,\"id\":\"d78c52e9-1941-4555-9bb9-abd01f176705\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Effervescent Dubinsky\",\"description\":\"Where Language Meets Logic.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:41:23.177402\",\"folder\":null,\"id\":\"5277a04c-b5da-4597-aaa2-a6b66ea11d02\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Cocky Poitras\",\"description\":\"Where Language Meets Logic.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:42:08.731865\",\"folder\":null,\"id\":\"b0d0c8de-4eea-484a-a068-b13e63f7e71c\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Pedantic Ptolemy\",\"description\":\"Crafting Conversations, One Node at a Time.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:42:25.658996\",\"folder\":null,\"id\":\"b6f155e2-03eb-4232-9bab-145463382fe9\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Loving Cray\",\"description\":\"Maximize Impact with Intelligent Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:43:57.530112\",\"folder\":null,\"id\":\"b75c10ca-9ecb-432b-88ab-e1847e836e22\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Effervescent Pasteur\",\"description\":\"Language Models, Mapped and Mastered.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:44:58.979393\",\"folder\":null,\"id\":\"3710eccb-e7a7-41d5-9339-d9c301515d17\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Pensive Gates\",\"description\":\"The Power of Language at Your Fingertips.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:45:42.744174\",\"folder\":null,\"id\":\"fdd2271e-92f6-4349-8c01-2ec0e9e73f13\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Determined Khorana\",\"description\":\"Beyond Text Generation - Unleashing Business Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:46:10.084684\",\"folder\":null,\"id\":\"88b49a97-0888-4fea-8d9b-6ac2cc6d158e\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Lonely Booth\",\"description\":\"Design Dialogues with Langflow.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:46:41.577750\",\"folder\":null,\"id\":\"629afe54-8796-45be-a570-e3ac79c60792\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Jubilant Mendeleev\",\"description\":\"Chain the Words, Master Language!\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:47:22.631243\",\"folder\":null,\"id\":\"7bf481b0-73fe-4f5b-a3d4-1263d9d8e827\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Clever Varahamihira\",\"description\":\"Building Powerful Solutions with Language Models.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:49:51.026960\",\"folder\":null,\"id\":\"df9e86b6-56c9-4848-9010-102615314766\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Sleepy Stallman\",\"description\":\"Empowering Language Engineering.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:50:14.932236\",\"folder\":null,\"id\":\"3e66994c-9b7a-4b85-a917-65d1959d7352\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Modest Wozniak\",\"description\":\"Advanced NLP for Groundbreaking Business Solutions.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:51:13.811894\",\"folder\":null,\"id\":\"d10f924a-5780-4255-9f41-3e102ae03e84\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Hopeful Mirzakhani\",\"description\":\"Graph Your Way to Great Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:52:23.906908\",\"folder\":null,\"id\":\"f3378fa8-ccaf-4a3b-90d6-b8ab0c4e481f\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Awesome Joule\",\"description\":\"Design, Develop, Dialogize.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:52:43.863440\",\"folder\":null,\"id\":\"deaa50e7-a8b1-46b1-856c-334ee781e1c2\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Peppy Shockley\",\"description\":\"Generate, Innovate, Communicate.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:53:43.299699\",\"folder\":null,\"id\":\"c72eac2c-d924-40c6-a102-da524216d090\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Zany Dewey\",\"description\":\"Flow into the Future of Language.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:54:18.848827\",\"folder\":null,\"id\":\"d9425324-bb60-462e-b431-90a536f2bc76\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Gloomy Joliot\",\"description\":\"Language Engineering Excellence.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:58:12.348608\",\"folder\":null,\"id\":\"621ba134-3fac-487c-98cd-96941439f1be\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Backstabbing Franklin\",\"description\":\"Craft Language Connections Here.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:58:13.491824\",\"folder\":null,\"id\":\"86ca9773-c7b7-4a1a-859a-6cbe0ddff206\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Sharp Swartz\",\"description\":\"Beyond Text Generation - Unleashing Business Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:58:13.524414\",\"folder\":null,\"id\":\"da1c02b7-d608-4498-9946-7d02f55fa103\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Serene Volta\",\"description\":\"Connect the Dots, Craft Language.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:58:13.641432\",\"folder\":null,\"id\":\"8d5dd998-6b51-4f65-8331-086a7f3b11d7\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Focused Lichterman\",\"description\":\"Crafting Dialogues that Drive Business Success.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:58:13.746120\",\"folder\":null,\"id\":\"942027d3-e2ea-48c6-8279-0a41b54e8862\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Lively Einstein\",\"description\":\"Unleashing Linguistic Creativity.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:58:13.746904\",\"folder\":null,\"id\":\"9e9b6298-1073-4297-8ecc-3c620b432e70\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Cocky Planck\",\"description\":\"Empowering Language Engineering.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:58:13.747420\",\"folder\":null,\"id\":\"7cd60c83-b797-4e60-af6d-cbc540657943\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Suspicious Zobell\",\"description\":\"Innovation in Interaction, Revolution in Revenue.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:58:13.749951\",\"folder\":null,\"id\":\"dab08306-9521-4e15-aa11-e6a6a4e210f8\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Small Knuth\",\"description\":\"Nurture NLP Nodes Here.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:59:16.772119\",\"folder\":null,\"id\":\"c9149590-636a-44f5-aaae-45a4e78fe4df\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Evil Wright\",\"description\":\"Unfolding Linguistic Possibilities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:59:52.954568\",\"folder\":null,\"id\":\"6b23b2ad-c07c-46f6-b9ad-268783d1712e\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Vibrant Lalande\",\"description\":\"Language Models, Mapped and Mastered.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:59:53.656156\",\"folder\":null,\"id\":\"ece3bcf6-a147-4559-862e-cacff9db5f48\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Happy Gauss\",\"description\":\"The Pinnacle of Prompt Generation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:59:53.717991\",\"folder\":null,\"id\":\"252b6021-ecad-4eaf-9e2f-106c4c89c496\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Gigantic Rosalind\",\"description\":\"Building Powerful Solutions with Language Models.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:59:53.736261\",\"folder\":null,\"id\":\"b8cb6d8d-c0fb-4e8d-a46e-2c608dc8a714\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Adoring Hubble\",\"description\":\"Powerful Prompts, Perfectly Positioned.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:59:53.769546\",\"folder\":null,\"id\":\"553a67db-7225-474c-978e-8a40cde2bfb2\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Pensive Mclean\",\"description\":\"Unlock the Power of AI in Your Business Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:59:53.981063\",\"folder\":null,\"id\":\"e0865007-4d80-4edf-87ab-9e8d2892d719\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Trusting Murdock\",\"description\":\"Uncover Business Opportunities with NLP.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:59:53.982286\",\"folder\":null,\"id\":\"1021cd20-66e0-4b81-9c79-bfe729774d20\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Perky Riemann\",\"description\":\"Powerful Prompts, Perfectly Positioned.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T00:59:53.983216\",\"folder\":null,\"id\":\"089074d3-8a1e-4d85-a59d-b4717090e4d3\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Small Tesla\",\"description\":\"Language Models, Unleashed.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:00:35.704142\",\"folder\":null,\"id\":\"beb49d88-255e-4db4-931b-4ab4358f1097\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Effervescent Boyd\",\"description\":\"Smart Chains, Smarter Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:01:13.569507\",\"folder\":null,\"id\":\"75b5ab8d-e0c0-43cf-912b-8578550e198a\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Small Babbage\",\"description\":\"Interactive Language Weaving.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:01:27.944868\",\"folder\":null,\"id\":\"503edd55-8f70-43e5-87fb-2324eaf62336\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Lonely Bose\",\"description\":\"Crafting Dialogues that Drive Business Success.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:02:40.122079\",\"folder\":null,\"id\":\"ae4f2992-1a23-4a43-bec6-68b823935762\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Mirthful Coulomb\",\"description\":\"Craft Meaningful Interactions, Generate Value.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:03:15.263237\",\"folder\":null,\"id\":\"a2a464db-b02a-4440-ad9e-7b552ee6c027\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Drunk Newton\",\"description\":\"Craft Meaningful Interactions, Generate Value.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:03:15.883766\",\"folder\":null,\"id\":\"1a5d9af7-5a96-4035-a09c-e15741785828\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Jovial Pasteur\",\"description\":\"Your Hub for Text Generation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:03:15.933083\",\"folder\":null,\"id\":\"04b94873-0828-41dc-a850-fd4132c9b9f1\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Playful Spence\",\"description\":\"Connect the Dots, Craft Language.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:03:15.967685\",\"folder\":null,\"id\":\"47003dc2-7884-48a3-aa66-e4185079f4d9\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Cheerful Noyce\",\"description\":\"Your Passport to Linguistic Landscapes.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:03:15.983198\",\"folder\":null,\"id\":\"13769cb4-2e15-4d54-a28a-c97dc15db58c\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Awesome Edison\",\"description\":\"Unfolding Linguistic Possibilities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:03:16.018879\",\"folder\":null,\"id\":\"453dacde-6b10-406b-a5b3-f90f44be6899\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Upbeat Snyder\",\"description\":\"Powerful Prompts, Perfectly Positioned.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:03:16.205689\",\"folder\":null,\"id\":\"9544fac9-3002-47aa-86b9-102844fe9649\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Tender Khorana\",\"description\":\"Chain the Words, Master Language!\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:03:16.243434\",\"folder\":null,\"id\":\"90498ef6-34f9-45c8-8cd0-fe6a36a26f41\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Elated Albattani\",\"description\":\"Interactive Language Weaving.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:05:07.775497\",\"folder\":null,\"id\":\"9577c416-8ce8-48f6-ad6d-ab2e003bb415\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Charming Goodall\",\"description\":\"Maximize Impact with Intelligent Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:07:52.139318\",\"folder\":null,\"id\":\"f10dc08e-b9c7-44b3-8837-b95aee2f6dbb\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Hilarious Ramanujan\",\"description\":\"Harness the Power of Conversational AI.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:08:22.448480\",\"folder\":null,\"id\":\"c864bd8c-67cd-465f-bf7d-7a35c7df37f3\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Tender Mclean\",\"description\":\"Unleashing Linguistic Creativity.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:09:56.507826\",\"folder\":null,\"id\":\"f0c13b19-ae23-40e6-88d6-d135897ee100\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Grave Hawking\",\"description\":\"Building Intelligent Interactions.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:10:27.169757\",\"folder\":null,\"id\":\"0afb91b4-8f41-4270-900a-f5de647d45ad\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Gloomy Lovelace\",\"description\":\"Your Passport to Linguistic Landscapes.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:11:02.292233\",\"folder\":null,\"id\":\"0f1e5dcf-8769-4157-b495-5f215b490107\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Fervent Kilby\",\"description\":\"Empowering Enterprises with Intelligent Interactions.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:11:46.960966\",\"folder\":null,\"id\":\"310d03d9-dd50-4946-9a27-38ee06906212\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Admiring Almeida\",\"description\":\"Language Models, Mapped and Mastered.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:12:24.475101\",\"folder\":null,\"id\":\"3cbc8fc2-a86f-4177-9a1c-a833b2a24283\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Elated Roentgen\",\"description\":\"Empowering Enterprises with Intelligent Interactions.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:06.753571\",\"folder\":null,\"id\":\"c508e922-29e9-4234-84ae-505c5bdf41c1\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Perky Poitras\",\"description\":\"Chain the Words, Master Language!\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:07.754605\",\"folder\":null,\"id\":\"1431df05-1b6f-41af-a063-a18d26a946ef\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Tender Khayyam\",\"description\":\"Navigate the Linguistic Landscape, Discover Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:07.791627\",\"folder\":null,\"id\":\"344e03fb-fd49-4e87-be67-7dce04ba655b\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Zealous Mayer\",\"description\":\"Navigate the Linguistic Landscape, Discover Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:07.803889\",\"folder\":null,\"id\":\"8b3ff1cb-3a6c-46ee-b09a-0e9f9f13a8b9\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Tiny Ramanujan\",\"description\":\"Empowering Communication, Enabling Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:07.822583\",\"folder\":null,\"id\":\"18961e76-f4b1-4968-926a-fed22cb04f69\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Cheerful Franklin\",\"description\":\"Building Intelligent Interactions.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:07.854440\",\"folder\":null,\"id\":\"0e0ee854-ab46-4333-a848-2e1239a24334\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Serene Swirles\",\"description\":\"Maximize Impact with Intelligent Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:07.988932\",\"folder\":null,\"id\":\"cc7b8238-3d15-4f78-bd0c-8311691c9ff8\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Sleepy Swartz\",\"description\":\"Uncover Business Opportunities with NLP.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:08.028688\",\"folder\":null,\"id\":\"123369f9-c83c-4ed3-93b6-78ca29c271cf\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Cranky Kowalevski\",\"description\":\"Unleashing Linguistic Creativity.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:59.097607\",\"folder\":null,\"id\":\"ed4b1490-e9e5-46bf-b337-166b48eaadd6\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Sprightly Golick\",\"description\":\"Building Powerful Solutions with Language Models.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:59.617772\",\"folder\":null,\"id\":\"9d1be311-c618-4e3e-aeb1-4161ab37850e\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Boring Newton\",\"description\":\"Generate, Innovate, Communicate.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:59.646124\",\"folder\":null,\"id\":\"63a75f99-1745-40d3-9e27-3d19a143be45\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Sprightly Noyce\",\"description\":\"Beyond Text Generation - Unleashing Business Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:59.685781\",\"folder\":null,\"id\":\"b418ca87-eb17-42e8-b789-3fcb0cab3ddb\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Fluffy Fermat\",\"description\":\"Text Generation Meets Business Transformation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:59.705984\",\"folder\":null,\"id\":\"93802b07-eee9-4a2b-8691-7d9a231bd67e\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Stoic Payne\",\"description\":\"Beyond Text Generation - Unleashing Business Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:59.723990\",\"folder\":null,\"id\":\"d62df661-0ae5-4b41-a9fb-71cb2e46ad52\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Effervescent Darwin\",\"description\":\"Unleashing Linguistic Creativity.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:59.818343\",\"folder\":null,\"id\":\"d1f62248-415c-474a-bfa6-3509a528a33b\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Focused Thompson\",\"description\":\"Transform Your Business with Smart Dialogues.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:13:59.925999\",\"folder\":null,\"id\":\"d2267176-f020-4c52-90a4-7f944d7c1749\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Admiring Dewey\",\"description\":\"Navigate the Networks of Conversation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:15:07.400402\",\"folder\":null,\"id\":\"8cf1ac8d-d34d-4e8a-a9da-be44672e1dfb\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Prickly Zuse\",\"description\":\"Where Language Meets Logic.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:15:08.384611\",\"folder\":null,\"id\":\"bae3cb5b-0f1b-4e95-bf58-7eab38da3d73\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Hungry Zuse\",\"description\":\"The Pinnacle of Prompt Generation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:15:08.436591\",\"folder\":null,\"id\":\"4dfafe3e-e9ef-405d-be72-550084411d69\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Lonely Khayyam\",\"description\":\"Design Dialogues with Langflow.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:15:08.435958\",\"folder\":null,\"id\":\"e0f81215-dc55-4b5a-b8cf-6e2fcbf297a7\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Big Mendel\",\"description\":\"Innovation in Interaction with Langflow.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:15:08.470080\",\"folder\":null,\"id\":\"5022a71c-da47-4975-a4d0-6d2d9e760d3d\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Inquisitive Poitras\",\"description\":\"Navigate the Networks of Conversation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:15:08.484430\",\"folder\":null,\"id\":\"4f1ff9e3-3500-404c-80af-2010bc46cdcb\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Joyous Jones\",\"description\":\"The Power of Language at Your Fingertips.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:15:08.661306\",\"folder\":null,\"id\":\"77af3e47-c2cc-42f6-99e1-78589439a447\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Exuberant Khayyam\",\"description\":\"Empowering Communication, Enabling Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:15:08.662877\",\"folder\":null,\"id\":\"6f3e2e56-b329-47e3-86cc-024c29203016\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Dazzling Visvesvaraya\",\"description\":\"Maximize Impact with Intelligent Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:16:10.092917\",\"folder\":null,\"id\":\"449ac0ee-ee29-4a9f-9aff-fd6a86624457\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Nostalgic Tesla\",\"description\":\"Nurture NLP Nodes Here.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:16:10.630382\",\"folder\":null,\"id\":\"a2136ed3-dc75-4a8f-ab34-6887ff955b23\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Goofy Noether\",\"description\":\"Language Models, Unleashed.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:16:10.652058\",\"folder\":null,\"id\":\"fd1080f8-db07-481a-b2ba-60f67fcb20a6\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Dazzling Pasteur\",\"description\":\"Language Models, Unleashed.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:16:10.688661\",\"folder\":null,\"id\":\"d534d5e1-92aa-4fb2-a795-7071c4feba47\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Comical Sinoussi\",\"description\":\"Bridging Prompts for Brilliance.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:16:10.741385\",\"folder\":null,\"id\":\"85323170-c066-4d8f-acb0-1b142241389e\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Small Ramanujan\",\"description\":\"Uncover Business Opportunities with NLP.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:16:10.790086\",\"folder\":null,\"id\":\"b0d18432-21ab-404b-acb6-57ef97353fad\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Sick Joliot\",\"description\":\"Text Generation Meets Business Transformation.\",\"data\":{\"nodes\":[{\"width\":384,\"height\":442,\"id\":\"OpenAIEmbeddings-rVj1B\",\"type\":\"genericNode\",\"position\":{\"x\":-100.23754663035719,\"y\":-718.7575880388187},\"data\":{\"type\":\"OpenAIEmbeddings\",\"node\":{\"template\":{\"allowed_special\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[],\"password\":false,\"name\":\"allowed_special\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"async_client\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"async_client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"chunk_size\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":1000,\"password\":false,\"name\":\"chunk_size\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"default_headers\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"default_headers\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"default_query\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"default_query\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"deployment\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"text-embedding-ada-002\",\"password\":false,\"name\":\"deployment\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"disallowed_special\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"all\",\"password\":false,\"name\":\"disallowed_special\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"embedding_ctx_length\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":8191,\"password\":false,\"name\":\"embedding_ctx_length\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"headers\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"{\\\"Authorization\\\": \\\"Bearer \\\"}\",\"password\":false,\"name\":\"headers\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"http_client\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"http_client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":2,\"password\":false,\"name\":\"max_retries\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"model\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"text-embedding-ada-002\",\"password\":false,\"name\":\"model\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_api_type\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"openai_api_type\",\"display_name\":\"OpenAI API Type\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_api_version\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"openai_api_version\",\"display_name\":\"OpenAI API Version\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"show_progress_bar\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"show_progress_bar\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"skip_empty\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"skip_empty\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tiktoken_enabled\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":true,\"password\":true,\"name\":\"tiktoken_enabled\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"OpenAIEmbeddings\"},\"description\":\"OpenAI embedding models.\",\"base_classes\":[\"OpenAIEmbeddings\",\"Embeddings\"],\"display_name\":\"OpenAIEmbeddings\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/openai\",\"beta\":false,\"error\":null},\"id\":\"OpenAIEmbeddings-rVj1B\"},\"selected\":true,\"dragging\":false,\"positionAbsolute\":{\"x\":-100.23754663035719,\"y\":-718.7575880388187}}],\"edges\":[],\"viewport\":{\"x\":267.7156633365312,\"y\":716.9644817529361,\"zoom\":0.7169776240079139}},\"is_component\":false,\"updated_at\":\"2023-12-08T18:52:26.999440\",\"folder\":null,\"id\":\"be39958a-ef42-4fa8-8e54-b611e56b5c97\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Graceful Lumiere\",\"description\":\"Conversational Cartography Unlocked.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-07T01:16:11.012069\",\"folder\":null,\"id\":\"f7dcecfd-533c-4f40-9dcb-f213962ed1a2\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"aaaaa\",\"description\":\"Text Generation Meets Business Transformation.\",\"data\":{\"nodes\":[{\"width\":384,\"height\":442,\"id\":\"OpenAIEmbeddings-P6Z0D\",\"type\":\"genericNode\",\"position\":{\"x\":-100.23754663035719,\"y\":-718.7575880388187},\"data\":{\"type\":\"OpenAIEmbeddings\",\"node\":{\"template\":{\"allowed_special\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[],\"password\":false,\"name\":\"allowed_special\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"async_client\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"async_client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"chunk_size\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":1000,\"password\":false,\"name\":\"chunk_size\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"default_headers\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"default_headers\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"default_query\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"default_query\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"deployment\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"text-embedding-ada-002\",\"password\":false,\"name\":\"deployment\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"disallowed_special\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"all\",\"password\":false,\"name\":\"disallowed_special\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"embedding_ctx_length\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":8191,\"password\":false,\"name\":\"embedding_ctx_length\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"headers\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"{\\\"Authorization\\\": \\\"Bearer \\\"}\",\"password\":false,\"name\":\"headers\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"http_client\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"http_client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":2,\"password\":false,\"name\":\"max_retries\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"model\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"text-embedding-ada-002\",\"password\":false,\"name\":\"model\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_api_type\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"openai_api_type\",\"display_name\":\"OpenAI API Type\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"},\"openai_api_version\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"openai_api_version\",\"display_name\":\"OpenAI API Version\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"show_progress_bar\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"show_progress_bar\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"skip_empty\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"skip_empty\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tiktoken_enabled\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":true,\"password\":true,\"name\":\"tiktoken_enabled\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"},\"_type\":\"OpenAIEmbeddings\"},\"description\":\"OpenAI embedding models.\",\"base_classes\":[\"OpenAIEmbeddings\",\"Embeddings\"],\"display_name\":\"OpenAIEmbeddings\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/openai\",\"beta\":false,\"error\":null},\"id\":\"OpenAIEmbeddings-P6Z0D\"},\"selected\":true,\"dragging\":false,\"positionAbsolute\":{\"x\":-100.23754663035719,\"y\":-718.7575880388187}}],\"edges\":[],\"viewport\":{\"x\":266.7156633365312,\"y\":657.9644817529361,\"zoom\":0.7169776240079139}},\"is_component\":false,\"updated_at\":\"2023-12-08T19:05:14.503144\",\"folder\":null,\"id\":\"c2411a20-57c6-44cc-a0d0-2c857453633d\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Lively Aryabhata\",\"description\":\"Design, Develop, Dialogize.\",\"data\":{\"nodes\":[{\"width\":384,\"height\":459,\"id\":\"CustomComponent-Qhbd7\",\"type\":\"genericNode\",\"position\":{\"x\":-224.36198532285903,\"y\":-39.03047722134913},\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\nfrom openai import OpenAI\\n\\n\\nclass Component(CustomComponent):\\n display_name: str = \\\"OpenAI STT english translator\\\"\\n description: str = \\\"Transcript and translate any audio to english\\\"\\n documentation: str = \\\"http://docs.langflow.org/components/custom\\\"\\n\\n def build_config(self):\\n return {\\\"audio_path\\\":{\\\"display_name\\\":\\\"Audio path\\\",\\\"input_types\\\":[\\\"str\\\"]},\\\"openAI_key\\\":{\\\"display_name\\\":\\\"OpenAI key\\\",\\\"password\\\":True}}\\n\\n def build(self,audio_path:str,openAI_key:str) -> str:\\n client = OpenAI(api_key=openAI_key)\\n audio_file= open(audio_path, \\\"rb\\\")\\n transcript = client.audio.translations.create(\\n model=\\\"whisper-1\\\", \\n file=audio_file\\n )\\n self.status = transcript.text\\n return transcript.text\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"audio_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"audio_path\",\"display_name\":\"Audio path\",\"advanced\":false,\"input_types\":[\"str\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"aaaaa\"},\"openAI_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"openAI_key\",\"display_name\":\"OpenAI key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"}},\"description\":\"Transcript and translate any audio to english\",\"base_classes\":[\"str\"],\"display_name\":\"OpenAI STT english tra\",\"custom_fields\":{\"audio_path\":null,\"openAI_key\":null},\"output_types\":[\"str\"],\"documentation\":\"http://docs.langflow.org/components/custom\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"CustomComponent-Qhbd7\"},\"selected\":true,\"dragging\":false,\"positionAbsolute\":{\"x\":-224.36198532285903,\"y\":-39.03047722134913}}],\"edges\":[],\"viewport\":{\"x\":433.8372868055629,\"y\":250.9611989970935,\"zoom\":0.8467453123625275}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:16:56.971879\",\"folder\":null,\"id\":\"122eee5d-9734-4e51-9da5-b39bead64a8d\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Goofy Wing\",\"description\":\"Your Toolkit for Text Generation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:18:23.227017\",\"folder\":null,\"id\":\"171d0063-6446-4c6a-8f5b-786a38951d44\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Mad Boyd\",\"description\":\"Empowering Language Engineering.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:18:24.063781\",\"folder\":null,\"id\":\"3a7af50c-6555-4004-a86e-1ea37e477900\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Boring Dewey\",\"description\":\"Unleashing Linguistic Creativity.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:18:24.065404\",\"folder\":null,\"id\":\"dc4b4235-a550-41e2-9ddb-bcb352a1bc03\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Nauseous Carroll\",\"description\":\"Navigate the Networks of Conversation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:18:24.087501\",\"folder\":null,\"id\":\"9550e2bf-db7a-41f5-84e5-177a181bbeda\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Silly Engelbart\",\"description\":\"Generate, Innovate, Communicate.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:18:24.112543\",\"folder\":null,\"id\":\"6a3a24bb-01cb-4d8e-8d17-0dc92d257322\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Sassy Khayyam\",\"description\":\"Innovation in Interaction, Revolution in Revenue.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:18:24.147631\",\"folder\":null,\"id\":\"8d372f5e-ca12-4ea8-a1a1-8846afa72692\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Mirthful Bell\",\"description\":\"Connect the Dots, Craft Language.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:18:24.212921\",\"folder\":null,\"id\":\"800f8785-0f41-4db3-aef8-9e3de5250526\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Sleepy Bassi\",\"description\":\"Unleashing Business Potential through Language Engineering.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:18:24.395729\",\"folder\":null,\"id\":\"4589607a-065b-4a8f-ba52-5045d7b04086\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Lonely Volhard\",\"description\":\"Where Language Meets Logic.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:20:33.263971\",\"folder\":null,\"id\":\"b2440ed8-44fa-4684-adf7-b5e84bff6577\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Ecstatic Poincare\",\"description\":\"Your Passport to Linguistic Landscapes.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:20:33.377270\",\"folder\":null,\"id\":\"b996f514-e0b8-432f-969b-7276630a8f4b\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Grave Zuse\",\"description\":\"Text Generation Meets Business Transformation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:20:33.406385\",\"folder\":null,\"id\":\"6e2e9c12-0afc-499e-acdd-adf4b5f7d4fc\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Big Hopper\",\"description\":\"Conversation Catalyst Engine.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:20:33.413014\",\"folder\":null,\"id\":\"e020f1a5-aa12-45e7-ba50-6eb64a735e60\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Gleeful Jang\",\"description\":\"Conversation Catalyst Engine.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:20:33.433045\",\"folder\":null,\"id\":\"ee58f892-b7b2-408e-b4b9-9d862fc315aa\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Twinkly Ohm\",\"description\":\"Promptly Ingenious!\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:20:33.403404\",\"folder\":null,\"id\":\"023a1fc3-8807-4167-b6b2-f4e5daf036f1\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Distracted Degrasse\",\"description\":\"Bridging Prompts for Brilliance.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:20:33.411655\",\"folder\":null,\"id\":\"085f106f-c1e9-4a0f-ba31-d2fafe685d9c\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Exuberant Volta\",\"description\":\"Catalyzing Business Growth through Conversational AI.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:20:33.408697\",\"folder\":null,\"id\":\"14481bb5-1353-452f-9359-d38c9419d79c\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Goofy Bose\",\"description\":\"Conversational Cartography Unlocked.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:22:21.774940\",\"folder\":null,\"id\":\"e9316292-4ee1-441b-8327-0b09a7831fe9\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Thirsty Easley\",\"description\":\"Language Models, Mapped and Mastered.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:22:22.416556\",\"folder\":null,\"id\":\"668806ba-3efa-44de-aeb7-4ac082ba9172\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Joyous Mestorf\",\"description\":\"Generate, Innovate, Communicate.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:22:22.484048\",\"folder\":null,\"id\":\"3fc0a371-aada-4450-9d17-33d3cc05c870\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Playful Franklin\",\"description\":\"Empowering Language Engineering.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:22:22.509095\",\"folder\":null,\"id\":\"af967c98-5f08-4ee2-b1ce-6c16b4f9ebe2\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Goofy Bhaskara\",\"description\":\"Empowering Enterprises with Intelligent Interactions.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:22:22.508465\",\"folder\":null,\"id\":\"758c4164-b521-45d0-a15f-d49480e312eb\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Funky Edison\",\"description\":\"Unravel the Art of Articulation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:22:22.602296\",\"folder\":null,\"id\":\"f9d3d30f-8859-433f-bafc-ccf1a7196e35\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Silly Ride\",\"description\":\"Unfolding Linguistic Possibilities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:22:22.604061\",\"folder\":null,\"id\":\"0142bca5-eb61-42ed-9917-70c4c0f54eb0\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Goofy Noyce\",\"description\":\"Text Generation Meets Business Transformation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:22:22.603113\",\"folder\":null,\"id\":\"0b63d036-4669-4ceb-8ea4-34035340df77\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Cocky Bhabha\",\"description\":\"Language Engineering Excellence.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:23:07.345767\",\"folder\":null,\"id\":\"8b9a66d4-a924-4b84-a2b5-5dd0645ac07a\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Thirsty Zobell\",\"description\":\"Unleashing Business Potential through Language Engineering.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:23:07.722319\",\"folder\":null,\"id\":\"c912fd6b-b32d-409f-a0e5-c6249b066429\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Fervent Shaw\",\"description\":\"Language Architect at Work!\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:23:07.750779\",\"folder\":null,\"id\":\"9d755cd4-c652-43e0-a68d-75a5475ce7a3\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Giggly Newton\",\"description\":\"Navigate the Linguistic Landscape, Discover Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:23:07.786602\",\"folder\":null,\"id\":\"0d3af7de-1ada-4c43-a69f-1bfad370ccfc\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Modest Yalow\",\"description\":\"Text Generation Meets Business Transformation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:23:07.792245\",\"folder\":null,\"id\":\"b6444376-4162-436b-8b40-f5a6afc850db\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Sad Bhabha\",\"description\":\"Empowering Enterprises with Intelligent Interactions.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:23:07.890349\",\"folder\":null,\"id\":\"d90af439-fb34-4d27-98f2-06f7f9a9ed8c\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Spirited Hoover\",\"description\":\"The Pinnacle of Prompt Generation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:23:07.905750\",\"folder\":null,\"id\":\"31597ce2-de3c-490b-9ead-3f702f63cfd9\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Trusting Davinci\",\"description\":\"Design, Develop, Dialogize.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-08T21:23:08.001400\",\"folder\":null,\"id\":\"b43c63e9-a257-4a53-8acc-049e13706ac2\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"23\",\"description\":\"23\",\"data\":{\"nodes\":[{\"width\":384,\"height\":467,\"id\":\"PromptTemplate-K7xiS\",\"type\":\"genericNode\",\"position\":{\"x\":-658.2250903773149,\"y\":809.352046606987},\"data\":{\"type\":\"PromptTemplate\",\"node\":{\"template\":{\"output_parser\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"BaseOutputParser\",\"list\":false},\"input_types\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_types\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"input_variables\":{\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":true,\"value\":[\"dasdas\",\"dasdasd\"]},\"partial_variables\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"partial_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"template\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"password\":false,\"name\":\"template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"prompt\",\"list\":false,\"value\":\"{dasdas}\\n{dasdasd}\\n\"},\"template_format\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"f-string\",\"password\":false,\"name\":\"template_format\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":false},\"validate_template\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"validate_template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"PromptTemplate\",\"dasdas\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"dasdas\",\"display_name\":\"dasdas\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"dasdasd\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"dasdasd\",\"display_name\":\"dasdasd\",\"advanced\":false,\"input_types\":[\"Document\",\"BaseOutputParser\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"A prompt template for a language model.\",\"base_classes\":[\"PromptTemplate\",\"BasePromptTemplate\",\"StringPromptTemplate\"],\"name\":\"\",\"display_name\":\"PromptTemplate\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/\",\"custom_fields\":{\"\":[\"dasdas\",\"dasdasd\"]},\"output_types\":[],\"full_path\":null,\"field_formatters\":{},\"beta\":false,\"error\":null},\"id\":\"PromptTemplate-K7xiS\"},\"selected\":false,\"positionAbsolute\":{\"x\":-658.2250903773149,\"y\":809.352046606987},\"dragging\":false},{\"width\":384,\"height\":366,\"id\":\"AirbyteJSONLoader-DXfcM\",\"type\":\"genericNode\",\"position\":{\"x\":-1110.8267574563533,\"y\":569.1107380883907},\"data\":{\"type\":\"AirbyteJSONLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"suffixes\":[\".json\"],\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\"json\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"\":\"\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"AirbyteJSONLoader\"},\"description\":\"Load local `Airbyte` json files.\",\"base_classes\":[\"Document\"],\"display_name\":\"AirbyteJSONLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/airbyte_json\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"AirbyteJSONLoader-DXfcM\"},\"selected\":false,\"positionAbsolute\":{\"x\":-1110.8267574563533,\"y\":569.1107380883907},\"dragging\":false},{\"width\":384,\"height\":376,\"id\":\"PromptRunner-ckWMH\",\"type\":\"genericNode\",\"position\":{\"x\":-1149.4746387825978,\"y\":992.3970573758324},\"data\":{\"type\":\"PromptRunner\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\n\\nfrom langchain.llms.base import BaseLLM\\nfrom langchain.prompts import PromptTemplate\\nfrom langchain.schema import Document\\n\\n\\nclass PromptRunner(CustomComponent):\\n display_name: str = \\\"Prompt Runner\\\"\\n description: str = \\\"Run a Chain with the given PromptTemplate\\\"\\n beta: bool = True\\n field_config = {\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"prompt\\\": {\\n \\\"display_name\\\": \\\"Prompt Template\\\",\\n \\\"info\\\": \\\"Make sure the prompt has all variables filled.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(self, llm: BaseLLM, prompt: PromptTemplate, inputs: dict = {}) -> Document:\\n chain = prompt | llm\\n # The input is an empty dict because the prompt is already filled\\n result = chain.invoke(input=inputs)\\n if hasattr(result, \\\"content\\\"):\\n result = result.content\\n self.repr_value = result\\n return Document(page_content=str(result))\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"inputs\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"\":\"\"}],\"password\":false,\"name\":\"inputs\",\"display_name\":\"inputs\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLLM\",\"list\":false},\"prompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"prompt\",\"display_name\":\"Prompt Template\",\"advanced\":false,\"dynamic\":false,\"info\":\"Make sure the prompt has all variables filled.\",\"type\":\"PromptTemplate\",\"list\":false}},\"description\":\"Run a Chain with the given PromptTemplate\",\"base_classes\":[\"Document\"],\"display_name\":\"Prompt Runner\",\"custom_fields\":{\"inputs\":null,\"llm\":null,\"prompt\":null},\"output_types\":[\"PromptRunner\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"id\":\"PromptRunner-ckWMH\"},\"selected\":false,\"positionAbsolute\":{\"x\":-1149.4746387825978,\"y\":992.3970573758324},\"dragging\":false}],\"edges\":[{\"source\":\"PromptRunner-ckWMH\",\"sourceHandle\":\"{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œPromptRunnerœ,œidœ:œPromptRunner-ckWMHœ}\",\"target\":\"PromptTemplate-K7xiS\",\"targetHandle\":\"{œfieldNameœ:œdasdasdœ,œidœ:œPromptTemplate-K7xiSœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"dasdasd\",\"id\":\"PromptTemplate-K7xiS\",\"inputTypes\":[\"Document\",\"BaseOutputParser\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"Document\"],\"dataType\":\"PromptRunner\",\"id\":\"PromptRunner-ckWMH\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-PromptRunner-ckWMH{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œPromptRunnerœ,œidœ:œPromptRunner-ckWMHœ}-PromptTemplate-K7xiS{œfieldNameœ:œdasdasdœ,œidœ:œPromptTemplate-K7xiSœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\"},{\"source\":\"AirbyteJSONLoader-DXfcM\",\"sourceHandle\":\"{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œAirbyteJSONLoaderœ,œidœ:œAirbyteJSONLoader-DXfcMœ}\",\"target\":\"PromptTemplate-K7xiS\",\"targetHandle\":\"{œfieldNameœ:œdasdasœ,œidœ:œPromptTemplate-K7xiSœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\",\"data\":{\"targetHandle\":{\"fieldName\":\"dasdas\",\"id\":\"PromptTemplate-K7xiS\",\"inputTypes\":[\"Document\",\"BaseOutputParser\"],\"type\":\"str\"},\"sourceHandle\":{\"baseClasses\":[\"Document\"],\"dataType\":\"AirbyteJSONLoader\",\"id\":\"AirbyteJSONLoader-DXfcM\"}},\"style\":{\"stroke\":\"#555\"},\"className\":\"stroke-gray-900 stroke-connection\",\"animated\":false,\"id\":\"reactflow__edge-AirbyteJSONLoader-DXfcM{œbaseClassesœ:[œDocumentœ],œdataTypeœ:œAirbyteJSONLoaderœ,œidœ:œAirbyteJSONLoader-DXfcMœ}-PromptTemplate-K7xiS{œfieldNameœ:œdasdasœ,œidœ:œPromptTemplate-K7xiSœ,œinputTypesœ:[œDocumentœ,œBaseOutputParserœ],œtypeœ:œstrœ}\"}],\"viewport\":{\"x\":721.09842496776,\"y\":-303.59762799439625,\"zoom\":0.6417129487814537}},\"is_component\":false,\"updated_at\":\"2023-12-08T22:52:14.560323\",\"folder\":null,\"id\":\"8533c46e-21fd-4b92-b68e-1086ea86c72d\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Twinkly Stonebraker\",\"description\":\"Navigate the Linguistic Landscape, Discover Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-09T13:26:42.332360\",\"folder\":null,\"id\":\"92bc0875-4a73-44f2-9410-3b8342e404bf\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Metaphor Search (1)\",\"description\":\"Search in Metaphor with a custom string.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom typing import List, Union\\nfrom langchain.llms.base import BaseLLM\\nfrom langchain.chains import LLMChain\\nfrom langchain import PromptTemplate\\nfrom langchain.schema import Document\\nfrom metaphor_python import Metaphor\\nimport json\\n\\nfrom typing import List\\nfrom langflow.field_typing import Data\\n\\nclass MetaphorSearch(CustomComponent):\\n display_name: str = \\\"Metaphor Search\\\"\\n description: str = \\\"Search in Metaphor with a custom string.\\\"\\n beta = True\\n \\n def build_config(self):\\n return {\\n \\\"metaphor_client\\\": {\\\"display_name\\\": \\\"Metaphor Wrapper\\\"}, \\n \\\"search_num_results\\\": {\\\"display_name\\\": \\\"Number of Results (per domain)\\\"},\\n \\\"include_domains\\\": {\\\"display_name\\\": \\\"Include Domains\\\", \\\"is_list\\\": True},\\n \\\"start_date\\\": {\\\"display_name\\\": \\\"Start Date\\\"},\\n \\\"use_autoprompt\\\": {\\\"display_name\\\": \\\"Use Autoprompt\\\", \\\"type\\\": \\\"boolean\\\"},\\n \\\"search_type\\\": {\\\"display_name\\\": \\\"Search Type\\\", \\\"options\\\": [\\\"neural\\\", \\\"keyword\\\"]},\\n \\\"start_date\\\": {\\\"input_types\\\": [\\\"Data\\\"]}\\n }\\n\\n def build(\\n self,\\n methaphor_client: Data,\\n query: str,\\n search_type: str='keyword',\\n search_num_results: int = 5,\\n include_domains: List[str]= [\\\"youtube.com\\\"],\\n use_autoprompt: bool = False,\\n start_date: str=\\\"2023-01-01\\\",\\n \\n ) -> Data:\\n \\n results = []\\n for domain in include_domains:\\n response = methaphor_client.search(\\n query,\\n num_results=int(search_num_results),\\n include_domains=[domain],\\n use_autoprompt=use_autoprompt,\\n type=search_type,\\n # start_crawl_date=start_date,\\n start_published_date=start_date\\n )\\n results.extend(response.results)\\n \\n self.repr_value = results\\n\\n return results\\n\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"include_domains\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[\"yout\"],\"password\":false,\"name\":\"include_domains\",\"display_name\":\"Include Domains\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"methaphor_client\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"methaphor_client\",\"display_name\":\"methaphor_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Data\",\"list\":false},\"query\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"query\",\"display_name\":\"query\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"pasteldasdasdas\"},\"search_num_results\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":5,\"password\":false,\"name\":\"search_num_results\",\"display_name\":\"Number of Results (per domain)\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"search_type\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"keyword\",\"password\":false,\"options\":[\"neural\",\"keyword\"],\"name\":\"search_type\",\"display_name\":\"Search Type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"start_date\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"start_date\",\"display_name\":\"start_date\",\"advanced\":false,\"input_types\":[\"Data\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"use_autoprompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"use_autoprompt\",\"display_name\":\"Use Autoprompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false}},\"description\":\"Search in Metaphor with a custom string.\",\"base_classes\":[\"Data\"],\"display_name\":\"Metaphor Search\",\"custom_fields\":{\"include_domains\":null,\"methaphor_client\":null,\"query\":null,\"search_num_results\":null,\"search_type\":null,\"start_date\":null,\"use_autoprompt\":null},\"output_types\":[\"Data\"],\"documentation\":\"\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"CustomComponent-dMB5d\"},\"id\":\"CustomComponent-dMB5d\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T13:26:43.668665\",\"folder\":null,\"id\":\"912265df-9b87-4b30-a585-1ca59b944391\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Metaphor Search (2)\",\"description\":\"Search in Metaphor with a custom string.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom typing import List, Union\\nfrom langchain.llms.base import BaseLLM\\nfrom langchain.chains import LLMChain\\nfrom langchain import PromptTemplate\\nfrom langchain.schema import Document\\nfrom metaphor_python import Metaphor\\nimport json\\n\\nfrom typing import List\\nfrom langflow.field_typing import Data\\n\\nclass MetaphorSearch(CustomComponent):\\n display_name: str = \\\"Metaphor Search\\\"\\n description: str = \\\"Search in Metaphor with a custom string.\\\"\\n beta = True\\n \\n def build_config(self):\\n return {\\n \\\"metaphor_client\\\": {\\\"display_name\\\": \\\"Metaphor Wrapper\\\"}, \\n \\\"search_num_results\\\": {\\\"display_name\\\": \\\"Number of Results (per domain)\\\"},\\n \\\"include_domains\\\": {\\\"display_name\\\": \\\"Include Domains\\\", \\\"is_list\\\": True},\\n \\\"start_date\\\": {\\\"display_name\\\": \\\"Start Date\\\"},\\n \\\"use_autoprompt\\\": {\\\"display_name\\\": \\\"Use Autoprompt\\\", \\\"type\\\": \\\"boolean\\\"},\\n \\\"search_type\\\": {\\\"display_name\\\": \\\"Search Type\\\", \\\"options\\\": [\\\"neural\\\", \\\"keyword\\\"]},\\n \\\"start_date\\\": {\\\"input_types\\\": [\\\"Data\\\"]}\\n }\\n\\n def build(\\n self,\\n methaphor_client: Data,\\n query: str,\\n search_type: str='keyword',\\n search_num_results: int = 5,\\n include_domains: List[str]= [\\\"youtube.com\\\"],\\n use_autoprompt: bool = False,\\n start_date: str=\\\"2023-01-01\\\",\\n \\n ) -> Data:\\n \\n results = []\\n for domain in include_domains:\\n response = methaphor_client.search(\\n query,\\n num_results=int(search_num_results),\\n include_domains=[domain],\\n use_autoprompt=use_autoprompt,\\n type=search_type,\\n # start_crawl_date=start_date,\\n start_published_date=start_date\\n )\\n results.extend(response.results)\\n \\n self.repr_value = results\\n\\n return results\\n\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"include_domains\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[\"yout\"],\"password\":false,\"name\":\"include_domains\",\"display_name\":\"Include Domains\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"methaphor_client\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"methaphor_client\",\"display_name\":\"methaphor_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Data\",\"list\":false},\"query\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"query\",\"display_name\":\"query\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"pasteldasdasdas\"},\"search_num_results\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":5,\"password\":false,\"name\":\"search_num_results\",\"display_name\":\"Number of Results (per domain)\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"search_type\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"keyword\",\"password\":false,\"options\":[\"neural\",\"keyword\"],\"name\":\"search_type\",\"display_name\":\"Search Type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"start_date\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"start_date\",\"display_name\":\"start_date\",\"advanced\":false,\"input_types\":[\"Data\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"use_autoprompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"use_autoprompt\",\"display_name\":\"Use Autoprompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false}},\"description\":\"Search in Metaphor with a custom string.\",\"base_classes\":[\"Data\"],\"display_name\":\"Metaphor Search\",\"custom_fields\":{\"include_domains\":null,\"methaphor_client\":null,\"query\":null,\"search_num_results\":null,\"search_type\":null,\"start_date\":null,\"use_autoprompt\":null},\"output_types\":[\"Data\"],\"documentation\":\"\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"CustomComponent-ipifC\"},\"id\":\"CustomComponent-ipifC\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T13:26:49.799612\",\"folder\":null,\"id\":\"ca83ee08-2f93-427d-9897-80fef6dd5447\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Metaphor Search\",\"description\":\"Search in Metaphor with a custom string.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CustomComponent\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom typing import List, Union\\nfrom langchain.llms.base import BaseLLM\\nfrom langchain.chains import LLMChain\\nfrom langchain import PromptTemplate\\nfrom langchain.schema import Document\\nfrom metaphor_python import Metaphor\\nimport json\\n\\nfrom typing import List\\nfrom langflow.field_typing import Data\\n\\nclass MetaphorSearch(CustomComponent):\\n display_name: str = \\\"Metaphor Search\\\"\\n description: str = \\\"Search in Metaphor with a custom string.\\\"\\n beta = True\\n \\n def build_config(self):\\n return {\\n \\\"metaphor_client\\\": {\\\"display_name\\\": \\\"Metaphor Wrapper\\\"}, \\n \\\"search_num_results\\\": {\\\"display_name\\\": \\\"Number of Results (per domain)\\\"},\\n \\\"include_domains\\\": {\\\"display_name\\\": \\\"Include Domains\\\", \\\"is_list\\\": True},\\n \\\"start_date\\\": {\\\"display_name\\\": \\\"Start Date\\\"},\\n \\\"use_autoprompt\\\": {\\\"display_name\\\": \\\"Use Autoprompt\\\", \\\"type\\\": \\\"boolean\\\"},\\n \\\"search_type\\\": {\\\"display_name\\\": \\\"Search Type\\\", \\\"options\\\": [\\\"neural\\\", \\\"keyword\\\"]},\\n \\\"start_date\\\": {\\\"input_types\\\": [\\\"Data\\\"]}\\n }\\n\\n def build(\\n self,\\n methaphor_client: Data,\\n query: str,\\n search_type: str='keyword',\\n search_num_results: int = 5,\\n include_domains: List[str]= [\\\"youtube.com\\\"],\\n use_autoprompt: bool = False,\\n start_date: str=\\\"2023-01-01\\\",\\n \\n ) -> Data:\\n \\n results = []\\n for domain in include_domains:\\n response = methaphor_client.search(\\n query,\\n num_results=int(search_num_results),\\n include_domains=[domain],\\n use_autoprompt=use_autoprompt,\\n type=search_type,\\n # start_crawl_date=start_date,\\n start_published_date=start_date\\n )\\n results.extend(response.results)\\n \\n self.repr_value = results\\n\\n return results\\n\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"include_domains\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[\"yout\"],\"password\":false,\"name\":\"include_domains\",\"display_name\":\"Include Domains\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"methaphor_client\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"methaphor_client\",\"display_name\":\"methaphor_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Data\",\"list\":false},\"query\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"query\",\"display_name\":\"query\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"pasteldasdasdas\"},\"search_num_results\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":5,\"password\":false,\"name\":\"search_num_results\",\"display_name\":\"Number of Results (per domain)\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"search_type\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"keyword\",\"password\":false,\"options\":[\"neural\",\"keyword\"],\"name\":\"search_type\",\"display_name\":\"Search Type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"start_date\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"start_date\",\"display_name\":\"start_date\",\"advanced\":false,\"input_types\":[\"Data\"],\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"use_autoprompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"use_autoprompt\",\"display_name\":\"Use Autoprompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false}},\"description\":\"Search in Metaphor with a custom string.\",\"base_classes\":[\"Data\"],\"display_name\":\"Metaphor Search\",\"custom_fields\":{\"include_domains\":null,\"methaphor_client\":null,\"query\":null,\"search_num_results\":null,\"search_type\":null,\"start_date\":null,\"use_autoprompt\":null},\"output_types\":[\"Data\"],\"documentation\":\"\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"CustomComponent-Y4qL7\"},\"id\":\"CustomComponent-Y4qL7\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T13:26:53.719960\",\"folder\":null,\"id\":\"5847602b-769a-4a82-82e8-a70f54a59929\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Lively Williams\",\"description\":\"Conversational Cartography Unlocked.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-09T13:27:45.691254\",\"folder\":null,\"id\":\"0e3bdba9-127a-4399-81a4-2865b70a4a47\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Shared Component\",\"description\":\"Conversational Cartography Unlocked.\",\"data\":{\"nodes\":[{\"width\":384,\"height\":328,\"id\":\"CSVAgent-TK9Ea\",\"type\":\"genericNode\",\"position\":{\"x\":251.25514772667083,\"y\":160.7424529887874},\"data\":{\"type\":\"CSVAgent\",\"node\":{\"template\":{\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".csv\"],\"file_path\":null},\"_type\":\"csv_agent\"},\"description\":\"Construct a CSV agent from a CSV and tools.\",\"base_classes\":[\"AgentExecutor\"],\"display_name\":\"CSVAgent\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/agents/toolkits/csv\",\"beta\":false,\"error\":null},\"id\":\"CSVAgent-TK9Ea\"},\"positionAbsolute\":{\"x\":251.25514772667083,\"y\":160.7424529887874}}],\"edges\":[],\"viewport\":{\"x\":104.85568116317398,\"y\":88.26375874183478,\"zoom\":0.7169776240079145}},\"is_component\":false,\"updated_at\":\"2023-12-09T13:28:34.119070\",\"folder\":null,\"id\":\"29c1a247-47b0-457b-8666-7c0a67dc72b0\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"teste cristhian\",\"description\":\"11111\",\"data\":{\"nodes\":[{\"width\":384,\"height\":328,\"id\":\"CSVAgent-P5wrB\",\"type\":\"genericNode\",\"position\":{\"x\":251.25514772667083,\"y\":160.7424529887874},\"data\":{\"type\":\"CSVAgent\",\"node\":{\"template\":{\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".csv\"],\"file_path\":null},\"_type\":\"csv_agent\"},\"description\":\"Construct a CSV agent from a CSV and tools.\",\"base_classes\":[\"AgentExecutor\"],\"display_name\":\"CSVAgent\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/agents/toolkits/csv\",\"beta\":false,\"error\":null},\"id\":\"CSVAgent-P5wrB\"},\"positionAbsolute\":{\"x\":251.25514772667083,\"y\":160.7424529887874}},{\"width\":384,\"height\":626,\"id\":\"OpenAI-zpihD\",\"type\":\"genericNode\",\"position\":{\"x\":-56.983202536768374,\"y\":61.715652677908665},\"data\":{\"type\":\"OpenAI\",\"node\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"list\":true},\"allowed_special\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":[],\"password\":false,\"name\":\"allowed_special\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"async_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"async_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"batch_size\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":20,\"password\":false,\"name\":\"batch_size\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"best_of\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"best_of\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"default_headers\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"default_query\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_query\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"disallowed_special\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"all\",\"password\":false,\"name\":\"disallowed_special\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"frequency_penalty\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":0,\"password\":false,\"name\":\"frequency_penalty\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"http_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"http_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"logit_bias\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"logit_bias\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":2,\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"max_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":true,\"name\":\"max_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"text-babbage-001\",\"password\":false,\"options\":[\"text-davinci-003\",\"text-davinci-002\",\"text-curie-001\",\"text-babbage-001\",\"text-ada-001\"],\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"n\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"n\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":false,\"dynamic\":false,\"info\":\"\\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\\n\",\"type\":\"str\",\"list\":false,\"value\":\"dasdasdasdsadasdas\"},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"presence_penalty\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":0,\"password\":false,\"name\":\"presence_penalty\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"1.4\",\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"top_p\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"top_p\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"OpenAI\"},\"description\":\"OpenAI large language models.\",\"base_classes\":[\"OpenAI\",\"BaseLanguageModel\",\"BaseLLM\",\"BaseOpenAI\"],\"display_name\":\"OpenAI\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/openai\",\"beta\":false,\"error\":null},\"id\":\"OpenAI-zpihD\"},\"selected\":true,\"dragging\":false,\"positionAbsolute\":{\"x\":-56.983202536768374,\"y\":61.715652677908665}}],\"edges\":[],\"viewport\":{\"x\":104.85568116317398,\"y\":88.26375874183478,\"zoom\":0.7169776240079145}},\"is_component\":false,\"updated_at\":\"2023-12-09T13:40:48.453096\",\"folder\":null,\"id\":\"2e59d013-2acb-49a6-915b-9231a7e6eb58\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"CSVAgent (1)\",\"description\":\"Construct a CSV agent from a CSV and tools.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CSVAgent\",\"node\":{\"template\":{\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".csv\"],\"file_path\":null},\"_type\":\"csv_agent\"},\"description\":\"Construct a CSV agent from a CSV and tools.\",\"base_classes\":[\"AgentExecutor\"],\"display_name\":\"CSVAgent\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/agents/toolkits/csv\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"CSVAgent-jsHqy\"},\"id\":\"CSVAgent-jsHqy\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T13:31:17.317322\",\"folder\":null,\"id\":\"ab1034a9-9b5b-4c65-bf6e-9f098a403942\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Suspicious Wilsonfasdfsd\",\"description\":\"Building Linguistic Labyrinths.fasdfads\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-09T14:43:45.298121\",\"folder\":null,\"id\":\"7d91c0c5-fba6-4c60-b4d1-11d430ef357a\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"AirbyteJSONLoader (1)\",\"description\":\"Load local `Airbyte` json files.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"AirbyteJSONLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".json\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"\":\"\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"AirbyteJSONLoader\"},\"description\":\"Load local `Airbyte` json files.\",\"base_classes\":[\"Document\"],\"display_name\":\"AirbyteJSONLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/airbyte_json\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"AirbyteJSONLoader-pAHh6\"},\"id\":\"AirbyteJSONLoader-pAHh6\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T13:47:58.573137\",\"folder\":null,\"id\":\"f0cc4292-97cc-4748-803d-949e30dcf661\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"AirbyteJSONLoader\",\"description\":\"Load local `Airbyte` json files.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"AirbyteJSONLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".json\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"ff2\":\"d3bbd\"},{\"w\":\"bvd\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"AirbyteJSONLoader\"},\"description\":\"Load local `Airbyte` json files.\",\"base_classes\":[\"Document\"],\"display_name\":\"AirbyteJSONLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/airbyte_json\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"AirbyteJSONLoader-0zU2Q\"},\"id\":\"AirbyteJSONLoader-0zU2Q\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T13:50:09.035318\",\"folder\":null,\"id\":\"5e3c0d55-1a00-4e15-9821-0c625c6415ff\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"CSVAgent\",\"description\":\"Construct a CSV agent from a CSV and tools.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CSVAgent\",\"node\":{\"template\":{\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".csv\"],\"file_path\":null},\"_type\":\"csv_agent\"},\"description\":\"Construct a CSV agent from a CSV and tools.\",\"base_classes\":[\"AgentExecutor\"],\"display_name\":\"CSVAgent\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/agents/toolkits/csv\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"CSVAgent-Ub1Xe\"},\"id\":\"CSVAgent-Ub1Xe\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T13:50:16.985419\",\"folder\":null,\"id\":\"baee8061-4788-4ce6-928f-c6ce1ecb443c\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Lively Heisenberg\",\"description\":\"Maximize Impact with Intelligent Conversations.\",\"data\":{\"nodes\":[{\"width\":384,\"height\":366,\"id\":\"CSVLoader-RMUx9\",\"type\":\"genericNode\",\"position\":{\"x\":111,\"y\":345.51250076293945},\"data\":{\"type\":\"CSVLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".csv\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"z2b\":\"z9\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"CSVLoader\"},\"description\":\"Load a `CSV` file into a list of Documents.\",\"base_classes\":[\"Document\"],\"display_name\":\"CSVLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/csv\",\"beta\":false,\"error\":null},\"id\":\"CSVLoader-RMUx9\"},\"positionAbsolute\":{\"x\":111,\"y\":345.51250076293945}}],\"edges\":[],\"viewport\":{\"x\":0,\"y\":0,\"zoom\":1}},\"is_component\":false,\"updated_at\":\"2023-12-09T14:38:40.291137\",\"folder\":null,\"id\":\"109e9629-d569-4555-9d40-42203a5ed035\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"CohereEmbeddings\",\"description\":\"Cohere embedding models.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CohereEmbeddings\",\"node\":{\"template\":{\"async_client\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"async_client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"cohere_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"cohere_api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false,\"value\":\"\"},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"max_retries\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"model\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"embed-english-v2.0\",\"password\":false,\"name\":\"model\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"truncate\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"truncate\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"user_agent\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"langchain\",\"password\":false,\"name\":\"user_agent\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"CohereEmbeddings\"},\"description\":\"Cohere embedding models.\",\"base_classes\":[\"CohereEmbeddings\",\"Embeddings\"],\"display_name\":\"CohereEmbeddings\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/cohere\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"CohereEmbeddings-HFUAf\"},\"id\":\"CohereEmbeddings-HFUAf\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T13:50:46.172344\",\"folder\":null,\"id\":\"662d8040-d47c-40db-bda1-66489a1c9d24\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"CSVLoader (1)\",\"description\":\"Load a `CSV` file into a list of Documents.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CSVLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".csv\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"cddscz23\":\"aaqd\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"CSVLoader\"},\"description\":\"Load a `CSV` file into a list of Documents.\",\"base_classes\":[\"Document\"],\"display_name\":\"CSVLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/csv\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"CSVLoader-3wrib\"},\"id\":\"CSVLoader-3wrib\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T13:56:11.662526\",\"folder\":null,\"id\":\"4fae6aec-ddbd-498d-a4d1-ca0290f6a5ad\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"CSVLoader (2)\",\"description\":\"Load a `CSV` file into a list of Documents.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CSVLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".csv\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"cddscz23\":\"aaqd\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"CSVLoader\"},\"description\":\"Load a `CSV` file into a list of Documents.\",\"base_classes\":[\"Document\"],\"display_name\":\"CSVLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/csv\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"CSVLoader-VEjyx\"},\"id\":\"CSVLoader-VEjyx\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T13:57:37.560784\",\"folder\":null,\"id\":\"d80635ee-966c-41f2-981c-afa2c388ac6e\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"CSVLoader (3)\",\"description\":\"Load a `CSV` file into a list of Documents.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CSVLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".csv\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"cddscz23\":\"aaqd\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"CSVLoader\"},\"description\":\"Load a `CSV` file into a list of Documents.\",\"base_classes\":[\"Document\"],\"display_name\":\"CSVLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/csv\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"CSVLoader-PIhOc\"},\"id\":\"CSVLoader-PIhOc\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:00:27.991966\",\"folder\":null,\"id\":\"c5cc4c32-77c8-4889-a9f8-2632466b7366\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"CSVLoader (4)\",\"description\":\"Load a `CSV` file into a list of Documents.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CSVLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".csv\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"cddscz23\":\"aaqd\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"CSVLoader\"},\"description\":\"Load a `CSV` file into a list of Documents.\",\"base_classes\":[\"Document\"],\"display_name\":\"CSVLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/csv\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"CSVLoader-deB43\"},\"id\":\"CSVLoader-deB43\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:00:42.509243\",\"folder\":null,\"id\":\"0ab59938-ccf4-4bb9-b285-1f5da38648f0\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"CSVLoader\",\"description\":\"Load a `CSV` file into a list of Documents.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CSVLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".csv\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"\":\"aaqd\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"CSVLoader\"},\"description\":\"Load a `CSV` file into a list of Documents.\",\"base_classes\":[\"Document\"],\"display_name\":\"CSVLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/csv\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"CSVLoader-mdkLm\"},\"id\":\"CSVLoader-mdkLm\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:02:17.458354\",\"folder\":null,\"id\":\"f127b7e7-4149-492e-8998-6b1b35ec4153\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"CSVLoader (5)\",\"description\":\"Load a `CSV` file into a list of Documents.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CSVLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".csv\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"cddscz23\":\"aaqd\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"CSVLoader\"},\"description\":\"Load a `CSV` file into a list of Documents.\",\"base_classes\":[\"Document\"],\"display_name\":\"CSVLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/csv\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"CSVLoader-FRc6Y\"},\"id\":\"CSVLoader-FRc6Y\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:02:26.958867\",\"folder\":null,\"id\":\"a870a096-725c-4914-add0-8d57d710b7e5\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"AirbyteJSONLoader (2)\",\"description\":\"Load local `Airbyte` json files.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"AirbyteJSONLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".json\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"\":\"\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"AirbyteJSONLoader\"},\"description\":\"Load local `Airbyte` json files.\",\"base_classes\":[\"Document\"],\"display_name\":\"AirbyteJSONLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/airbyte_json\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"AirbyteJSONLoader-Z0uol\"},\"id\":\"AirbyteJSONLoader-Z0uol\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:03:33.764117\",\"folder\":null,\"id\":\"2a37c76c-65c8-4c01-a72d-eb46f3d41a56\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Amazon Bedrock Embeddings\",\"description\":\"Embeddings model from Amazon Bedrock.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"AmazonBedrockEmbeddings\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain.embeddings import BedrockEmbeddings\\nfrom langchain.embeddings.base import Embeddings\\nfrom langflow import CustomComponent\\n\\n\\nclass AmazonBedrockEmeddingsComponent(CustomComponent):\\n \\\"\\\"\\\"\\n A custom component for implementing an Embeddings Model using Amazon Bedrock.\\n \\\"\\\"\\\"\\n\\n display_name: str = \\\"Amazon Bedrock Embeddings\\\"\\n description: str = \\\"Embeddings model from Amazon Bedrock.\\\"\\n documentation = \\\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock\\\"\\n beta = True\\n\\n def build_config(self):\\n return {\\n \\\"model_id\\\": {\\n \\\"display_name\\\": \\\"Model Id\\\",\\n \\\"options\\\": [\\\"amazon.titan-embed-text-v1\\\"],\\n },\\n \\\"credentials_profile_name\\\": {\\\"display_name\\\": \\\"Credentials Profile Name\\\"},\\n \\\"endpoint_url\\\": {\\\"display_name\\\": \\\"Bedrock Endpoint URL\\\"},\\n \\\"region_name\\\": {\\\"display_name\\\": \\\"AWS Region\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n model_id: str = \\\"amazon.titan-embed-text-v1\\\",\\n credentials_profile_name: Optional[str] = None,\\n endpoint_url: Optional[str] = None,\\n region_name: Optional[str] = None,\\n ) -> Embeddings:\\n try:\\n output = BedrockEmbeddings(\\n credentials_profile_name=credentials_profile_name,\\n model_id=model_id,\\n endpoint_url=endpoint_url,\\n region_name=region_name,\\n ) # type: ignore\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to AmazonBedrock API.\\\") from e\\n return output\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"credentials_profile_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"credentials_profile_name\",\"display_name\":\"Credentials Profile Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"endpoint_url\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"endpoint_url\",\"display_name\":\"Bedrock Endpoint URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"model_id\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"amazon.titan-embed-text-v1\",\"password\":false,\"options\":[\"amazon.titan-embed-text-v1\"],\"name\":\"model_id\",\"display_name\":\"Model Id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"region_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"region_name\",\"display_name\":\"AWS Region\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"Embeddings model from Amazon Bedrock.\",\"base_classes\":[\"Embeddings\"],\"display_name\":\"Amazon Bedrock Embeddings\",\"custom_fields\":{\"credentials_profile_name\":null,\"endpoint_url\":null,\"model_id\":null,\"region_name\":null},\"output_types\":[\"AmazonBedrockEmbeddings\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"AmazonBedrockEmbeddings-28ASv\"},\"id\":\"AmazonBedrockEmbeddings-28ASv\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:03:41.066618\",\"folder\":null,\"id\":\"850ba4e6-96ca-49a7-9b0c-4b7048fd52c8\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"ConversationBufferMemory\",\"description\":\"Buffer for storing conversation memory.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"ConversationBufferMemory\",\"node\":{\"template\":{\"chat_memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"chat_memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseChatMessageHistory\",\"list\":false},\"ai_prefix\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"AI\",\"password\":false,\"name\":\"ai_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"human_prefix\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"Human\",\"password\":false,\"name\":\"human_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"input_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"input_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Input when more than one variable is available.\",\"type\":\"str\",\"list\":false},\"memory_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"chat_history\",\"password\":false,\"name\":\"memory_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"output_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"output_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Output (e.g. answer in a ConversationalRetrievalChain)\",\"type\":\"str\",\"list\":false},\"return_messages\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"return_messages\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ConversationBufferMemory\"},\"description\":\"Buffer for storing conversation memory.\",\"base_classes\":[\"BaseMemory\",\"BaseChatMemory\",\"ConversationBufferMemory\"],\"display_name\":\"ConversationBufferMemory\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/memory/how_to/buffer\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"ConversationBufferMemory-WaoLx\"},\"id\":\"ConversationBufferMemory-WaoLx\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:04:46.058568\",\"folder\":null,\"id\":\"be650940-0449-4eb0-a708-056310f924fd\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Amazon Bedrock Embeddings (1)\",\"description\":\"Embeddings model from Amazon Bedrock.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"AmazonBedrockEmbeddings\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain.embeddings import BedrockEmbeddings\\nfrom langchain.embeddings.base import Embeddings\\nfrom langflow import CustomComponent\\n\\n\\nclass AmazonBedrockEmeddingsComponent(CustomComponent):\\n \\\"\\\"\\\"\\n A custom component for implementing an Embeddings Model using Amazon Bedrock.\\n \\\"\\\"\\\"\\n\\n display_name: str = \\\"Amazon Bedrock Embeddings\\\"\\n description: str = \\\"Embeddings model from Amazon Bedrock.\\\"\\n documentation = \\\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock\\\"\\n beta = True\\n\\n def build_config(self):\\n return {\\n \\\"model_id\\\": {\\n \\\"display_name\\\": \\\"Model Id\\\",\\n \\\"options\\\": [\\\"amazon.titan-embed-text-v1\\\"],\\n },\\n \\\"credentials_profile_name\\\": {\\\"display_name\\\": \\\"Credentials Profile Name\\\"},\\n \\\"endpoint_url\\\": {\\\"display_name\\\": \\\"Bedrock Endpoint URL\\\"},\\n \\\"region_name\\\": {\\\"display_name\\\": \\\"AWS Region\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n model_id: str = \\\"amazon.titan-embed-text-v1\\\",\\n credentials_profile_name: Optional[str] = None,\\n endpoint_url: Optional[str] = None,\\n region_name: Optional[str] = None,\\n ) -> Embeddings:\\n try:\\n output = BedrockEmbeddings(\\n credentials_profile_name=credentials_profile_name,\\n model_id=model_id,\\n endpoint_url=endpoint_url,\\n region_name=region_name,\\n ) # type: ignore\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to AmazonBedrock API.\\\") from e\\n return output\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"credentials_profile_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"credentials_profile_name\",\"display_name\":\"Credentials Profile Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"endpoint_url\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"endpoint_url\",\"display_name\":\"Bedrock Endpoint URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"model_id\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"amazon.titan-embed-text-v1\",\"password\":false,\"options\":[\"amazon.titan-embed-text-v1\"],\"name\":\"model_id\",\"display_name\":\"Model Id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"region_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"region_name\",\"display_name\":\"AWS Region\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"Embeddings model from Amazon Bedrock.\",\"base_classes\":[\"Embeddings\"],\"display_name\":\"Amazon Bedrock Embeddings\",\"custom_fields\":{\"credentials_profile_name\":null,\"endpoint_url\":null,\"model_id\":null,\"region_name\":null},\"output_types\":[\"AmazonBedrockEmbeddings\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"AmazonBedrockEmbeddings-Bs5PG\"},\"id\":\"AmazonBedrockEmbeddings-Bs5PG\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:05:50.570800\",\"folder\":null,\"id\":\"53ad1fe2-f3af-4354-86e0-eb141ce12859\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Amazon Bedrock Embeddings (2)\",\"description\":\"Embeddings model from Amazon Bedrock.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"AmazonBedrockEmbeddings\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain.embeddings import BedrockEmbeddings\\nfrom langchain.embeddings.base import Embeddings\\nfrom langflow import CustomComponent\\n\\n\\nclass AmazonBedrockEmeddingsComponent(CustomComponent):\\n \\\"\\\"\\\"\\n A custom component for implementing an Embeddings Model using Amazon Bedrock.\\n \\\"\\\"\\\"\\n\\n display_name: str = \\\"Amazon Bedrock Embeddings\\\"\\n description: str = \\\"Embeddings model from Amazon Bedrock.\\\"\\n documentation = \\\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock\\\"\\n beta = True\\n\\n def build_config(self):\\n return {\\n \\\"model_id\\\": {\\n \\\"display_name\\\": \\\"Model Id\\\",\\n \\\"options\\\": [\\\"amazon.titan-embed-text-v1\\\"],\\n },\\n \\\"credentials_profile_name\\\": {\\\"display_name\\\": \\\"Credentials Profile Name\\\"},\\n \\\"endpoint_url\\\": {\\\"display_name\\\": \\\"Bedrock Endpoint URL\\\"},\\n \\\"region_name\\\": {\\\"display_name\\\": \\\"AWS Region\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n model_id: str = \\\"amazon.titan-embed-text-v1\\\",\\n credentials_profile_name: Optional[str] = None,\\n endpoint_url: Optional[str] = None,\\n region_name: Optional[str] = None,\\n ) -> Embeddings:\\n try:\\n output = BedrockEmbeddings(\\n credentials_profile_name=credentials_profile_name,\\n model_id=model_id,\\n endpoint_url=endpoint_url,\\n region_name=region_name,\\n ) # type: ignore\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to AmazonBedrock API.\\\") from e\\n return output\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"credentials_profile_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"credentials_profile_name\",\"display_name\":\"Credentials Profile Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"endpoint_url\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"endpoint_url\",\"display_name\":\"Bedrock Endpoint URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"model_id\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"amazon.titan-embed-text-v1\",\"password\":false,\"options\":[\"amazon.titan-embed-text-v1\"],\"name\":\"model_id\",\"display_name\":\"Model Id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"region_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"region_name\",\"display_name\":\"AWS Region\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"Embeddings model from Amazon Bedrock.\",\"base_classes\":[\"Embeddings\"],\"display_name\":\"Amazon Bedrock Embeddings\",\"custom_fields\":{\"credentials_profile_name\":null,\"endpoint_url\":null,\"model_id\":null,\"region_name\":null},\"output_types\":[\"AmazonBedrockEmbeddings\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"AmazonBedrockEmbeddings-zSZ4t\"},\"id\":\"AmazonBedrockEmbeddings-zSZ4t\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:06:11.415088\",\"folder\":null,\"id\":\"e9ed1c90-146e-452d-8ccd-ebf2e0da4331\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Amazon Bedrock Embeddings (3)\",\"description\":\"Embeddings model from Amazon Bedrock.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"AmazonBedrockEmbeddings\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain.embeddings import BedrockEmbeddings\\nfrom langchain.embeddings.base import Embeddings\\nfrom langflow import CustomComponent\\n\\n\\nclass AmazonBedrockEmeddingsComponent(CustomComponent):\\n \\\"\\\"\\\"\\n A custom component for implementing an Embeddings Model using Amazon Bedrock.\\n \\\"\\\"\\\"\\n\\n display_name: str = \\\"Amazon Bedrock Embeddings\\\"\\n description: str = \\\"Embeddings model from Amazon Bedrock.\\\"\\n documentation = \\\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock\\\"\\n beta = True\\n\\n def build_config(self):\\n return {\\n \\\"model_id\\\": {\\n \\\"display_name\\\": \\\"Model Id\\\",\\n \\\"options\\\": [\\\"amazon.titan-embed-text-v1\\\"],\\n },\\n \\\"credentials_profile_name\\\": {\\\"display_name\\\": \\\"Credentials Profile Name\\\"},\\n \\\"endpoint_url\\\": {\\\"display_name\\\": \\\"Bedrock Endpoint URL\\\"},\\n \\\"region_name\\\": {\\\"display_name\\\": \\\"AWS Region\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n model_id: str = \\\"amazon.titan-embed-text-v1\\\",\\n credentials_profile_name: Optional[str] = None,\\n endpoint_url: Optional[str] = None,\\n region_name: Optional[str] = None,\\n ) -> Embeddings:\\n try:\\n output = BedrockEmbeddings(\\n credentials_profile_name=credentials_profile_name,\\n model_id=model_id,\\n endpoint_url=endpoint_url,\\n region_name=region_name,\\n ) # type: ignore\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to AmazonBedrock API.\\\") from e\\n return output\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"credentials_profile_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"credentials_profile_name\",\"display_name\":\"Credentials Profile Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"endpoint_url\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"endpoint_url\",\"display_name\":\"Bedrock Endpoint URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"model_id\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"amazon.titan-embed-text-v1\",\"password\":false,\"options\":[\"amazon.titan-embed-text-v1\"],\"name\":\"model_id\",\"display_name\":\"Model Id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"region_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"region_name\",\"display_name\":\"AWS Region\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"Embeddings model from Amazon Bedrock.\",\"base_classes\":[\"Embeddings\"],\"display_name\":\"Amazon Bedrock Embeddings\",\"custom_fields\":{\"credentials_profile_name\":null,\"endpoint_url\":null,\"model_id\":null,\"region_name\":null},\"output_types\":[\"AmazonBedrockEmbeddings\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"AmazonBedrockEmbeddings-Bxhlt\"},\"id\":\"AmazonBedrockEmbeddings-Bxhlt\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:07:06.411108\",\"folder\":null,\"id\":\"83783c57-64e3-41a6-aa7e-ed82f80f1e53\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"CSVLoader (6)\",\"description\":\"Load a `CSV` file into a list of Documents.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"CSVLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".csv\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"z2b\":\"z9\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"CSVLoader\"},\"description\":\"Load a `CSV` file into a list of Documents.\",\"base_classes\":[\"Document\"],\"display_name\":\"CSVLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/csv\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"CSVLoader-2pn2o\"},\"id\":\"CSVLoader-2pn2o\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:38:30.706258\",\"folder\":null,\"id\":\"c4ae9de6-9df3-4d3c-afc9-1752af4fecd7\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Agent Initializer\",\"description\":\"Initialize a Langchain Agent.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"AgentInitializer\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from typing import Callable, List, Union\\n\\nfrom langchain.agents import AgentExecutor, AgentType, initialize_agent, types\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import BaseChatMemory, BaseLanguageModel, Tool\\n\\n\\nclass AgentInitializerComponent(CustomComponent):\\n display_name: str = \\\"Agent Initializer\\\"\\n description: str = \\\"Initialize a Langchain Agent.\\\"\\n documentation: str = \\\"https://python.langchain.com/docs/modules/agents/agent_types/\\\"\\n\\n def build_config(self):\\n agents = list(types.AGENT_TO_CLASS.keys())\\n # field_type and required are optional\\n return {\\n \\\"agent\\\": {\\\"options\\\": agents, \\\"value\\\": agents[0], \\\"display_name\\\": \\\"Agent Type\\\"},\\n \\\"max_iterations\\\": {\\\"display_name\\\": \\\"Max Iterations\\\", \\\"value\\\": 10},\\n \\\"memory\\\": {\\\"display_name\\\": \\\"Memory\\\"},\\n \\\"tools\\\": {\\\"display_name\\\": \\\"Tools\\\"},\\n \\\"llm\\\": {\\\"display_name\\\": \\\"Language Model\\\"},\\n }\\n\\n def build(\\n self, agent: str, llm: BaseLanguageModel, memory: BaseChatMemory, tools: List[Tool], max_iterations: int\\n ) -> Union[AgentExecutor, Callable]:\\n agent = AgentType(agent)\\n return initialize_agent(\\n tools=tools,\\n llm=llm,\\n agent=agent,\\n memory=memory,\\n return_intermediate_steps=True,\\n handle_parsing_errors=True,\\n max_iterations=max_iterations,\\n )\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"agent\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"zero-shot-react-description\",\"password\":false,\"options\":[\"zero-shot-react-description\",\"react-docstore\",\"self-ask-with-search\",\"conversational-react-description\",\"chat-zero-shot-react-description\",\"chat-conversational-react-description\",\"structured-chat-zero-shot-react-description\",\"openai-functions\",\"openai-multi-functions\",\"JsonAgent\",\"CSVAgent\",\"AgentInitializer\",\"VectorStoreAgent\",\"VectorStoreRouterAgent\",\"SQLAgent\"],\"name\":\"agent\",\"display_name\":\"Agent Type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"Language Model\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"max_iterations\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":10,\"password\":false,\"name\":\"max_iterations\",\"display_name\":\"Max Iterations\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"memory\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseChatMemory\",\"list\":false},\"tools\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"tools\",\"display_name\":\"Tools\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Tool\",\"list\":true}},\"description\":\"Initialize a Langchain Agent.\",\"base_classes\":[\"Chain\",\"AgentExecutor\",\"Callable\"],\"display_name\":\"Agent Initializer\",\"custom_fields\":{\"agent\":null,\"llm\":null,\"max_iterations\":null,\"memory\":null,\"tools\":null},\"output_types\":[\"AgentInitializer\"],\"documentation\":\"https://python.langchain.com/docs/modules/agents/agent_types/\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"AgentInitializer-MJrAC\"},\"id\":\"AgentInitializer-MJrAC\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:42:54.715163\",\"folder\":null,\"id\":\"ff84b5f9-5680-4084-a9f1-7d94fe675486\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Agent Initializer (1)\",\"description\":\"Initialize a Langchain Agent.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"AgentInitializer\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from typing import Callable, List, Union\\n\\nfrom langchain.agents import AgentExecutor, AgentType, initialize_agent, types\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import BaseChatMemory, BaseLanguageModel, Tool\\n\\n\\nclass AgentInitializerComponent(CustomComponent):\\n display_name: str = \\\"Agent Initializer\\\"\\n description: str = \\\"Initialize a Langchain Agent.\\\"\\n documentation: str = \\\"https://python.langchain.com/docs/modules/agents/agent_types/\\\"\\n\\n def build_config(self):\\n agents = list(types.AGENT_TO_CLASS.keys())\\n # field_type and required are optional\\n return {\\n \\\"agent\\\": {\\\"options\\\": agents, \\\"value\\\": agents[0], \\\"display_name\\\": \\\"Agent Type\\\"},\\n \\\"max_iterations\\\": {\\\"display_name\\\": \\\"Max Iterations\\\", \\\"value\\\": 10},\\n \\\"memory\\\": {\\\"display_name\\\": \\\"Memory\\\"},\\n \\\"tools\\\": {\\\"display_name\\\": \\\"Tools\\\"},\\n \\\"llm\\\": {\\\"display_name\\\": \\\"Language Model\\\"},\\n }\\n\\n def build(\\n self, agent: str, llm: BaseLanguageModel, memory: BaseChatMemory, tools: List[Tool], max_iterations: int\\n ) -> Union[AgentExecutor, Callable]:\\n agent = AgentType(agent)\\n return initialize_agent(\\n tools=tools,\\n llm=llm,\\n agent=agent,\\n memory=memory,\\n return_intermediate_steps=True,\\n handle_parsing_errors=True,\\n max_iterations=max_iterations,\\n )\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"agent\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"zero-shot-react-description\",\"password\":false,\"options\":[\"zero-shot-react-description\",\"react-docstore\",\"self-ask-with-search\",\"conversational-react-description\",\"chat-zero-shot-react-description\",\"chat-conversational-react-description\",\"structured-chat-zero-shot-react-description\",\"openai-functions\",\"openai-multi-functions\",\"JsonAgent\",\"CSVAgent\",\"AgentInitializer\",\"VectorStoreAgent\",\"VectorStoreRouterAgent\",\"SQLAgent\"],\"name\":\"agent\",\"display_name\":\"Agent Type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"Language Model\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"max_iterations\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":10,\"password\":false,\"name\":\"max_iterations\",\"display_name\":\"Max Iterations\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"memory\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseChatMemory\",\"list\":false},\"tools\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"tools\",\"display_name\":\"Tools\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Tool\",\"list\":true}},\"description\":\"Initialize a Langchain Agent.\",\"base_classes\":[\"Chain\",\"AgentExecutor\",\"Callable\"],\"display_name\":\"Agent Initializer\",\"custom_fields\":{\"agent\":null,\"llm\":null,\"max_iterations\":null,\"memory\":null,\"tools\":null},\"output_types\":[\"AgentInitializer\"],\"documentation\":\"https://python.langchain.com/docs/modules/agents/agent_types/\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"AgentInitializer-3lcZ4\"},\"id\":\"AgentInitializer-3lcZ4\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:43:20.819934\",\"folder\":null,\"id\":\"97f5db9f-d6cc-4555-88fb-3be102c67814\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Exuberant Banach\",\"description\":\"Unfolding Linguistic Possibilities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-09T14:52:49.951416\",\"folder\":null,\"id\":\"a600acd1-213a-4ce7-8648-ab2ee59f5918\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"AirbyteJSONLoader (3)\",\"description\":\"Load local `Airbyte` json files.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"AirbyteJSONLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".json\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"\":\"\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"AirbyteJSONLoader\"},\"description\":\"Load local `Airbyte` json files.\",\"base_classes\":[\"Document\"],\"display_name\":\"AirbyteJSONLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/airbyte_json\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"AirbyteJSONLoader-JhQtx\"},\"id\":\"AirbyteJSONLoader-JhQtx\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:44:49.587337\",\"folder\":null,\"id\":\"07c52ad7-ca52-4cdd-ab40-74a91dbad0dd\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"AirbyteJSONLoader (4)\",\"description\":\"Load local `Airbyte` json files.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"AirbyteJSONLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".json\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"\":\"\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"AirbyteJSONLoader\"},\"description\":\"Load local `Airbyte` json files.\",\"base_classes\":[\"Document\"],\"display_name\":\"AirbyteJSONLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/airbyte_json\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"AirbyteJSONLoader-bIvDc\"},\"id\":\"AirbyteJSONLoader-bIvDc\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:45:13.458500\",\"folder\":null,\"id\":\"53e4d256-3653-444b-b8e0-fb97b3ae5c7e\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"AirbyteJSONLoader (5)\",\"description\":\"Load local `Airbyte` json files.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"AirbyteJSONLoader\",\"node\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\".json\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[{\"\":\"\"}],\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"AirbyteJSONLoader\"},\"description\":\"Load local `Airbyte` json files.\",\"base_classes\":[\"Document\"],\"display_name\":\"AirbyteJSONLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/airbyte_json\",\"beta\":false,\"error\":null,\"official\":false},\"id\":\"AirbyteJSONLoader-2BLS8\"},\"id\":\"AirbyteJSONLoader-2BLS8\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:45:44.461699\",\"folder\":null,\"id\":\"b5158cc1-c6b8-4e25-907a-bc7e7637aa38\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Amazon Bedrock Embeddings (4)\",\"description\":\"Embeddings model from Amazon Bedrock.\",\"data\":{\"edges\":[],\"nodes\":[{\"data\":{\"type\":\"AmazonBedrockEmbeddings\",\"node\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain.embeddings import BedrockEmbeddings\\nfrom langchain.embeddings.base import Embeddings\\nfrom langflow import CustomComponent\\n\\n\\nclass AmazonBedrockEmeddingsComponent(CustomComponent):\\n \\\"\\\"\\\"\\n A custom component for implementing an Embeddings Model using Amazon Bedrock.\\n \\\"\\\"\\\"\\n\\n display_name: str = \\\"Amazon Bedrock Embeddings\\\"\\n description: str = \\\"Embeddings model from Amazon Bedrock.\\\"\\n documentation = \\\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock\\\"\\n beta = True\\n\\n def build_config(self):\\n return {\\n \\\"model_id\\\": {\\n \\\"display_name\\\": \\\"Model Id\\\",\\n \\\"options\\\": [\\\"amazon.titan-embed-text-v1\\\"],\\n },\\n \\\"credentials_profile_name\\\": {\\\"display_name\\\": \\\"Credentials Profile Name\\\"},\\n \\\"endpoint_url\\\": {\\\"display_name\\\": \\\"Bedrock Endpoint URL\\\"},\\n \\\"region_name\\\": {\\\"display_name\\\": \\\"AWS Region\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n model_id: str = \\\"amazon.titan-embed-text-v1\\\",\\n credentials_profile_name: Optional[str] = None,\\n endpoint_url: Optional[str] = None,\\n region_name: Optional[str] = None,\\n ) -> Embeddings:\\n try:\\n output = BedrockEmbeddings(\\n credentials_profile_name=credentials_profile_name,\\n model_id=model_id,\\n endpoint_url=endpoint_url,\\n region_name=region_name,\\n ) # type: ignore\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to AmazonBedrock API.\\\") from e\\n return output\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"credentials_profile_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"credentials_profile_name\",\"display_name\":\"Credentials Profile Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"endpoint_url\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"endpoint_url\",\"display_name\":\"Bedrock Endpoint URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"model_id\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"amazon.titan-embed-text-v1\",\"password\":false,\"options\":[\"amazon.titan-embed-text-v1\"],\"name\":\"model_id\",\"display_name\":\"Model Id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"region_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"region_name\",\"display_name\":\"AWS Region\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"Embeddings model from Amazon Bedrock.\",\"base_classes\":[\"Embeddings\"],\"display_name\":\"Amazon Bedrock Embeddings\",\"custom_fields\":{\"credentials_profile_name\":null,\"endpoint_url\":null,\"model_id\":null,\"region_name\":null},\"output_types\":[\"AmazonBedrockEmbeddings\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock\",\"beta\":true,\"error\":null,\"official\":false},\"id\":\"AmazonBedrockEmbeddings-NsBzN\"},\"id\":\"AmazonBedrockEmbeddings-NsBzN\",\"position\":{\"x\":0,\"y\":0},\"type\":\"genericNode\"}],\"viewport\":{\"x\":1,\"y\":1,\"zoom\":1}},\"is_component\":true,\"updated_at\":\"2023-12-09T14:50:29.791575\",\"folder\":null,\"id\":\"3fb77f72-1be7-4ce0-ae89-a82b0eee9acf\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Evil Golick\",\"description\":\"Where Language Meets Logic.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:19:02.707854\",\"folder\":null,\"id\":\"9c5d21c2-ea82-4cf4-a591-c3d3fd3f13e6\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Gleeful Davinci (1)\",\"description\":\"Unleashing Linguistic Creativity.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:19:02.761150\",\"folder\":null,\"id\":\"f8e2e16e-129c-4116-9626-2c6b524d97b7\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Effervescent Degrasse\",\"description\":\"Language Models, Mapped and Mastered.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:19:02.764440\",\"folder\":null,\"id\":\"d7f4f7b5-effe-4834-8cab-4f2fc4f6e9de\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Prickly Archimedes\",\"description\":\"Language Chainlink Master.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:19:02.767546\",\"folder\":null,\"id\":\"2265d813-4a87-410f-b06a-65e35db8219e\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Boring Heyrovsky\",\"description\":\"Building Intelligent Interactions.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:19:02.765105\",\"folder\":null,\"id\":\"10bfd881-e67e-4c33-965d-ee041695edce\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Nostalgic Carroll\",\"description\":\"Unfolding Linguistic Possibilities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:19:02.811794\",\"folder\":null,\"id\":\"63fa5653-4513-47f2-8dfa-baeb1d981f93\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Pensive Perlman\",\"description\":\"Empowering Communication, Enabling Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:19:02.814993\",\"folder\":null,\"id\":\"f4bc5945-20d9-4703-a5bb-6a4a3ef7fc8e\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Hilarious Stallman\",\"description\":\"Connect the Dots, Craft Language.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:19:02.813144\",\"folder\":null,\"id\":\"8d8b80f9-4b74-4cd5-bc5c-08a32c4d2b95\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Awesome Einstein\",\"description\":\"The Power of Language at Your Fingertips.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:20:19.518262\",\"folder\":null,\"id\":\"21808fd7-a492-4e29-8863-301c2785f542\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Funky Swanson\",\"description\":\"Sculpting Language with Precision.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:20:20.185637\",\"folder\":null,\"id\":\"7752299a-4aa9-44db-8d9c-5c4a2ac1b071\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Romantic Pascal\",\"description\":\"Unlock the Power of AI in Your Business Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:20:20.223064\",\"folder\":null,\"id\":\"78f48a13-6a9f-42ce-9d58-ec9b63b381d2\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Twinkly Bartik\",\"description\":\"Sculpting Language with Precision.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:20:20.239758\",\"folder\":null,\"id\":\"38074091-3d7c-4d42-b61b-ae195c1b8a4e\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Condescending Joliot\",\"description\":\"Language Models, Unleashed.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:20:20.271996\",\"folder\":null,\"id\":\"773020aa-5c2d-4632-ad9e-21276861ab93\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Gleeful Kalam\",\"description\":\"The Power of Language at Your Fingertips.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:20:20.283929\",\"folder\":null,\"id\":\"0092d077-6d31-401f-a739-b164476b90ed\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Grinning Bhabha\",\"description\":\"Your Passport to Linguistic Landscapes.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:20:20.467739\",\"folder\":null,\"id\":\"4a395211-712d-4dd2-b3bb-e6b19200f15d\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Mirthful Babbage\",\"description\":\"Design Dialogues with Langflow.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:20:20.742990\",\"folder\":null,\"id\":\"3f086a82-3e29-4328-9da8-e02dc9201744\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Tiny Volta\",\"description\":\"Nurture NLP Nodes Here.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:24:18.594247\",\"folder\":null,\"id\":\"659b8289-c8e8-413d-9b2b-51e68411f170\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Radiant Jennings\",\"description\":\"Design, Develop, Dialogize.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:24:42.640309\",\"folder\":null,\"id\":\"f55f0640-d47e-4471-b1ba-3411d38ecac5\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Distracted Shaw\",\"description\":\"Interactive Language Weaving.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:24:58.376247\",\"folder\":null,\"id\":\"a039811e-449a-4244-83ed-4ddd731a0921\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Peppy Murdock (1)\",\"description\":\"Language Chainlink Master.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:25:14.674524\",\"folder\":null,\"id\":\"0faf6144-6ca6-4f64-a343-665ae54774ef\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Lively Volta\",\"description\":\"Language Models, Mapped and Mastered.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:26:50.418029\",\"folder\":null,\"id\":\"c5d149d0-c401-4f5e-b79f-2abcc7b8d98d\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Bubbly Curie\",\"description\":\"Navigate the Networks of Conversation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:27:10.900899\",\"folder\":null,\"id\":\"7bb2d226-9740-433d-861f-a499632c5a13\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Radiant Nobel\",\"description\":\"Navigate the Linguistic Landscape, Discover Opportunities.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:29:11.541630\",\"folder\":null,\"id\":\"947906d8-75ea-470c-a8e2-cc80c5d3bdbb\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Cheerful Northcutt\",\"description\":\"Unleashing Business Potential through Language Engineering.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:29:37.169791\",\"folder\":null,\"id\":\"56f109fd-2c18-42ed-a9b2-089a678a0c11\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Suspicious Khayyam\",\"description\":\"Crafting Dialogues that Drive Business Success.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:30:24.686359\",\"folder\":null,\"id\":\"551d7bfa-49aa-43f1-a779-e47eabc2aaf2\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Twinkly Spence\",\"description\":\"Create, Curate, Communicate with Langflow.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:30:47.738472\",\"folder\":null,\"id\":\"12aef128-130e-492e-bf84-62d4cb4cd456\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Mirthful Lavoisier\",\"description\":\"Nurture NLP Nodes Here.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:31:43.272365\",\"folder\":null,\"id\":\"9952c044-6903-4fba-a270-6ed0b90c93c9\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Upbeat Bose\",\"description\":\"Unravel the Art of Articulation.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:32:23.972035\",\"folder\":null,\"id\":\"65f49582-c9fa-4c67-a2bc-4e8fa73ca731\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Tender Perlman\",\"description\":\"Maximize Impact with Intelligent Conversations.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:33:26.984083\",\"folder\":null,\"id\":\"9ae57fe2-c677-47fa-a059-7d3d915a1178\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"},{\"name\":\"Sharp Cori\",\"description\":\"Conversation Catalyst Engine.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2023-12-11T18:33:52.377359\",\"folder\":null,\"id\":\"2920dde2-5c24-4fe0-9c06-ef86b5a16a99\",\"user_id\":\"d253bfba-6368-44dc-85f7-0d6da9e45968\"}]" - }, - "headersSize": -1, - "bodySize": -1, - "redirectURL": "" - }, - "cache": {}, - "timings": { "send": -1, "wait": -1, "receive": 1.309 } - }, - { - "startedDateTime": "2023-12-11T18:55:08.950Z", - "time": 0.595, - "request": { - "method": "GET", - "url": "http://localhost:3000/api/v1/build/2920dde2-5c24-4fe0-9c06-ef86b5a16a99/status", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Accept", "value": "application/json, text/plain, */*" }, - { "name": "Accept-Encoding", "value": "gzip, deflate, br" }, - { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, - { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20" }, - { "name": "Connection", "value": "keep-alive" }, - { "name": "Cookie", "value": "access_token_lf=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkMjUzYmZiYS02MzY4LTQ0ZGMtODVmNy0wZDZkYTllNDU5NjgiLCJleHAiOjE3MzM4NTY4OTh9.5MFFb0JCck3ITSKXbxhwO9yAscnXcwXNTV70ZYBRB20; refresh_tkn_lflw=auto" }, - { "name": "Host", "value": "localhost:3000" }, - { "name": "Referer", "value": "http://localhost:3000/flow/2920dde2-5c24-4fe0-9c06-ef86b5a16a99" }, - { "name": "Sec-Fetch-Dest", "value": "empty" }, - { "name": "Sec-Fetch-Mode", "value": "cors" }, - { "name": "Sec-Fetch-Site", "value": "same-origin" }, - { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" }, - { "name": "sec-ch-ua", "value": "\"Chromium\";v=\"119\", \"Not?A_Brand\";v=\"24\"" }, - { "name": "sec-ch-ua-mobile", "value": "?0" }, - { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } - ], - "queryString": [], - "headersSize": -1, - "bodySize": -1 - }, - "response": { - "status": 200, - "statusText": "OK", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Access-Control-Allow-Origin", "value": "*" }, - { "name": "connection", "value": "close" }, - { "name": "content-length", "value": "15" }, - { "name": "content-type", "value": "application/json" }, - { "name": "date", "value": "Mon, 11 Dec 2023 18:55:08 GMT" }, - { "name": "server", "value": "uvicorn" } - ], - "content": { - "size": -1, - "mimeType": "application/json", - "text": "{\"built\":false}" - }, - "headersSize": -1, - "bodySize": -1, - "redirectURL": "" - }, - "cache": {}, - "timings": { "send": -1, "wait": -1, "receive": 0.595 } - } - ] - } -} \ No newline at end of file diff --git a/src/frontend/harFiles/langflow.har b/src/frontend/harFiles/langflow.har index edac6806e..d6fef50cd 100644 --- a/src/frontend/harFiles/langflow.har +++ b/src/frontend/harFiles/langflow.har @@ -1,229 +1,733 @@ { - "log": { - "version": "1.2", - "creator": { - "name": "Playwright", - "version": "1.37.1" + "log": { + "version": "1.2", + "creator": { + "name": "Playwright", + "version": "1.42.0" + }, + "browser": { + "name": "chromium", + "version": "123.0.6312.4" + }, + "entries": [ + { + "startedDateTime": "2024-02-28T14:32:30.858Z", + "time": 0.77, + "request": { + "method": "GET", + "url": "http://localhost:3000/api/v1/version", + "httpVersion": "HTTP/1.1", + "cookies": [], + "headers": [ + { "name": "Accept", "value": "application/json, text/plain, */*" }, + { "name": "Accept-Encoding", "value": "gzip, deflate, br, zstd" }, + { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, + { "name": "Connection", "value": "keep-alive" }, + { "name": "Host", "value": "localhost:3000" }, + { "name": "Referer", "value": "http://localhost:3000/" }, + { "name": "Sec-Fetch-Dest", "value": "empty" }, + { "name": "Sec-Fetch-Mode", "value": "cors" }, + { "name": "Sec-Fetch-Site", "value": "same-origin" }, + { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" }, + { "name": "sec-ch-ua", "value": "\"Chromium\";v=\"123\", \"Not:A-Brand\";v=\"8\"" }, + { "name": "sec-ch-ua-mobile", "value": "?0" }, + { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } + ], + "queryString": [], + "headersSize": -1, + "bodySize": -1 + }, + "response": { + "status": 200, + "statusText": "OK", + "httpVersion": "HTTP/1.1", + "cookies": [], + "headers": [ + { "name": "Access-Control-Allow-Origin", "value": "*" }, + { "name": "connection", "value": "close" }, + { "name": "content-length", "value": "19" }, + { "name": "content-type", "value": "application/json" }, + { "name": "date", "value": "Wed, 28 Feb 2024 14:32:30 GMT" }, + { "name": "server", "value": "uvicorn" } + ], + "content": { + "size": -1, + "mimeType": "application/json", + "text": "{\"version\":\"0.6.7\"}" + }, + "headersSize": -1, + "bodySize": -1, + "redirectURL": "" + }, + "cache": {}, + "timings": { "send": -1, "wait": -1, "receive": 0.77 } }, - "browser": { - "name": "chromium", - "version": "116.0.5845.82" + { + "startedDateTime": "2024-02-28T14:32:30.859Z", + "time": 0.894, + "request": { + "method": "GET", + "url": "http://localhost:3000/api/v1/auto_login", + "httpVersion": "HTTP/1.1", + "cookies": [], + "headers": [ + { "name": "Accept", "value": "application/json, text/plain, */*" }, + { "name": "Accept-Encoding", "value": "gzip, deflate, br, zstd" }, + { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, + { "name": "Connection", "value": "keep-alive" }, + { "name": "Host", "value": "localhost:3000" }, + { "name": "Referer", "value": "http://localhost:3000/" }, + { "name": "Sec-Fetch-Dest", "value": "empty" }, + { "name": "Sec-Fetch-Mode", "value": "cors" }, + { "name": "Sec-Fetch-Site", "value": "same-origin" }, + { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" }, + { "name": "sec-ch-ua", "value": "\"Chromium\";v=\"123\", \"Not:A-Brand\";v=\"8\"" }, + { "name": "sec-ch-ua-mobile", "value": "?0" }, + { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } + ], + "queryString": [], + "headersSize": -1, + "bodySize": -1 + }, + "response": { + "status": 200, + "statusText": "OK", + "httpVersion": "HTTP/1.1", + "cookies": [], + "headers": [ + { "name": "Access-Control-Allow-Origin", "value": "*" }, + { "name": "connection", "value": "close" }, + { "name": "content-length", "value": "227" }, + { "name": "content-type", "value": "application/json" }, + { "name": "date", "value": "Wed, 28 Feb 2024 14:32:30 GMT" }, + { "name": "server", "value": "uvicorn" }, + { "name": "set-cookie", "value": "access_token_lf=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMzg5ZmIyOS1kYWE2LTQwOGMtYjhjYi1iOGZmOGQxNzM0M2EiLCJleHAiOjE3NDA2NjY3NTB9.ef5W5jwNOeVzU3JZ7ylLYf2MLEJcVxC4-fF7EK9Ecdc; Path=/; SameSite=none; Secure" } + ], + "content": { + "size": -1, + "mimeType": "application/json", + "text": "{\"access_token\":\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMzg5ZmIyOS1kYWE2LTQwOGMtYjhjYi1iOGZmOGQxNzM0M2EiLCJleHAiOjE3NDA2NjY3NTB9.ef5W5jwNOeVzU3JZ7ylLYf2MLEJcVxC4-fF7EK9Ecdc\",\"refresh_token\":null,\"token_type\":\"bearer\"}" + }, + "headersSize": -1, + "bodySize": -1, + "redirectURL": "" + }, + "cache": {}, + "timings": { "send": -1, "wait": -1, "receive": 0.894 } }, - "entries": [ - { - "startedDateTime": "2023-08-31T14:55:35.502Z", - "time": 0.727, - "request": { - "method": "GET", - "url": "http://localhost:3000/api/v1/auto_login", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Accept", "value": "application/json, text/plain, */*" }, - { "name": "Accept-Encoding", "value": "gzip, deflate, br" }, - { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, - { "name": "Connection", "value": "keep-alive" }, - { "name": "Host", "value": "localhost:3000" }, - { "name": "Referer", "value": "http://localhost:3000/" }, - { "name": "Sec-Fetch-Dest", "value": "empty" }, - { "name": "Sec-Fetch-Mode", "value": "cors" }, - { "name": "Sec-Fetch-Site", "value": "same-origin" }, - { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36" }, - { "name": "sec-ch-ua", "value": "\"Not)A;Brand\";v=\"24\", \"Chromium\";v=\"116\"" }, - { "name": "sec-ch-ua-mobile", "value": "?0" }, - { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } - ], - "queryString": [], - "headersSize": -1, - "bodySize": -1 - }, - "response": { - "status": 200, - "statusText": "OK", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Access-Control-Allow-Origin", "value": "*" }, - { "name": "connection", "value": "close" }, - { "name": "content-length", "value": "227" }, - { "name": "content-type", "value": "application/json" }, - { "name": "date", "value": "Thu, 31 Aug 2023 14:55:34 GMT" }, - { "name": "server", "value": "uvicorn" } - ], - "content": { - "size": -1, - "mimeType": "application/json", - "text": "{\"access_token\":\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiNWIxYjFhZC05M2VjLTRjMjgtYWMxNy01OGMxNDQ0MWI1ZGQiLCJleHAiOjE3MjUwMjk3MzV9.8qhEtryWqA9RbwEP2s20umKdVE7J7jHGoogXZqxLNWk\",\"refresh_token\":null,\"token_type\":\"bearer\"}" - }, - "headersSize": -1, - "bodySize": -1, - "redirectURL": "" - }, - "cache": {}, - "timings": { "send": -1, "wait": -1, "receive": 0.727 } + { + "startedDateTime": "2024-02-28T14:32:30.937Z", + "time": 0.944, + "request": { + "method": "GET", + "url": "http://localhost:3000/api/v1/users/whoami", + "httpVersion": "HTTP/1.1", + "cookies": [], + "headers": [ + { "name": "Accept", "value": "application/json, text/plain, */*" }, + { "name": "Accept-Encoding", "value": "gzip, deflate, br, zstd" }, + { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, + { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMzg5ZmIyOS1kYWE2LTQwOGMtYjhjYi1iOGZmOGQxNzM0M2EiLCJleHAiOjE3NDA2NjY3NTB9.ef5W5jwNOeVzU3JZ7ylLYf2MLEJcVxC4-fF7EK9Ecdc" }, + { "name": "Connection", "value": "keep-alive" }, + { "name": "Cookie", "value": "access_token_lf=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMzg5ZmIyOS1kYWE2LTQwOGMtYjhjYi1iOGZmOGQxNzM0M2EiLCJleHAiOjE3NDA2NjY3NTB9.ef5W5jwNOeVzU3JZ7ylLYf2MLEJcVxC4-fF7EK9Ecdc" }, + { "name": "Host", "value": "localhost:3000" }, + { "name": "Referer", "value": "http://localhost:3000/" }, + { "name": "Sec-Fetch-Dest", "value": "empty" }, + { "name": "Sec-Fetch-Mode", "value": "cors" }, + { "name": "Sec-Fetch-Site", "value": "same-origin" }, + { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" }, + { "name": "sec-ch-ua", "value": "\"Chromium\";v=\"123\", \"Not:A-Brand\";v=\"8\"" }, + { "name": "sec-ch-ua-mobile", "value": "?0" }, + { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } + ], + "queryString": [], + "headersSize": -1, + "bodySize": -1 }, - { - "startedDateTime": "2023-08-31T14:55:35.586Z", - "time": 0.719, - "request": { - "method": "GET", - "url": "http://localhost:3000/api/v1/flows/", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Accept", "value": "application/json, text/plain, */*" }, - { "name": "Accept-Encoding", "value": "gzip, deflate, br" }, - { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, - { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiNWIxYjFhZC05M2VjLTRjMjgtYWMxNy01OGMxNDQ0MWI1ZGQiLCJleHAiOjE3MjUwMjk3MzV9.8qhEtryWqA9RbwEP2s20umKdVE7J7jHGoogXZqxLNWk" }, - { "name": "Connection", "value": "keep-alive" }, - { "name": "Cookie", "value": "access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiNWIxYjFhZC05M2VjLTRjMjgtYWMxNy01OGMxNDQ0MWI1ZGQiLCJleHAiOjE3MjUwMjk3MzV9.8qhEtryWqA9RbwEP2s20umKdVE7J7jHGoogXZqxLNWk; refresh_token=auto" }, - { "name": "Host", "value": "localhost:3000" }, - { "name": "Referer", "value": "http://localhost:3000/" }, - { "name": "Sec-Fetch-Dest", "value": "empty" }, - { "name": "Sec-Fetch-Mode", "value": "cors" }, - { "name": "Sec-Fetch-Site", "value": "same-origin" }, - { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36" }, - { "name": "sec-ch-ua", "value": "\"Not)A;Brand\";v=\"24\", \"Chromium\";v=\"116\"" }, - { "name": "sec-ch-ua-mobile", "value": "?0" }, - { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } - ], - "queryString": [], - "headersSize": -1, - "bodySize": -1 + "response": { + "status": 200, + "statusText": "OK", + "httpVersion": "HTTP/1.1", + "cookies": [], + "headers": [ + { "name": "Access-Control-Allow-Origin", "value": "*" }, + { "name": "connection", "value": "close" }, + { "name": "content-length", "value": "253" }, + { "name": "content-type", "value": "application/json" }, + { "name": "date", "value": "Wed, 28 Feb 2024 14:32:30 GMT" }, + { "name": "server", "value": "uvicorn" } + ], + "content": { + "size": -1, + "mimeType": "application/json", + "text": "{\"id\":\"0389fb29-daa6-408c-b8cb-b8ff8d17343a\",\"username\":\"langflow\",\"profile_image\":null,\"is_active\":true,\"is_superuser\":true,\"create_at\":\"2024-02-28T14:31:41.362911\",\"updated_at\":\"2024-02-28T14:32:30.864882\",\"last_login_at\":\"2024-02-28T14:32:30.863748\"}" }, - "response": { - "status": 200, - "statusText": "OK", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Access-Control-Allow-Origin", "value": "*" }, - { "name": "connection", "value": "close" }, - { "name": "content-length", "value": "2" }, - { "name": "content-type", "value": "application/json" }, - { "name": "date", "value": "Thu, 31 Aug 2023 14:55:34 GMT" }, - { "name": "server", "value": "uvicorn" } - ], - "content": { - "size": -1, - "mimeType": "application/json", - "text": "[]" - }, - "headersSize": -1, - "bodySize": -1, - "redirectURL": "" - }, - "cache": {}, - "timings": { "send": -1, "wait": -1, "receive": 0.719 } + "headersSize": -1, + "bodySize": -1, + "redirectURL": "" }, - { - "startedDateTime": "2023-08-31T14:55:35.586Z", - "time": 1.031, - "request": { - "method": "GET", - "url": "http://localhost:3000/api/v1/all", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Accept", "value": "application/json, text/plain, */*" }, - { "name": "Accept-Encoding", "value": "gzip, deflate, br" }, - { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, - { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiNWIxYjFhZC05M2VjLTRjMjgtYWMxNy01OGMxNDQ0MWI1ZGQiLCJleHAiOjE3MjUwMjk3MzV9.8qhEtryWqA9RbwEP2s20umKdVE7J7jHGoogXZqxLNWk" }, - { "name": "Connection", "value": "keep-alive" }, - { "name": "Cookie", "value": "access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiNWIxYjFhZC05M2VjLTRjMjgtYWMxNy01OGMxNDQ0MWI1ZGQiLCJleHAiOjE3MjUwMjk3MzV9.8qhEtryWqA9RbwEP2s20umKdVE7J7jHGoogXZqxLNWk; refresh_token=auto" }, - { "name": "Host", "value": "localhost:3000" }, - { "name": "Referer", "value": "http://localhost:3000/" }, - { "name": "Sec-Fetch-Dest", "value": "empty" }, - { "name": "Sec-Fetch-Mode", "value": "cors" }, - { "name": "Sec-Fetch-Site", "value": "same-origin" }, - { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36" }, - { "name": "sec-ch-ua", "value": "\"Not)A;Brand\";v=\"24\", \"Chromium\";v=\"116\"" }, - { "name": "sec-ch-ua-mobile", "value": "?0" }, - { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } - ], - "queryString": [], - "headersSize": -1, - "bodySize": -1 - }, - "response": { - "status": 200, - "statusText": "OK", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Access-Control-Allow-Origin", "value": "*" }, - { "name": "connection", "value": "close" }, - { "name": "content-length", "value": "251307" }, - { "name": "content-type", "value": "application/json" }, - { "name": "date", "value": "Thu, 31 Aug 2023 14:55:34 GMT" }, - { "name": "server", "value": "uvicorn" } - ], - "content": { - "size": -1, - "mimeType": "application/json", - "text": "{\"chains\":{\"ConversationChain\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":true},\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseMemory\",\"list\":false},\"output_parser\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":{\"_type\":\"default\"},\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLLMOutputParser\",\"list\":false},\"prompt\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":{\"input_variables\":[\"history\",\"input\"],\"input_types\":{},\"output_parser\":null,\"partial_variables\":{},\"template\":\"The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\\n\\nCurrent conversation:\\n{history}\\nHuman: {input}\\nAI:\",\"template_format\":\"f-string\",\"validate_template\":true,\"_type\":\"prompt\"},\"password\":false,\"name\":\"prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BasePromptTemplate\",\"list\":false},\"input_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"input\",\"password\":false,\"name\":\"input_key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"llm_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"llm_kwargs\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"output_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"response\",\"password\":false,\"name\":\"output_key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"return_final_only\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":true,\"password\":false,\"name\":\"return_final_only\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ConversationChain\"},\"description\":\"Chain to have a conversation and load context from memory.\",\"base_classes\":[\"LLMChain\",\"Chain\",\"ConversationChain\",\"function\"],\"display_name\":\"ConversationChain\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"ConversationalRetrievalChain\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Callbacks\",\"list\":false},\"condense_question_llm\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"condense_question_llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"condense_question_prompt\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":{\"input_variables\":[\"chat_history\",\"question\"],\"input_types\":{},\"output_parser\":null,\"partial_variables\":{},\"template\":\"Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question, in its original language.\\n\\nChat History:\\n{chat_history}\\nFollow Up Input: {question}\\nStandalone question:\",\"template_format\":\"f-string\",\"validate_template\":true,\"_type\":\"prompt\"},\"password\":false,\"name\":\"condense_question_prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BasePromptTemplate\",\"list\":false},\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"memory\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseChatMemory\",\"list\":false},\"retriever\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"retriever\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseRetriever\",\"list\":false},\"chain_type\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"stuff\",\"password\":false,\"options\":[\"stuff\",\"map_reduce\",\"map_rerank\",\"refine\"],\"name\":\"chain_type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"combine_docs_chain_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"combine_docs_chain_kwargs\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"return_source_documents\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":true,\"password\":false,\"name\":\"return_source_documents\",\"display_name\":\"Return source documents\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ConversationalRetrievalChain\"},\"description\":\"Convenience method to load chain from LLM and retriever.\",\"base_classes\":[\"BaseConversationalRetrievalChain\",\"Chain\",\"ConversationalRetrievalChain\",\"function\"],\"display_name\":\"ConversationalRetrievalChain\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/chains/popular/chat_vector_db\",\"beta\":false,\"error\":null},\"LLMChain\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":true},\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseMemory\",\"list\":false},\"output_parser\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLLMOutputParser\",\"list\":false},\"prompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BasePromptTemplate\",\"list\":false},\"llm_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"llm_kwargs\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"output_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"text\",\"password\":false,\"name\":\"output_key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"return_final_only\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":true,\"password\":false,\"name\":\"return_final_only\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"LLMChain\"},\"description\":\"Chain to run queries against LLMs.\",\"base_classes\":[\"LLMChain\",\"Chain\",\"function\"],\"display_name\":\"LLMChain\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/chains/foundational/llm_chain\",\"beta\":false,\"error\":null},\"LLMCheckerChain\":{\"template\":{\"check_assertions_prompt\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":{\"input_variables\":[\"assertions\"],\"input_types\":{},\"output_parser\":null,\"partial_variables\":{},\"template\":\"Here is a bullet point list of assertions:\\n{assertions}\\nFor each assertion, determine whether it is true or false. If it is false, explain why.\\n\\n\",\"template_format\":\"f-string\",\"validate_template\":true,\"_type\":\"prompt\"},\"password\":false,\"name\":\"check_assertions_prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"PromptTemplate\",\"list\":false},\"create_draft_answer_prompt\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":{\"input_variables\":[\"question\"],\"input_types\":{},\"output_parser\":null,\"partial_variables\":{},\"template\":\"{question}\\n\\n\",\"template_format\":\"f-string\",\"validate_template\":true,\"_type\":\"prompt\"},\"password\":false,\"name\":\"create_draft_answer_prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"PromptTemplate\",\"list\":false},\"list_assertions_prompt\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":{\"input_variables\":[\"statement\"],\"input_types\":{},\"output_parser\":null,\"partial_variables\":{},\"template\":\"Here is a statement:\\n{statement}\\nMake a bullet point list of the assumptions you made when producing the above statement.\\n\\n\",\"template_format\":\"f-string\",\"validate_template\":true,\"_type\":\"prompt\"},\"password\":false,\"name\":\"list_assertions_prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"PromptTemplate\",\"list\":false},\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"revised_answer_prompt\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":{\"input_variables\":[\"checked_assertions\",\"question\"],\"input_types\":{},\"output_parser\":null,\"partial_variables\":{},\"template\":\"{checked_assertions}\\n\\nQuestion: In light of the above assertions and checks, how would you answer the question '{question}'?\\n\\nAnswer:\",\"template_format\":\"f-string\",\"validate_template\":true,\"_type\":\"prompt\"},\"password\":false,\"name\":\"revised_answer_prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"PromptTemplate\",\"list\":false},\"_type\":\"LLMCheckerChain\"},\"description\":\"\",\"base_classes\":[\"Chain\",\"LLMCheckerChain\",\"function\"],\"display_name\":\"LLMCheckerChain\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/chains/additional/llm_checker\",\"beta\":false,\"error\":null},\"LLMMathChain\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":true},\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"llm_chain\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm_chain\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"LLMChain\",\"list\":false},\"memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseMemory\",\"list\":false},\"prompt\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":{\"input_variables\":[\"question\"],\"input_types\":{},\"output_parser\":null,\"partial_variables\":{},\"template\":\"Translate a math problem into a expression that can be executed using Python's numexpr library. Use the output of running this code to answer the question.\\n\\nQuestion: ${{Question with math problem.}}\\n```text\\n${{single line mathematical expression that solves the problem}}\\n```\\n...numexpr.evaluate(text)...\\n```output\\n${{Output of running the code}}\\n```\\nAnswer: ${{Answer}}\\n\\nBegin.\\n\\nQuestion: What is 37593 * 67?\\n```text\\n37593 * 67\\n```\\n...numexpr.evaluate(\\\"37593 * 67\\\")...\\n```output\\n2518731\\n```\\nAnswer: 2518731\\n\\nQuestion: 37593^(1/5)\\n```text\\n37593**(1/5)\\n```\\n...numexpr.evaluate(\\\"37593**(1/5)\\\")...\\n```output\\n8.222831614237718\\n```\\nAnswer: 8.222831614237718\\n\\nQuestion: {question}\\n\",\"template_format\":\"f-string\",\"validate_template\":true,\"_type\":\"prompt\"},\"password\":false,\"name\":\"prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BasePromptTemplate\",\"list\":false},\"input_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"question\",\"password\":false,\"name\":\"input_key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"output_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"answer\",\"password\":false,\"name\":\"output_key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"LLMMathChain\"},\"description\":\"Chain that interprets a prompt and executes python code to do math.\",\"base_classes\":[\"Chain\",\"LLMMathChain\",\"function\"],\"display_name\":\"LLMMathChain\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/chains/additional/llm_math\",\"beta\":false,\"error\":null},\"RetrievalQA\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":true},\"combine_documents_chain\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"combine_documents_chain\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseCombineDocumentsChain\",\"list\":false},\"memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseMemory\",\"list\":false},\"retriever\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"retriever\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseRetriever\",\"list\":false},\"input_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"query\",\"password\":false,\"name\":\"input_key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"output_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"result\",\"password\":false,\"name\":\"output_key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"return_source_documents\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":true,\"password\":false,\"name\":\"return_source_documents\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"RetrievalQA\"},\"description\":\"Chain for question-answering against an index.\",\"base_classes\":[\"Chain\",\"RetrievalQA\",\"BaseRetrievalQA\",\"function\"],\"display_name\":\"RetrievalQA\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/chains/popular/vector_db_qa\",\"beta\":false,\"error\":null},\"RetrievalQAWithSourcesChain\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":true},\"combine_documents_chain\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"combine_documents_chain\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseCombineDocumentsChain\",\"list\":false},\"memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseMemory\",\"list\":false},\"retriever\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"retriever\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseRetriever\",\"list\":false},\"answer_key\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"answer\",\"password\":false,\"name\":\"answer_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"input_docs_key\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"docs\",\"password\":false,\"name\":\"input_docs_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"max_tokens_limit\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":3375,\"password\":false,\"name\":\"max_tokens_limit\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"question_key\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"question\",\"password\":false,\"name\":\"question_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"reduce_k_below_max_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"reduce_k_below_max_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"return_source_documents\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":true,\"password\":false,\"name\":\"return_source_documents\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"sources_answer_key\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"sources\",\"password\":false,\"name\":\"sources_answer_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"RetrievalQAWithSourcesChain\"},\"description\":\"Question-answering with sources over an index.\",\"base_classes\":[\"Chain\",\"BaseQAWithSourcesChain\",\"RetrievalQAWithSourcesChain\",\"function\"],\"display_name\":\"RetrievalQAWithSourcesChain\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"SQLDatabaseChain\":{\"template\":{\"db\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"db\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"SQLDatabase\",\"list\":false},\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"prompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BasePromptTemplate\",\"list\":false},\"_type\":\"SQLDatabaseChain\"},\"description\":\"\",\"base_classes\":[\"Chain\",\"SQLDatabaseChain\",\"function\"],\"display_name\":\"SQLDatabaseChain\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"CombineDocsChain\":{\"template\":{\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"chain_type\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"stuff\",\"password\":false,\"options\":[\"stuff\",\"map_reduce\",\"map_rerank\",\"refine\"],\"name\":\"chain_type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"_type\":\"load_qa_chain\"},\"description\":\"Load question answering chain.\",\"base_classes\":[\"BaseCombineDocumentsChain\",\"function\"],\"display_name\":\"CombineDocsChain\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"SeriesCharacterChain\":{\"template\":{\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"character\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"character\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"series\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"series\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"SeriesCharacterChain\"},\"description\":\"SeriesCharacterChain is a chain you can use to have a conversation with a character from a series.\",\"base_classes\":[\"LLMChain\",\"BaseCustomChain\",\"Chain\",\"ConversationChain\",\"SeriesCharacterChain\",\"function\"],\"display_name\":\"SeriesCharacterChain\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"MidJourneyPromptChain\":{\"template\":{\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseChatMemory\",\"list\":false},\"_type\":\"MidJourneyPromptChain\"},\"description\":\"MidJourneyPromptChain is a chain you can use to generate new MidJourney prompts.\",\"base_classes\":[\"LLMChain\",\"BaseCustomChain\",\"Chain\",\"ConversationChain\",\"MidJourneyPromptChain\"],\"display_name\":\"MidJourneyPromptChain\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"TimeTravelGuideChain\":{\"template\":{\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseChatMemory\",\"list\":false},\"_type\":\"TimeTravelGuideChain\"},\"description\":\"Time travel guide chain.\",\"base_classes\":[\"LLMChain\",\"BaseCustomChain\",\"TimeTravelGuideChain\",\"Chain\",\"ConversationChain\"],\"display_name\":\"TimeTravelGuideChain\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"PromptRunner\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\n\\nfrom langchain.llms.base import BaseLLM\\nfrom langchain.prompts import PromptTemplate\\nfrom langchain.schema import Document\\n\\n\\nclass PromptRunner(CustomComponent):\\n display_name: str = \\\"Prompt Runner\\\"\\n description: str = \\\"Run a Chain with the given PromptTemplate\\\"\\n beta = True\\n field_config = {\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"prompt\\\": {\\n \\\"display_name\\\": \\\"Prompt Template\\\",\\n \\\"info\\\": \\\"Make sure the prompt has all variables filled.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self, llm: BaseLLM, prompt: PromptTemplate, inputs: dict = {}\\n ) -> Document:\\n chain = prompt | llm\\n # The input is an empty dict because the prompt is already filled\\n result = chain.invoke(input=inputs)\\n if hasattr(result, \\\"content\\\"):\\n result = result.content\\n self.repr_value = result\\n return Document(page_content=str(result))\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"inputs\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"inputs\",\"display_name\":\"inputs\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLLM\",\"list\":false},\"prompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"prompt\",\"display_name\":\"Prompt Template\",\"advanced\":false,\"dynamic\":false,\"info\":\"Make sure the prompt has all variables filled.\",\"type\":\"PromptTemplate\",\"list\":false}},\"description\":\"Run a Chain with the given PromptTemplate\",\"base_classes\":[\"Document\"],\"display_name\":\"Prompt Runner\",\"custom_fields\":{\"inputs\":null,\"llm\":null,\"prompt\":null},\"output_types\":[\"PromptRunner\"],\"documentation\":\"\",\"beta\":true,\"error\":null}},\"agents\":{\"ZeroShotAgent\":{\"template\":{\"callback_manager\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callback_manager\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseCallbackManager\",\"list\":false},\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"output_parser\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"AgentOutputParser\",\"list\":false},\"tools\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"tools\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseTool\",\"list\":true},\"format_instructions\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"Use the following format:\\n\\nQuestion: the input question you must answer\\nThought: you should always think about what to do\\nAction: the action to take, should be one of [{tool_names}]\\nAction Input: the input to the action\\nObservation: the result of the action\\n... (this Thought/Action/Action Input/Observation can repeat N times)\\nThought: I now know the final answer\\nFinal Answer: the final answer to the original input question\",\"password\":false,\"name\":\"format_instructions\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"input_variables\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_variables\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"prefix\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"Answer the following questions as best you can. You have access to the following tools:\",\"password\":false,\"name\":\"prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"suffix\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"Begin!\\n\\nQuestion: {input}\\nThought:{agent_scratchpad}\",\"password\":false,\"name\":\"suffix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"ZeroShotAgent\"},\"description\":\"Construct an agent from an LLM and tools.\",\"base_classes\":[\"Agent\",\"BaseSingleActionAgent\",\"ZeroShotAgent\",\"function\"],\"display_name\":\"ZeroShotAgent\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/agents/how_to/custom_mrkl_agent\",\"beta\":false,\"error\":null},\"JsonAgent\":{\"template\":{\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"toolkit\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"toolkit\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseToolkit\",\"list\":false},\"_type\":\"json_agent\"},\"description\":\"Construct a json agent from an LLM and tools.\",\"base_classes\":[\"AgentExecutor\"],\"display_name\":\"JsonAgent\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/agents/toolkits/openapi\",\"beta\":false,\"error\":null},\"CSVAgent\":{\"template\":{\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"suffixes\":[\".csv\"],\"password\":false,\"name\":\"path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\"csv\"],\"file_path\":null},\"_type\":\"csv_agent\"},\"description\":\"Construct a CSV agent from a CSV and tools.\",\"base_classes\":[\"AgentExecutor\"],\"display_name\":\"CSVAgent\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/agents/toolkits/csv\",\"beta\":false,\"error\":null},\"AgentInitializer\":{\"template\":{\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseChatMemory\",\"list\":false},\"tools\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"tools\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Tool\",\"list\":true},\"agent\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"zero-shot-react-description\",\"password\":false,\"options\":[\"zero-shot-react-description\",\"react-docstore\",\"self-ask-with-search\",\"conversational-react-description\",\"openai-functions\",\"openai-multi-functions\"],\"name\":\"agent\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"_type\":\"initialize_agent\"},\"description\":\"Construct a zero shot agent from an LLM and tools.\",\"base_classes\":[\"AgentExecutor\",\"function\"],\"display_name\":\"AgentInitializer\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/agents/agent_types/\",\"beta\":false,\"error\":null},\"VectorStoreAgent\":{\"template\":{\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"vectorstoreinfo\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"vectorstoreinfo\",\"display_name\":\"Vector Store Info\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"VectorStoreInfo\",\"list\":false},\"_type\":\"vectorstore_agent\"},\"description\":\"Construct an agent from a Vector Store.\",\"base_classes\":[\"AgentExecutor\"],\"display_name\":\"VectorStoreAgent\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"VectorStoreRouterAgent\":{\"template\":{\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"vectorstoreroutertoolkit\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"vectorstoreroutertoolkit\",\"display_name\":\"Vector Store Router Toolkit\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"VectorStoreRouterToolkit\",\"list\":false},\"_type\":\"vectorstorerouter_agent\"},\"description\":\"Construct an agent from a Vector Store Router.\",\"base_classes\":[\"AgentExecutor\"],\"display_name\":\"VectorStoreRouterAgent\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"SQLAgent\":{\"template\":{\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"database_uri\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"database_uri\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"sql_agent\"},\"description\":\"Construct an SQL agent from an LLM and tools.\",\"base_classes\":[\"AgentExecutor\"],\"display_name\":\"SQLAgent\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"OpenAIConversationalAgent\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom typing import Optional\\nfrom langchain.prompts import SystemMessagePromptTemplate\\nfrom langchain.tools import Tool\\nfrom langchain.schema.memory import BaseMemory\\nfrom langchain.chat_models import ChatOpenAI\\n\\nfrom langchain.agents.agent import AgentExecutor\\nfrom langchain.agents.openai_functions_agent.base import OpenAIFunctionsAgent\\nfrom langchain.memory.token_buffer import ConversationTokenBufferMemory\\nfrom langchain.prompts.chat import MessagesPlaceholder\\nfrom langchain.agents.agent_toolkits.conversational_retrieval.openai_functions import (\\n _get_default_system_message,\\n)\\n\\n\\nclass ConversationalAgent(CustomComponent):\\n display_name: str = \\\"OpenAI Conversational Agent\\\"\\n description: str = \\\"Conversational Agent that can use OpenAI's function calling API\\\"\\n\\n def build_config(self):\\n openai_function_models = [\\n \\\"gpt-3.5-turbo-0613\\\",\\n \\\"gpt-3.5-turbo-16k-0613\\\",\\n \\\"gpt-4-0613\\\",\\n \\\"gpt-4-32k-0613\\\",\\n ]\\n return {\\n \\\"tools\\\": {\\\"is_list\\\": True, \\\"display_name\\\": \\\"Tools\\\"},\\n \\\"memory\\\": {\\\"display_name\\\": \\\"Memory\\\"},\\n \\\"system_message\\\": {\\\"display_name\\\": \\\"System Message\\\"},\\n \\\"max_token_limit\\\": {\\\"display_name\\\": \\\"Max Token Limit\\\"},\\n \\\"model_name\\\": {\\n \\\"display_name\\\": \\\"Model Name\\\",\\n \\\"options\\\": openai_function_models,\\n \\\"value\\\": openai_function_models[0],\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n model_name: str,\\n openai_api_key: str,\\n tools: Tool,\\n openai_api_base: Optional[str] = None,\\n memory: Optional[BaseMemory] = None,\\n system_message: Optional[SystemMessagePromptTemplate] = None,\\n max_token_limit: int = 2000,\\n ) -> AgentExecutor:\\n llm = ChatOpenAI(\\n model=model_name,\\n openai_api_key=openai_api_key,\\n openai_api_base=openai_api_base,\\n )\\n if not memory:\\n memory_key = \\\"chat_history\\\"\\n memory = ConversationTokenBufferMemory(\\n memory_key=memory_key,\\n return_messages=True,\\n output_key=\\\"output\\\",\\n llm=llm,\\n max_token_limit=max_token_limit,\\n )\\n else:\\n memory_key = memory.memory_key # type: ignore\\n\\n _system_message = system_message or _get_default_system_message()\\n prompt = OpenAIFunctionsAgent.create_prompt(\\n system_message=_system_message, # type: ignore\\n extra_prompt_messages=[MessagesPlaceholder(variable_name=memory_key)],\\n )\\n agent = OpenAIFunctionsAgent(\\n llm=llm, tools=tools, prompt=prompt # type: ignore\\n )\\n return AgentExecutor(\\n agent=agent,\\n tools=tools, # type: ignore\\n memory=memory,\\n verbose=True,\\n return_intermediate_steps=True,\\n handle_parsing_errors=True,\\n )\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"max_token_limit\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":2000,\"password\":false,\"name\":\"max_token_limit\",\"display_name\":\"Max Token Limit\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseMemory\",\"list\":false},\"model_name\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"gpt-3.5-turbo-0613\",\"password\":false,\"options\":[\"gpt-3.5-turbo-0613\",\"gpt-3.5-turbo-16k-0613\",\"gpt-4-0613\",\"gpt-4-32k-0613\"],\"name\":\"model_name\",\"display_name\":\"Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_api_base\",\"display_name\":\"openai_api_base\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_api_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_api_key\",\"display_name\":\"openai_api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"system_message\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"system_message\",\"display_name\":\"System Message\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"SystemMessagePromptTemplate\",\"list\":false},\"tools\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"tools\",\"display_name\":\"Tools\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Tool\",\"list\":true}},\"description\":\"Conversational Agent that can use OpenAI's function calling API\",\"base_classes\":[\"Chain\",\"AgentExecutor\"],\"display_name\":\"OpenAI Conversational Agent\",\"custom_fields\":{\"max_token_limit\":null,\"memory\":null,\"model_name\":null,\"openai_api_base\":null,\"openai_api_key\":null,\"system_message\":null,\"tools\":null},\"output_types\":[\"OpenAIConversationalAgent\"],\"documentation\":\"\",\"beta\":true,\"error\":null}},\"prompts\":{\"ChatMessagePromptTemplate\":{\"template\":{\"additional_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"additional_kwargs\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"prompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\\nYou are a helpful assistant that talks casually about life in general.\\nYou are a good listener and you can talk about anything.\\n\",\"password\":false,\"name\":\"prompt\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"prompt\",\"list\":false},\"role\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"role\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"ChatMessagePromptTemplate\"},\"description\":\"Chat message prompt template.\",\"base_classes\":[\"BaseStringMessagePromptTemplate\",\"ChatMessagePromptTemplate\",\"BaseMessagePromptTemplate\"],\"display_name\":\"ChatMessagePromptTemplate\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/msg_prompt_templates\",\"beta\":false,\"error\":null},\"ChatPromptTemplate\":{\"template\":{\"messages\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"messages\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"BaseMessagePromptTemplate\",\"list\":true},\"output_parser\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"BaseOutputParser\",\"list\":false},\"input_types\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_types\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"input_variables\":{\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":true},\"partial_variables\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"partial_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"ChatPromptTemplate\"},\"description\":\"A prompt template for chat models.\",\"base_classes\":[\"BaseChatPromptTemplate\",\"BasePromptTemplate\",\"ChatPromptTemplate\"],\"display_name\":\"ChatPromptTemplate\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/how_to/prompts\",\"beta\":false,\"error\":null},\"HumanMessagePromptTemplate\":{\"template\":{\"additional_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"additional_kwargs\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"prompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\\nYou are a helpful assistant that talks casually about life in general.\\nYou are a good listener and you can talk about anything.\\n\",\"password\":false,\"name\":\"prompt\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"prompt\",\"list\":false},\"_type\":\"HumanMessagePromptTemplate\"},\"description\":\"Human message prompt template. This is a message sent from the user.\",\"base_classes\":[\"BaseStringMessagePromptTemplate\",\"HumanMessagePromptTemplate\",\"BaseMessagePromptTemplate\"],\"display_name\":\"HumanMessagePromptTemplate\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/how_to/prompts\",\"beta\":false,\"error\":null},\"PromptTemplate\":{\"template\":{\"output_parser\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"BaseOutputParser\",\"list\":false},\"input_types\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_types\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"input_variables\":{\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"input_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":true},\"partial_variables\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"partial_variables\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"template\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"password\":false,\"name\":\"template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"prompt\",\"list\":false},\"template_format\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"f-string\",\"password\":false,\"name\":\"template_format\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"str\",\"list\":false},\"validate_template\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":true,\"password\":false,\"name\":\"validate_template\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"PromptTemplate\"},\"description\":\"A prompt template for a language model.\",\"base_classes\":[\"StringPromptTemplate\",\"BasePromptTemplate\",\"PromptTemplate\"],\"display_name\":\"PromptTemplate\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/\",\"beta\":false,\"error\":null},\"SystemMessagePromptTemplate\":{\"template\":{\"additional_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"additional_kwargs\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"prompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\\nYou are a helpful assistant that talks casually about life in general.\\nYou are a good listener and you can talk about anything.\\n\",\"password\":false,\"name\":\"prompt\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"prompt\",\"list\":false},\"_type\":\"SystemMessagePromptTemplate\"},\"description\":\"System message prompt template.\",\"base_classes\":[\"BaseStringMessagePromptTemplate\",\"BaseMessagePromptTemplate\",\"SystemMessagePromptTemplate\"],\"display_name\":\"SystemMessagePromptTemplate\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/how_to/prompts\",\"beta\":false,\"error\":null}},\"llms\":{\"Anthropic\":{\"template\":{\"anthropic_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"anthropic_api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"SecretStr\",\"list\":false},\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":true},\"count_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"count_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Callable[[str], int]\",\"list\":false},\"AI_PROMPT\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"AI_PROMPT\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"HUMAN_PROMPT\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"HUMAN_PROMPT\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"anthropic_api_url\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"anthropic_api_url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"async_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"async_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"default_request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"max_tokens_to_sample\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":256,\"password\":false,\"name\":\"max_tokens_to_sample\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"claude-2\",\"password\":false,\"name\":\"model\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"top_k\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"top_k\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"top_p\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"top_p\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"Anthropic\"},\"description\":\"Anthropic large language models.\",\"base_classes\":[\"_AnthropicCommon\",\"BaseLanguageModel\",\"Anthropic\",\"BaseLLM\",\"LLM\"],\"display_name\":\"Anthropic\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"Cohere\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":true},\"async_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"async_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"cohere_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"cohere_api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"frequency_penalty\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":0.0,\"password\":false,\"name\":\"frequency_penalty\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"k\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":0,\"password\":false,\"name\":\"k\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":10,\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"max_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":256,\"password\":true,\"name\":\"max_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"model\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"p\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"p\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"presence_penalty\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":0.0,\"password\":false,\"name\":\"presence_penalty\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"stop\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"stop\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":0.75,\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"truncate\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"truncate\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"Cohere\"},\"description\":\"Cohere large language models.\",\"base_classes\":[\"BaseLanguageModel\",\"BaseLLM\",\"LLM\",\"BaseCohere\",\"Cohere\"],\"display_name\":\"Cohere\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/cohere\",\"beta\":false,\"error\":null},\"CTransformers\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":true},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"config\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"{\\n \\\"top_k\\\": 40,\\n \\\"top_p\\\": 0.95,\\n \\\"temperature\\\": 0.8,\\n \\\"repetition_penalty\\\": 1.1,\\n \\\"last_n_tokens\\\": 64,\\n \\\"seed\\\": -1,\\n \\\"max_new_tokens\\\": 256,\\n \\\"stop\\\": null,\\n \\\"stream\\\": false,\\n \\\"reset\\\": true,\\n \\\"batch_size\\\": 8,\\n \\\"threads\\\": -1,\\n \\\"context_length\\\": -1,\\n \\\"gpu_layers\\\": 0\\n}\",\"password\":false,\"name\":\"config\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"lib\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"lib\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"model_file\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_file\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"model_type\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"CTransformers\"},\"description\":\"C Transformers LLM models.\",\"base_classes\":[\"CTransformers\",\"BaseLanguageModel\",\"BaseLLM\",\"LLM\"],\"display_name\":\"CTransformers\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/ctransformers\",\"beta\":false,\"error\":null},\"HuggingFaceHub\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":true},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"huggingfacehub_api_token\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"huggingfacehub_api_token\",\"display_name\":\"HuggingFace Hub API Token\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"repo_id\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"gpt2\",\"password\":false,\"name\":\"repo_id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"task\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"text-generation\",\"password\":false,\"options\":[\"text-generation\",\"text2text-generation\",\"summarization\"],\"name\":\"task\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"HuggingFaceHub\"},\"description\":\"HuggingFaceHub models.\",\"base_classes\":[\"HuggingFaceHub\",\"BaseLanguageModel\",\"BaseLLM\",\"LLM\"],\"display_name\":\"HuggingFaceHub\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/huggingface_hub\",\"beta\":false,\"error\":null},\"LlamaCpp\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":true},\"grammar\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"grammar\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"ForwardRef('str\",\"list\":false},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"echo\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"echo\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"f16_kv\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":true,\"password\":false,\"name\":\"f16_kv\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"grammar_path\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"grammar_path\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"last_n_tokens_size\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":64,\"password\":false,\"name\":\"last_n_tokens_size\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"logits_all\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"logits_all\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"logprobs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"logprobs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"lora_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"lora_base\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"lora_path\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"lora_path\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"max_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":256,\"password\":true,\"name\":\"max_tokens\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"n_batch\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":8,\"password\":false,\"name\":\"n_batch\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"n_ctx\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":512,\"password\":false,\"name\":\"n_ctx\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"n_gpu_layers\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"n_gpu_layers\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"n_parts\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":-1,\"password\":false,\"name\":\"n_parts\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"n_threads\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"n_threads\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"repeat_penalty\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":1.1,\"password\":false,\"name\":\"repeat_penalty\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"rope_freq_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":10000.0,\"password\":false,\"name\":\"rope_freq_base\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"rope_freq_scale\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":1.0,\"password\":false,\"name\":\"rope_freq_scale\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"seed\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":-1,\"password\":false,\"name\":\"seed\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"stop\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"stop\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":true,\"password\":false,\"name\":\"streaming\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"suffix\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"password\":false,\"name\":\"suffix\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":0.8,\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"top_k\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":40,\"password\":false,\"name\":\"top_k\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"top_p\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":0.95,\"password\":false,\"name\":\"top_p\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"use_mlock\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"use_mlock\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"use_mmap\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":true,\"password\":false,\"name\":\"use_mmap\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":true,\"password\":false,\"name\":\"verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"vocab_only\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"vocab_only\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"LlamaCpp\"},\"description\":\"llama.cpp model.\",\"base_classes\":[\"BaseLanguageModel\",\"BaseLLM\",\"LLM\",\"LlamaCpp\"],\"display_name\":\"LlamaCpp\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/llamacpp\",\"beta\":false,\"error\":null},\"OpenAI\":{\"template\":{\"allowed_special\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":[],\"password\":false,\"name\":\"allowed_special\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Literal'all'\",\"list\":true},\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":true},\"disallowed_special\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"all\",\"password\":false,\"name\":\"disallowed_special\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Literal'all'\",\"list\":false},\"batch_size\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":20,\"password\":false,\"name\":\"batch_size\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"best_of\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"best_of\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"frequency_penalty\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":0,\"password\":false,\"name\":\"frequency_penalty\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"logit_bias\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"logit_bias\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":6,\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"max_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":256,\"password\":true,\"name\":\"max_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"text-davinci-003\",\"password\":false,\"options\":[\"text-davinci-003\",\"text-davinci-002\",\"text-curie-001\",\"text-babbage-001\",\"text-ada-001\"],\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"n\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"n\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":false,\"dynamic\":false,\"info\":\"\\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\\n\",\"type\":\"str\",\"list\":false},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"presence_penalty\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":0,\"password\":false,\"name\":\"presence_penalty\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":0.7,\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"top_p\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"top_p\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"OpenAI\"},\"description\":\"OpenAI large language models.\",\"base_classes\":[\"BaseLanguageModel\",\"BaseLLM\",\"BaseOpenAI\",\"OpenAI\"],\"display_name\":\"OpenAI\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/openai\",\"beta\":false,\"error\":null},\"VertexAI\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":true},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"ForwardRef(\\\"'_LanguageModel'\\\")\",\"list\":false},\"credentials\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"suffixes\":[\".json\"],\"password\":false,\"name\":\"credentials\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\"json\"],\"file_path\":null},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"location\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"us-central1\",\"password\":false,\"name\":\"location\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"max_output_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":128,\"password\":false,\"name\":\"max_output_tokens\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":6,\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"text-bison\",\"password\":false,\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"project\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"project\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_parallelism\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":5,\"password\":false,\"name\":\"request_parallelism\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"stop\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"stop\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":0.0,\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"top_k\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":40,\"password\":false,\"name\":\"top_k\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"top_p\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":0.95,\"password\":false,\"name\":\"top_p\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"tuned_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"tuned_model_name\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"VertexAI\"},\"description\":\"Google Vertex AI large language models.\",\"base_classes\":[\"_VertexAICommon\",\"VertexAI\",\"BaseLanguageModel\",\"BaseLLM\",\"_VertexAIBase\"],\"display_name\":\"VertexAI\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/google_vertex_ai_palm\",\"beta\":false,\"error\":null},\"ChatAnthropic\":{\"template\":{\"anthropic_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"anthropic_api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"SecretStr\",\"list\":false},\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":true},\"count_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"count_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Callable[[str], int]\",\"list\":false},\"AI_PROMPT\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"AI_PROMPT\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"HUMAN_PROMPT\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"HUMAN_PROMPT\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"anthropic_api_url\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"anthropic_api_url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"async_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"async_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"default_request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"default_request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"max_tokens_to_sample\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":256,\"password\":false,\"name\":\"max_tokens_to_sample\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"claude-2\",\"password\":false,\"name\":\"model\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"top_k\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"top_k\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"top_p\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"top_p\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ChatAnthropic\"},\"description\":\"`Anthropic` chat large language models.\",\"base_classes\":[\"_AnthropicCommon\",\"BaseLanguageModel\",\"BaseChatModel\",\"ChatAnthropic\",\"BaseLLM\"],\"display_name\":\"ChatAnthropic\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/integrations/anthropic\",\"beta\":false,\"error\":null},\"ChatOpenAI\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":true},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":6,\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"max_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"max_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"gpt-3.5-turbo-0613\",\"password\":false,\"options\":[\"gpt-3.5-turbo-0613\",\"gpt-3.5-turbo\",\"gpt-3.5-turbo-16k-0613\",\"gpt-3.5-turbo-16k\",\"gpt-4-0613\",\"gpt-4-32k-0613\",\"gpt-4\",\"gpt-4-32k\"],\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"n\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":1,\"password\":false,\"name\":\"n\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":false,\"dynamic\":false,\"info\":\"\\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\\n\",\"type\":\"str\",\"list\":false},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":0.7,\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ChatOpenAI\"},\"description\":\"`OpenAI` Chat large language models API.\",\"base_classes\":[\"BaseLanguageModel\",\"BaseChatModel\",\"ChatOpenAI\",\"BaseLLM\"],\"display_name\":\"ChatOpenAI\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai\",\"beta\":false,\"error\":null},\"ChatVertexAI\":{\"template\":{\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":true},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"ForwardRef(\\\"'_LanguageModel'\\\")\",\"list\":false},\"credentials\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"suffixes\":[\".json\"],\"password\":false,\"name\":\"credentials\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\"json\"],\"file_path\":null},\"cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"location\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"us-central1\",\"password\":false,\"name\":\"location\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"max_output_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":128,\"password\":false,\"name\":\"max_output_tokens\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":6,\"password\":false,\"name\":\"max_retries\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"chat-bison\",\"password\":false,\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"project\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"project\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_parallelism\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":5,\"password\":false,\"name\":\"request_parallelism\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"stop\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"stop\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":0.0,\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"top_k\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":40,\"password\":false,\"name\":\"top_k\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"top_p\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":0.95,\"password\":false,\"name\":\"top_p\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"verbose\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ChatVertexAI\"},\"description\":\"`Vertex AI` Chat large language models API.\",\"base_classes\":[\"_VertexAICommon\",\"BaseChatModel\",\"BaseLanguageModel\",\"_VertexAIBase\",\"ChatVertexAI\",\"BaseLLM\"],\"display_name\":\"ChatVertexAI\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/integrations/google_vertex_ai_palm\",\"beta\":false,\"error\":null},\"HuggingFaceEndpoints\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Optional\\nfrom langflow import CustomComponent\\nfrom langchain.llms.huggingface_endpoint import HuggingFaceEndpoint\\nfrom langchain.llms.base import BaseLLM\\n\\n\\nclass HuggingFaceEndpointsComponent(CustomComponent):\\n display_name: str = \\\"Hugging Face Inference API\\\"\\n description: str = \\\"LLM model from Hugging Face Inference API.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"endpoint_url\\\": {\\\"display_name\\\": \\\"Endpoint URL\\\", \\\"password\\\": True},\\n \\\"task\\\": {\\n \\\"display_name\\\": \\\"Task\\\",\\n \\\"options\\\": [\\\"text2text-generation\\\", \\\"text-generation\\\", \\\"summarization\\\"],\\n },\\n \\\"huggingfacehub_api_token\\\": {\\\"display_name\\\": \\\"API token\\\", \\\"password\\\": True},\\n \\\"model_kwargs\\\": {\\n \\\"display_name\\\": \\\"Model Keyword Arguments\\\",\\n \\\"field_type\\\": \\\"code\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n endpoint_url: str,\\n task: str = \\\"text2text-generation\\\",\\n huggingfacehub_api_token: Optional[str] = None,\\n model_kwargs: Optional[dict] = None,\\n ) -> BaseLLM:\\n try:\\n output = HuggingFaceEndpoint(\\n endpoint_url=endpoint_url,\\n task=task,\\n huggingfacehub_api_token=huggingfacehub_api_token,\\n model_kwargs=model_kwargs,\\n )\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to HuggingFace Endpoints API.\\\") from e\\n return output\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"endpoint_url\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"endpoint_url\",\"display_name\":\"Endpoint URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"huggingfacehub_api_token\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"huggingfacehub_api_token\",\"display_name\":\"API token\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"display_name\":\"Model Keyword Arguments\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"code\",\"list\":false},\"task\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"text2text-generation\",\"password\":false,\"options\":[\"text2text-generation\",\"text-generation\",\"summarization\"],\"name\":\"task\",\"display_name\":\"Task\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true}},\"description\":\"LLM model from Hugging Face Inference API.\",\"base_classes\":[\"BaseLanguageModel\",\"BaseLLM\"],\"display_name\":\"Hugging Face Inference API\",\"custom_fields\":{\"endpoint_url\":null,\"huggingfacehub_api_token\":null,\"model_kwargs\":null,\"task\":null},\"output_types\":[\"HuggingFaceEndpoints\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"BaiduQianfanChatEndpoints\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Optional\\nfrom langflow import CustomComponent\\nfrom langchain.chat_models.baidu_qianfan_endpoint import QianfanChatEndpoint\\nfrom langchain.llms.base import BaseLLM\\n\\n\\nclass QianfanChatEndpointComponent(CustomComponent):\\n display_name: str = \\\"QianfanChatEndpoint\\\"\\n description: str = (\\n \\\"Baidu Qianfan chat models. Get more detail from \\\"\\n \\\"https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint.\\\"\\n )\\n\\n def build_config(self):\\n return {\\n \\\"model\\\": {\\n \\\"display_name\\\": \\\"Model Name\\\",\\n \\\"options\\\": [\\n \\\"ERNIE-Bot\\\",\\n \\\"ERNIE-Bot-turbo\\\",\\n \\\"BLOOMZ-7B\\\",\\n \\\"Llama-2-7b-chat\\\",\\n \\\"Llama-2-13b-chat\\\",\\n \\\"Llama-2-70b-chat\\\",\\n \\\"Qianfan-BLOOMZ-7B-compressed\\\",\\n \\\"Qianfan-Chinese-Llama-2-7B\\\",\\n \\\"ChatGLM2-6B-32K\\\",\\n \\\"AquilaChat-7B\\\",\\n ],\\n \\\"info\\\": \\\"https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint\\\",\\n \\\"required\\\": True,\\n },\\n \\\"qianfan_ak\\\": {\\n \\\"display_name\\\": \\\"Qianfan Ak\\\",\\n \\\"required\\\": True,\\n \\\"password\\\": True,\\n \\\"info\\\": \\\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\\\",\\n },\\n \\\"qianfan_sk\\\": {\\n \\\"display_name\\\": \\\"Qianfan Sk\\\",\\n \\\"required\\\": True,\\n \\\"password\\\": True,\\n \\\"info\\\": \\\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\\\",\\n },\\n \\\"top_p\\\": {\\n \\\"display_name\\\": \\\"Top p\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\\\",\\n \\\"value\\\": 0.8,\\n },\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\\\",\\n \\\"value\\\": 0.95,\\n },\\n \\\"penalty_score\\\": {\\n \\\"display_name\\\": \\\"Penalty Score\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\\\",\\n \\\"value\\\": 1.0,\\n },\\n \\\"endpoint\\\": {\\n \\\"display_name\\\": \\\"Endpoint\\\",\\n \\\"info\\\": \\\"Endpoint of the Qianfan LLM, required if custom model used.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n model: str = \\\"ERNIE-Bot-turbo\\\",\\n qianfan_ak: Optional[str] = None,\\n qianfan_sk: Optional[str] = None,\\n top_p: Optional[float] = None,\\n temperature: Optional[float] = None,\\n penalty_score: Optional[float] = None,\\n endpoint: Optional[str] = None,\\n ) -> BaseLLM:\\n try:\\n output = QianfanChatEndpoint( # type: ignore\\n model=model,\\n qianfan_ak=qianfan_ak,\\n qianfan_sk=qianfan_sk,\\n top_p=top_p,\\n temperature=temperature,\\n penalty_score=penalty_score,\\n endpoint=endpoint,\\n )\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to Baidu Qianfan API.\\\") from e\\n return output # type: ignore\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"endpoint\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"endpoint\",\"display_name\":\"Endpoint\",\"advanced\":false,\"dynamic\":false,\"info\":\"Endpoint of the Qianfan LLM, required if custom model used.\",\"type\":\"str\",\"list\":false},\"model\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"ERNIE-Bot-turbo\",\"password\":false,\"options\":[\"ERNIE-Bot\",\"ERNIE-Bot-turbo\",\"BLOOMZ-7B\",\"Llama-2-7b-chat\",\"Llama-2-13b-chat\",\"Llama-2-70b-chat\",\"Qianfan-BLOOMZ-7B-compressed\",\"Qianfan-Chinese-Llama-2-7B\",\"ChatGLM2-6B-32K\",\"AquilaChat-7B\"],\"name\":\"model\",\"display_name\":\"Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint\",\"type\":\"str\",\"list\":true},\"penalty_score\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":1.0,\"password\":false,\"name\":\"penalty_score\",\"display_name\":\"Penalty Score\",\"advanced\":false,\"dynamic\":false,\"info\":\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\",\"type\":\"float\",\"list\":false},\"qianfan_ak\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"qianfan_ak\",\"display_name\":\"Qianfan Ak\",\"advanced\":false,\"dynamic\":false,\"info\":\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\",\"type\":\"str\",\"list\":false},\"qianfan_sk\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"qianfan_sk\",\"display_name\":\"Qianfan Sk\",\"advanced\":false,\"dynamic\":false,\"info\":\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\",\"type\":\"str\",\"list\":false},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":0.95,\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\",\"type\":\"float\",\"list\":false},\"top_p\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":0.8,\"password\":false,\"name\":\"top_p\",\"display_name\":\"Top p\",\"advanced\":false,\"dynamic\":false,\"info\":\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\",\"type\":\"float\",\"list\":false}},\"description\":\"Baidu Qianfan chat models. Get more detail from https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint.\",\"base_classes\":[\"BaseLanguageModel\",\"BaseLLM\"],\"display_name\":\"QianfanChatEndpoint\",\"custom_fields\":{\"endpoint\":null,\"model\":null,\"penalty_score\":null,\"qianfan_ak\":null,\"qianfan_sk\":null,\"temperature\":null,\"top_p\":null},\"output_types\":[\"BaiduQianfanChatEndpoints\"],\"documentation\":\"\",\"beta\":true,\"error\":null},\"BaiduQianfanLLMEndpoints\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Optional\\nfrom langflow import CustomComponent\\nfrom langchain.llms.baidu_qianfan_endpoint import QianfanLLMEndpoint\\nfrom langchain.llms.base import BaseLLM\\n\\n\\nclass QianfanLLMEndpointComponent(CustomComponent):\\n display_name: str = \\\"QianfanLLMEndpoint\\\"\\n description: str = (\\n \\\"Baidu Qianfan hosted open source or customized models. \\\"\\n \\\"Get more detail from https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint\\\"\\n )\\n\\n def build_config(self):\\n return {\\n \\\"model\\\": {\\n \\\"display_name\\\": \\\"Model Name\\\",\\n \\\"options\\\": [\\n \\\"ERNIE-Bot\\\",\\n \\\"ERNIE-Bot-turbo\\\",\\n \\\"BLOOMZ-7B\\\",\\n \\\"Llama-2-7b-chat\\\",\\n \\\"Llama-2-13b-chat\\\",\\n \\\"Llama-2-70b-chat\\\",\\n \\\"Qianfan-BLOOMZ-7B-compressed\\\",\\n \\\"Qianfan-Chinese-Llama-2-7B\\\",\\n \\\"ChatGLM2-6B-32K\\\",\\n \\\"AquilaChat-7B\\\",\\n ],\\n \\\"info\\\": \\\"https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint\\\",\\n \\\"required\\\": True,\\n },\\n \\\"qianfan_ak\\\": {\\n \\\"display_name\\\": \\\"Qianfan Ak\\\",\\n \\\"required\\\": True,\\n \\\"password\\\": True,\\n \\\"info\\\": \\\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\\\",\\n },\\n \\\"qianfan_sk\\\": {\\n \\\"display_name\\\": \\\"Qianfan Sk\\\",\\n \\\"required\\\": True,\\n \\\"password\\\": True,\\n \\\"info\\\": \\\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\\\",\\n },\\n \\\"top_p\\\": {\\n \\\"display_name\\\": \\\"Top p\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\\\",\\n \\\"value\\\": 0.8,\\n },\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\\\",\\n \\\"value\\\": 0.95,\\n },\\n \\\"penalty_score\\\": {\\n \\\"display_name\\\": \\\"Penalty Score\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\\\",\\n \\\"value\\\": 1.0,\\n },\\n \\\"endpoint\\\": {\\n \\\"display_name\\\": \\\"Endpoint\\\",\\n \\\"info\\\": \\\"Endpoint of the Qianfan LLM, required if custom model used.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n model: str = \\\"ERNIE-Bot-turbo\\\",\\n qianfan_ak: Optional[str] = None,\\n qianfan_sk: Optional[str] = None,\\n top_p: Optional[float] = None,\\n temperature: Optional[float] = None,\\n penalty_score: Optional[float] = None,\\n endpoint: Optional[str] = None,\\n ) -> BaseLLM:\\n try:\\n output = QianfanLLMEndpoint( # type: ignore\\n model=model,\\n qianfan_ak=qianfan_ak,\\n qianfan_sk=qianfan_sk,\\n top_p=top_p,\\n temperature=temperature,\\n penalty_score=penalty_score,\\n endpoint=endpoint,\\n )\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to Baidu Qianfan API.\\\") from e\\n return output # type: ignore\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"endpoint\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"endpoint\",\"display_name\":\"Endpoint\",\"advanced\":false,\"dynamic\":false,\"info\":\"Endpoint of the Qianfan LLM, required if custom model used.\",\"type\":\"str\",\"list\":false},\"model\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"ERNIE-Bot-turbo\",\"password\":false,\"options\":[\"ERNIE-Bot\",\"ERNIE-Bot-turbo\",\"BLOOMZ-7B\",\"Llama-2-7b-chat\",\"Llama-2-13b-chat\",\"Llama-2-70b-chat\",\"Qianfan-BLOOMZ-7B-compressed\",\"Qianfan-Chinese-Llama-2-7B\",\"ChatGLM2-6B-32K\",\"AquilaChat-7B\"],\"name\":\"model\",\"display_name\":\"Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint\",\"type\":\"str\",\"list\":true},\"penalty_score\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":1.0,\"password\":false,\"name\":\"penalty_score\",\"display_name\":\"Penalty Score\",\"advanced\":false,\"dynamic\":false,\"info\":\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\",\"type\":\"float\",\"list\":false},\"qianfan_ak\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"qianfan_ak\",\"display_name\":\"Qianfan Ak\",\"advanced\":false,\"dynamic\":false,\"info\":\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\",\"type\":\"str\",\"list\":false},\"qianfan_sk\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"qianfan_sk\",\"display_name\":\"Qianfan Sk\",\"advanced\":false,\"dynamic\":false,\"info\":\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\",\"type\":\"str\",\"list\":false},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":0.95,\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\",\"type\":\"float\",\"list\":false},\"top_p\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":0.8,\"password\":false,\"name\":\"top_p\",\"display_name\":\"Top p\",\"advanced\":false,\"dynamic\":false,\"info\":\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\",\"type\":\"float\",\"list\":false}},\"description\":\"Baidu Qianfan hosted open source or customized models. Get more detail from https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint\",\"base_classes\":[\"BaseLanguageModel\",\"BaseLLM\"],\"display_name\":\"QianfanLLMEndpoint\",\"custom_fields\":{\"endpoint\":null,\"model\":null,\"penalty_score\":null,\"qianfan_ak\":null,\"qianfan_sk\":null,\"temperature\":null,\"top_p\":null},\"output_types\":[\"BaiduQianfanLLMEndpoints\"],\"documentation\":\"\",\"beta\":true,\"error\":null}},\"memories\":{\"ConversationBufferMemory\":{\"template\":{\"chat_memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"chat_memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseChatMessageHistory\",\"list\":false},\"ai_prefix\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"AI\",\"password\":false,\"name\":\"ai_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"human_prefix\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"Human\",\"password\":false,\"name\":\"human_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"input_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"input_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Input when more than one variable is available.\",\"type\":\"str\",\"list\":false},\"memory_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"chat_history\",\"password\":false,\"name\":\"memory_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"output_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"output_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Output (e.g. answer in a ConversationalRetrievalChain)\",\"type\":\"str\",\"list\":false},\"return_messages\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"return_messages\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ConversationBufferMemory\"},\"description\":\"Buffer for storing conversation memory.\",\"base_classes\":[\"BaseMemory\",\"BaseChatMemory\",\"ConversationBufferMemory\"],\"display_name\":\"ConversationBufferMemory\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/memory/how_to/buffer\",\"beta\":false,\"error\":null},\"ConversationBufferWindowMemory\":{\"template\":{\"chat_memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"chat_memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseChatMessageHistory\",\"list\":false},\"ai_prefix\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"AI\",\"password\":false,\"name\":\"ai_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"human_prefix\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"Human\",\"password\":false,\"name\":\"human_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"input_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"input_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Input when more than one variable is available.\",\"type\":\"str\",\"list\":false},\"k\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":10,\"password\":false,\"name\":\"k\",\"display_name\":\"Memory Size\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"memory_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"chat_history\",\"password\":false,\"name\":\"memory_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"output_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"output_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Output (e.g. answer in a ConversationalRetrievalChain)\",\"type\":\"str\",\"list\":false},\"return_messages\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"return_messages\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ConversationBufferWindowMemory\"},\"description\":\"Buffer for storing conversation memory inside a limited size window.\",\"base_classes\":[\"BaseMemory\",\"ConversationBufferWindowMemory\",\"BaseChatMemory\"],\"display_name\":\"ConversationBufferWindowMemory\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/memory/how_to/buffer_window\",\"beta\":false,\"error\":null},\"ConversationEntityMemory\":{\"template\":{\"chat_memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"chat_memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseChatMessageHistory\",\"list\":false},\"entity_extraction_prompt\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"entity_extraction_prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BasePromptTemplate\",\"list\":false},\"entity_store\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"entity_store\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseEntityStore\",\"list\":false},\"entity_summarization_prompt\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"entity_summarization_prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BasePromptTemplate\",\"list\":false},\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"ai_prefix\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"AI\",\"password\":false,\"name\":\"ai_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"chat_history_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"history\",\"password\":false,\"name\":\"chat_history_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"entity_cache\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"entity_cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"human_prefix\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"Human\",\"password\":false,\"name\":\"human_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"input_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"input_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Input when more than one variable is available.\",\"type\":\"str\",\"list\":false},\"k\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":10,\"password\":false,\"name\":\"k\",\"display_name\":\"Memory Size\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"output_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"output_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Output (e.g. answer in a ConversationalRetrievalChain)\",\"type\":\"str\",\"list\":false},\"return_messages\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"return_messages\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ConversationEntityMemory\"},\"description\":\"Entity extractor & summarizer memory.\",\"base_classes\":[\"BaseMemory\",\"ConversationEntityMemory\",\"BaseChatMemory\"],\"display_name\":\"ConversationEntityMemory\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/memory/integrations/entity_memory_with_sqlite\",\"beta\":false,\"error\":null},\"ConversationKGMemory\":{\"template\":{\"chat_memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"chat_memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseChatMessageHistory\",\"list\":false},\"entity_extraction_prompt\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"entity_extraction_prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BasePromptTemplate\",\"list\":false},\"kg\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"kg\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"NetworkxEntityGraph\",\"list\":false},\"knowledge_extraction_prompt\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"knowledge_extraction_prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BasePromptTemplate\",\"list\":false},\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"summary_message_cls\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"summary_message_cls\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Type[langchain.schema.messages.BaseMessage]\",\"list\":false},\"ai_prefix\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"AI\",\"password\":false,\"name\":\"ai_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"human_prefix\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"Human\",\"password\":false,\"name\":\"human_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"input_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"input_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Input when more than one variable is available.\",\"type\":\"str\",\"list\":false},\"k\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":10,\"password\":false,\"name\":\"k\",\"display_name\":\"Memory Size\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"memory_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"chat_history\",\"password\":false,\"name\":\"memory_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"output_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"output_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Output (e.g. answer in a ConversationalRetrievalChain)\",\"type\":\"str\",\"list\":false},\"return_messages\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"return_messages\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ConversationKGMemory\"},\"description\":\"Knowledge graph conversation memory.\",\"base_classes\":[\"ConversationKGMemory\",\"BaseMemory\",\"BaseChatMemory\"],\"display_name\":\"ConversationKGMemory\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/memory/how_to/kg\",\"beta\":false,\"error\":null},\"ConversationSummaryMemory\":{\"template\":{\"chat_memory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"chat_memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseChatMessageHistory\",\"list\":false},\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"prompt\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BasePromptTemplate\",\"list\":false},\"summary_message_cls\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"summary_message_cls\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Type[langchain.schema.messages.BaseMessage]\",\"list\":false},\"ai_prefix\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"AI\",\"password\":false,\"name\":\"ai_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"buffer\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"buffer\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"human_prefix\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"Human\",\"password\":false,\"name\":\"human_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"input_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"input_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Input when more than one variable is available.\",\"type\":\"str\",\"list\":false},\"memory_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"chat_history\",\"password\":false,\"name\":\"memory_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"output_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"output_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Output (e.g. answer in a ConversationalRetrievalChain)\",\"type\":\"str\",\"list\":false},\"return_messages\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"return_messages\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"ConversationSummaryMemory\"},\"description\":\"Conversation summarizer to chat memory.\",\"base_classes\":[\"SummarizerMixin\",\"ConversationSummaryMemory\",\"BaseChatMemory\",\"BaseMemory\"],\"display_name\":\"ConversationSummaryMemory\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/memory/how_to/summary\",\"beta\":false,\"error\":null},\"MongoDBChatMessageHistory\":{\"template\":{\"collection_name\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"message_store\",\"password\":false,\"name\":\"collection_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"connection_string\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"connection_string\",\"advanced\":false,\"dynamic\":false,\"info\":\"MongoDB connection string (e.g mongodb://mongo_user:password123@mongo:27017)\",\"type\":\"str\",\"list\":false},\"database_name\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"chat_history\",\"password\":false,\"name\":\"database_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"session_id\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"session_id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"MongoDBChatMessageHistory\"},\"description\":\"Memory store with MongoDB\",\"base_classes\":[\"MongoDBChatMessageHistory\",\"BaseChatMessageHistory\"],\"display_name\":\"MongoDBChatMessageHistory\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/memory/integrations/mongodb_chat_message_history\",\"beta\":false,\"error\":null},\"MotorheadMemory\":{\"template\":{\"chat_memory\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"chat_memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseChatMessageHistory\",\"list\":false},\"api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"client_id\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"client_id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"context\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"context\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"input_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"input_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Input when more than one variable is available.\",\"type\":\"str\",\"list\":false},\"memory_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"chat_history\",\"password\":false,\"name\":\"memory_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"output_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"output_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Output (e.g. answer in a ConversationalRetrievalChain)\",\"type\":\"str\",\"list\":false},\"return_messages\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"return_messages\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"session_id\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"session_id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"url\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"https://api.getmetal.io/v1/motorhead\",\"password\":false,\"name\":\"url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"MotorheadMemory\"},\"description\":\"Chat message memory backed by Motorhead service.\",\"base_classes\":[\"BaseMemory\",\"BaseChatMemory\",\"MotorheadMemory\"],\"display_name\":\"MotorheadMemory\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/integrations/memory/motorhead_memory\",\"beta\":false,\"error\":null},\"PostgresChatMessageHistory\":{\"template\":{\"connection_string\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"postgresql://postgres:mypassword@localhost/chat_history\",\"password\":false,\"name\":\"connection_string\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"session_id\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"session_id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"table_name\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"message_store\",\"password\":false,\"name\":\"table_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"PostgresChatMessageHistory\"},\"description\":\"Memory store with Postgres\",\"base_classes\":[\"PostgresChatMessageHistory\",\"BaseChatMessageHistory\"],\"display_name\":\"PostgresChatMessageHistory\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/memory/integrations/postgres_chat_message_history\",\"beta\":false,\"error\":null},\"VectorStoreRetrieverMemory\":{\"template\":{\"retriever\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"retriever\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"VectorStoreRetriever\",\"list\":false},\"exclude_input_keys\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"exclude_input_keys\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"input_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"input_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Input when more than one variable is available.\",\"type\":\"str\",\"list\":false},\"memory_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"chat_history\",\"password\":false,\"name\":\"memory_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"return_docs\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"return_docs\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"return_messages\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"return_messages\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"VectorStoreRetrieverMemory\"},\"description\":\"VectorStoreRetriever-backed memory.\",\"base_classes\":[\"BaseMemory\",\"VectorStoreRetrieverMemory\"],\"display_name\":\"VectorStoreRetrieverMemory\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/memory/how_to/vectorstore_retriever_memory\",\"beta\":false,\"error\":null}},\"tools\":{\"Calculator\":{\"template\":{\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"_type\":\"Calculator\"},\"description\":\"Useful for when you need to answer questions about math.\",\"base_classes\":[\"Tool\",\"BaseTool\"],\"display_name\":\"Calculator\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"News API\":{\"template\":{\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"news_api_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":true,\"name\":\"news_api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"News API\"},\"description\":\"Use this when you want to get information about the top headlines of current news stories. The input should be a question in natural language that this API can answer.\",\"base_classes\":[\"Tool\",\"BaseTool\"],\"display_name\":\"News API\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"TMDB API\":{\"template\":{\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"tmdb_bearer_token\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":true,\"name\":\"tmdb_bearer_token\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"TMDB API\"},\"description\":\"Useful for when you want to get information from The Movie Database. The input should be a question in natural language that this API can answer.\",\"base_classes\":[\"Tool\",\"BaseTool\"],\"display_name\":\"TMDB API\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"Podcast API\":{\"template\":{\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"listen_api_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":true,\"name\":\"listen_api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"Podcast API\"},\"description\":\"Use the Listen Notes Podcast API to search all podcasts or episodes. The input should be a question in natural language that this API can answer.\",\"base_classes\":[\"Tool\",\"BaseTool\"],\"display_name\":\"Podcast API\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"Search\":{\"template\":{\"aiosession\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"aiosession\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"serpapi_api_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":true,\"name\":\"serpapi_api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"Search\"},\"description\":\"A search engine. Useful for when you need to answer questions about current events. Input should be a search query.\",\"base_classes\":[\"Tool\",\"BaseTool\"],\"display_name\":\"Search\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"Tool\":{\"template\":{\"func\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"password\":false,\"name\":\"func\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"function\",\"list\":false},\"description\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"description\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"name\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"return_direct\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"return_direct\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"Tool\"},\"description\":\"Converts a chain, agent or function into a tool.\",\"base_classes\":[\"Tool\",\"BaseTool\"],\"display_name\":\"Tool\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"PythonFunctionTool\":{\"template\":{\"code\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\\ndef python_function(text: str) -> str:\\n \\\"\\\"\\\"This is a default python function that returns the input text\\\"\\\"\\\"\\n return text\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"code\",\"list\":false},\"description\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\",\"password\":false,\"name\":\"description\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"name\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"return_direct\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"return_direct\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"PythonFunctionTool\"},\"description\":\"Python function to be executed.\",\"base_classes\":[\"BaseTool\",\"Tool\"],\"display_name\":\"PythonFunctionTool\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"PythonFunction\":{\"template\":{\"code\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"\\ndef python_function(text: str) -> str:\\n \\\"\\\"\\\"This is a default python function that returns the input text\\\"\\\"\\\"\\n return text\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"code\",\"list\":false},\"_type\":\"PythonFunction\"},\"description\":\"Python function to be executed.\",\"base_classes\":[\"function\"],\"display_name\":\"PythonFunction\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"JsonSpec\":{\"template\":{\"path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"suffixes\":[\".json\",\".yaml\",\".yml\"],\"password\":false,\"name\":\"path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\"json\",\"yaml\",\"yml\"],\"file_path\":null},\"max_value_length\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"max_value_length\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"_type\":\"JsonSpec\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"JsonSpec\"],\"display_name\":\"JsonSpec\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"BingSearchRun\":{\"template\":{\"api_wrapper\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"api_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BingSearchAPIWrapper\",\"list\":false},\"args_schema\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Type[pydantic.main.BaseModel]\",\"list\":false},\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":false},\"handle_tool_error\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"BingSearchRun\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"BingSearchRun\",\"BaseTool\"],\"display_name\":\"BingSearchRun\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"GoogleSearchResults\":{\"template\":{\"api_wrapper\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"api_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"GoogleSearchAPIWrapper\",\"list\":false},\"args_schema\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Type[pydantic.main.BaseModel]\",\"list\":false},\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":false},\"handle_tool_error\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"num_results\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":4,\"password\":false,\"name\":\"num_results\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"GoogleSearchResults\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"GoogleSearchResults\",\"BaseTool\"],\"display_name\":\"GoogleSearchResults\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"GoogleSearchRun\":{\"template\":{\"api_wrapper\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"api_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"GoogleSearchAPIWrapper\",\"list\":false},\"args_schema\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Type[pydantic.main.BaseModel]\",\"list\":false},\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":false},\"handle_tool_error\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"GoogleSearchRun\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"GoogleSearchRun\",\"BaseTool\"],\"display_name\":\"GoogleSearchRun\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"GoogleSerperRun\":{\"template\":{\"api_wrapper\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"api_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"GoogleSerperAPIWrapper\",\"list\":false},\"args_schema\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Type[pydantic.main.BaseModel]\",\"list\":false},\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":false},\"handle_tool_error\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"GoogleSerperRun\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"GoogleSerperRun\",\"BaseTool\"],\"display_name\":\"GoogleSerperRun\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"InfoSQLDatabaseTool\":{\"template\":{\"args_schema\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Type[pydantic.main.BaseModel]\",\"list\":false},\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":false},\"db\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"db\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"SQLDatabase\",\"list\":false},\"handle_tool_error\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"InfoSQLDatabaseTool\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"BaseSQLDatabaseTool\",\"InfoSQLDatabaseTool\",\"BaseTool\"],\"display_name\":\"InfoSQLDatabaseTool\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"JsonGetValueTool\":{\"template\":{\"args_schema\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Type[pydantic.main.BaseModel]\",\"list\":false},\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":false},\"spec\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"spec\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"JsonSpec\",\"list\":false},\"handle_tool_error\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"JsonGetValueTool\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"JsonGetValueTool\",\"BaseTool\"],\"display_name\":\"JsonGetValueTool\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"JsonListKeysTool\":{\"template\":{\"args_schema\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Type[pydantic.main.BaseModel]\",\"list\":false},\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":false},\"spec\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"spec\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"JsonSpec\",\"list\":false},\"handle_tool_error\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"JsonListKeysTool\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"JsonListKeysTool\",\"BaseTool\"],\"display_name\":\"JsonListKeysTool\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"ListSQLDatabaseTool\":{\"template\":{\"args_schema\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Type[pydantic.main.BaseModel]\",\"list\":false},\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":false},\"db\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"db\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"SQLDatabase\",\"list\":false},\"handle_tool_error\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"ListSQLDatabaseTool\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"BaseSQLDatabaseTool\",\"BaseTool\",\"ListSQLDatabaseTool\"],\"display_name\":\"ListSQLDatabaseTool\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"PythonAstREPLTool\":{\"template\":{\"args_schema\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Type[pydantic.main.BaseModel]\",\"list\":false},\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":false},\"globals\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"globals\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"handle_tool_error\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"locals\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"locals\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"sanitize_input\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":true,\"password\":false,\"name\":\"sanitize_input\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"PythonAstREPLTool\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"PythonAstREPLTool\",\"BaseTool\"],\"display_name\":\"PythonAstREPLTool\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"PythonREPLTool\":{\"template\":{\"args_schema\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Type[pydantic.main.BaseModel]\",\"list\":false},\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":false},\"python_repl\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"python_repl\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"PythonREPL\",\"list\":false},\"handle_tool_error\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"sanitize_input\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":true,\"password\":false,\"name\":\"sanitize_input\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"PythonREPLTool\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"PythonREPLTool\",\"BaseTool\"],\"display_name\":\"PythonREPLTool\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"QuerySQLDataBaseTool\":{\"template\":{\"args_schema\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Type[pydantic.main.BaseModel]\",\"list\":false},\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":false},\"db\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"db\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"SQLDatabase\",\"list\":false},\"handle_tool_error\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"QuerySQLDataBaseTool\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"BaseSQLDatabaseTool\",\"QuerySQLDataBaseTool\",\"BaseTool\"],\"display_name\":\"QuerySQLDataBaseTool\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"RequestsDeleteTool\":{\"template\":{\"args_schema\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Type[pydantic.main.BaseModel]\",\"list\":false},\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":false},\"requests_wrapper\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"requests_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"TextRequestsWrapper\",\"list\":false},\"handle_tool_error\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"RequestsDeleteTool\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"RequestsDeleteTool\",\"BaseRequestsTool\",\"BaseTool\"],\"display_name\":\"RequestsDeleteTool\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"RequestsGetTool\":{\"template\":{\"args_schema\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Type[pydantic.main.BaseModel]\",\"list\":false},\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":false},\"requests_wrapper\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"requests_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"TextRequestsWrapper\",\"list\":false},\"handle_tool_error\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"RequestsGetTool\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"RequestsGetTool\",\"BaseRequestsTool\",\"BaseTool\"],\"display_name\":\"RequestsGetTool\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"RequestsPatchTool\":{\"template\":{\"args_schema\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Type[pydantic.main.BaseModel]\",\"list\":false},\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":false},\"requests_wrapper\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"requests_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"TextRequestsWrapper\",\"list\":false},\"handle_tool_error\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"RequestsPatchTool\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"BaseRequestsTool\",\"BaseTool\",\"RequestsPatchTool\"],\"display_name\":\"RequestsPatchTool\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"RequestsPostTool\":{\"template\":{\"args_schema\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Type[pydantic.main.BaseModel]\",\"list\":false},\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":false},\"requests_wrapper\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"requests_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"TextRequestsWrapper\",\"list\":false},\"handle_tool_error\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"RequestsPostTool\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"RequestsPostTool\",\"BaseRequestsTool\",\"BaseTool\"],\"display_name\":\"RequestsPostTool\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"RequestsPutTool\":{\"template\":{\"args_schema\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Type[pydantic.main.BaseModel]\",\"list\":false},\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":false},\"requests_wrapper\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"requests_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"TextRequestsWrapper\",\"list\":false},\"handle_tool_error\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"RequestsPutTool\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"BaseRequestsTool\",\"BaseTool\",\"RequestsPutTool\"],\"display_name\":\"RequestsPutTool\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"WikipediaQueryRun\":{\"template\":{\"api_wrapper\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"api_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"WikipediaAPIWrapper\",\"list\":false},\"args_schema\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Type[pydantic.main.BaseModel]\",\"list\":false},\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":false},\"handle_tool_error\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"WikipediaQueryRun\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"WikipediaQueryRun\",\"BaseTool\"],\"display_name\":\"WikipediaQueryRun\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"WolframAlphaQueryRun\":{\"template\":{\"api_wrapper\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"api_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"WolframAlphaAPIWrapper\",\"list\":false},\"args_schema\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Type[pydantic.main.BaseModel]\",\"list\":false},\"callbacks\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"langchain.callbacks.base.BaseCallbackHandler\",\"list\":false},\"handle_tool_error\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"tags\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"WolframAlphaQueryRun\"},\"description\":\"\",\"base_classes\":[\"Tool\",\"BaseTool\",\"WolframAlphaQueryRun\",\"BaseTool\"],\"display_name\":\"WolframAlphaQueryRun\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null}},\"toolkits\":{\"JsonToolkit\":{\"template\":{\"spec\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"spec\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"JsonSpec\",\"list\":false},\"_type\":\"JsonToolkit\"},\"description\":\"Toolkit for interacting with a JSON spec.\",\"base_classes\":[\"BaseToolkit\",\"JsonToolkit\",\"Tool\"],\"display_name\":\"JsonToolkit\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"OpenAPIToolkit\":{\"template\":{\"json_agent\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"json_agent\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"AgentExecutor\",\"list\":false},\"requests_wrapper\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"requests_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"TextRequestsWrapper\",\"list\":false},\"_type\":\"OpenAPIToolkit\"},\"description\":\"Toolkit for interacting with an OpenAPI API.\",\"base_classes\":[\"BaseToolkit\",\"OpenAPIToolkit\",\"Tool\"],\"display_name\":\"OpenAPIToolkit\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"VectorStoreInfo\":{\"template\":{\"vectorstore\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"vectorstore\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"VectorStore\",\"list\":false},\"description\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"password\":false,\"name\":\"description\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"name\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"VectorStoreInfo\"},\"description\":\"Information about a VectorStore.\",\"base_classes\":[\"VectorStoreInfo\"],\"display_name\":\"VectorStoreInfo\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"VectorStoreRouterToolkit\":{\"template\":{\"llm\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"vectorstores\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"vectorstores\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"VectorStoreInfo\",\"list\":true},\"_type\":\"VectorStoreRouterToolkit\"},\"description\":\"Toolkit for routing between Vector Stores.\",\"base_classes\":[\"BaseToolkit\",\"VectorStoreRouterToolkit\",\"Tool\"],\"display_name\":\"VectorStoreRouterToolkit\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"VectorStoreToolkit\":{\"template\":{\"llm\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLanguageModel\",\"list\":false},\"vectorstore_info\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"vectorstore_info\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"VectorStoreInfo\",\"list\":false},\"_type\":\"VectorStoreToolkit\"},\"description\":\"Toolkit for interacting with a Vector Store.\",\"base_classes\":[\"BaseToolkit\",\"VectorStoreToolkit\",\"Tool\"],\"display_name\":\"VectorStoreToolkit\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"Metaphor\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from typing import List, Union\\nfrom langflow import CustomComponent\\n\\nfrom metaphor_python import Metaphor # type: ignore\\nfrom langchain.tools import Tool\\nfrom langchain.agents import tool\\nfrom langchain.agents.agent_toolkits.base import BaseToolkit\\n\\n\\nclass MetaphorToolkit(CustomComponent):\\n display_name: str = \\\"Metaphor\\\"\\n description: str = \\\"Metaphor Toolkit\\\"\\n documentation = (\\n \\\"https://python.langchain.com/docs/integrations/tools/metaphor_search\\\"\\n )\\n beta = True\\n # api key should be password = True\\n field_config = {\\n \\\"metaphor_api_key\\\": {\\\"display_name\\\": \\\"Metaphor API Key\\\", \\\"password\\\": True},\\n \\\"code\\\": {\\\"advanced\\\": True},\\n }\\n\\n def build(\\n self,\\n metaphor_api_key: str,\\n use_autoprompt: bool = True,\\n search_num_results: int = 5,\\n similar_num_results: int = 5,\\n ) -> Union[Tool, BaseToolkit]:\\n # If documents, then we need to create a Vectara instance using .from_documents\\n client = Metaphor(api_key=metaphor_api_key)\\n\\n @tool\\n def search(query: str):\\n \\\"\\\"\\\"Call search engine with a query.\\\"\\\"\\\"\\n return client.search(\\n query, use_autoprompt=use_autoprompt, num_results=search_num_results\\n )\\n\\n @tool\\n def get_contents(ids: List[str]):\\n \\\"\\\"\\\"Get contents of a webpage.\\n\\n The ids passed in should be a list of ids as fetched from `search`.\\n \\\"\\\"\\\"\\n return client.get_contents(ids)\\n\\n @tool\\n def find_similar(url: str):\\n \\\"\\\"\\\"Get search results similar to a given URL.\\n\\n The url passed in should be a URL returned from `search`\\n \\\"\\\"\\\"\\n return client.find_similar(url, num_results=similar_num_results)\\n\\n return [search, get_contents, find_similar] # type: ignore\\n\",\"password\":false,\"name\":\"code\",\"advanced\":true,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"metaphor_api_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"metaphor_api_key\",\"display_name\":\"Metaphor API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"search_num_results\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":5,\"password\":false,\"name\":\"search_num_results\",\"display_name\":\"search_num_results\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"similar_num_results\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":5,\"password\":false,\"name\":\"similar_num_results\",\"display_name\":\"similar_num_results\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"use_autoprompt\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":true,\"password\":false,\"name\":\"use_autoprompt\",\"display_name\":\"use_autoprompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false}},\"description\":\"Metaphor Toolkit\",\"base_classes\":[\"Tool\",\"BaseTool\"],\"display_name\":\"Metaphor\",\"custom_fields\":{\"metaphor_api_key\":null,\"search_num_results\":null,\"similar_num_results\":null,\"use_autoprompt\":null},\"output_types\":[\"Metaphor\"],\"documentation\":\"https://python.langchain.com/docs/integrations/tools/metaphor_search\",\"beta\":true,\"error\":null}},\"wrappers\":{\"TextRequestsWrapper\":{\"template\":{\"aiosession\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"aiosession\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"ClientSession\",\"list\":false},\"auth\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"auth\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"headers\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"{\\\"Authorization\\\": \\\"Bearer \\\"}\",\"password\":false,\"name\":\"headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"TextRequestsWrapper\"},\"description\":\"Lightweight wrapper around requests library.\",\"base_classes\":[\"TextRequestsWrapper\"],\"display_name\":\"TextRequestsWrapper\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"SQLDatabase\":{\"template\":{\"database_uri\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"database_uri\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"engine_args\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"engine_args\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"SQLDatabase\"},\"description\":\"Construct a SQLAlchemy engine from URI.\",\"base_classes\":[\"SQLDatabase\",\"function\"],\"display_name\":\"SQLDatabase\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null}},\"embeddings\":{\"OpenAIEmbeddings\":{\"template\":{\"allowed_special\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":[],\"password\":false,\"name\":\"allowed_special\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Literal'all'\",\"list\":true},\"disallowed_special\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"all\",\"password\":false,\"name\":\"disallowed_special\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Literal'all'\",\"list\":true},\"chunk_size\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":1000,\"password\":false,\"name\":\"chunk_size\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"deployment\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"text-embedding-ada-002\",\"password\":false,\"name\":\"deployment\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"embedding_ctx_length\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":8191,\"password\":false,\"name\":\"embedding_ctx_length\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"headers\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"{\\\"Authorization\\\": \\\"Bearer \\\"}\",\"password\":false,\"name\":\"headers\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":6,\"password\":false,\"name\":\"max_retries\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"model\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"text-embedding-ada-002\",\"password\":false,\"name\":\"model\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"openai_api_base\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_api_type\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"openai_api_type\",\"display_name\":\"OpenAI API Type\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_api_version\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"openai_api_version\",\"display_name\":\"OpenAI API Version\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_organization\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"openai_proxy\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"request_timeout\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"show_progress_bar\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"show_progress_bar\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"skip_empty\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"skip_empty\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"tiktoken_model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"tiktoken_model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"OpenAIEmbeddings\"},\"description\":\"OpenAI embedding models.\",\"base_classes\":[\"OpenAIEmbeddings\",\"Embeddings\"],\"display_name\":\"OpenAIEmbeddings\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/openai\",\"beta\":false,\"error\":null},\"CohereEmbeddings\":{\"template\":{\"async_client\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"async_client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"cohere_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"cohere_api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"model\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"embed-english-v2.0\",\"password\":false,\"name\":\"model\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"truncate\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"truncate\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"CohereEmbeddings\"},\"description\":\"Cohere embedding models.\",\"base_classes\":[\"CohereEmbeddings\",\"Embeddings\"],\"display_name\":\"CohereEmbeddings\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/cohere\",\"beta\":false,\"error\":null},\"HuggingFaceEmbeddings\":{\"template\":{\"cache_folder\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"cache_folder\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"encode_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"encode_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"model_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"sentence-transformers/all-mpnet-base-v2\",\"password\":false,\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"multi_process\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"multi_process\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"HuggingFaceEmbeddings\"},\"description\":\"HuggingFace sentence_transformers embedding models.\",\"base_classes\":[\"HuggingFaceEmbeddings\",\"Embeddings\"],\"display_name\":\"HuggingFaceEmbeddings\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/sentence_transformers\",\"beta\":false,\"error\":null},\"VertexAIEmbeddings\":{\"template\":{\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"ForwardRef(\\\"'_LanguageModel'\\\")\",\"list\":false},\"credentials\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"suffixes\":[\".json\"],\"password\":false,\"name\":\"credentials\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\"json\"],\"file_path\":null},\"location\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"us-central1\",\"password\":false,\"name\":\"location\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"max_output_tokens\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":128,\"password\":true,\"name\":\"max_output_tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"max_retries\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":6,\"password\":false,\"name\":\"max_retries\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"model_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"textembedding-gecko\",\"password\":false,\"name\":\"model_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"project\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"project\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"request_parallelism\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":5,\"password\":false,\"name\":\"request_parallelism\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"stop\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"stop\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"streaming\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"streaming\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"temperature\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":0.0,\"password\":false,\"name\":\"temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"top_k\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":40,\"password\":false,\"name\":\"top_k\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"top_p\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":0.95,\"password\":false,\"name\":\"top_p\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"_type\":\"VertexAIEmbeddings\"},\"description\":\"Google Cloud VertexAI embedding models.\",\"base_classes\":[\"_VertexAICommon\",\"VertexAIEmbeddings\",\"Embeddings\",\"_VertexAIBase\"],\"display_name\":\"VertexAIEmbeddings\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/google_vertex_ai_palm\",\"beta\":false,\"error\":null}},\"vectorstores\":{\"Chroma\":{\"template\":{\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"chromadb.Client\",\"list\":false},\"client_settings\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client_settings\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"chromadb.config.Setting\",\"list\":true},\"documents\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Document\",\"list\":true},\"embedding\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Embeddings\",\"list\":false},\"chroma_server_cors_allow_origins\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"chroma_server_cors_allow_origins\",\"display_name\":\"Chroma Server CORS Allow Origins\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"chroma_server_grpc_port\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"chroma_server_grpc_port\",\"display_name\":\"Chroma Server GRPC Port\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"chroma_server_host\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"chroma_server_host\",\"display_name\":\"Chroma Server Host\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"chroma_server_http_port\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"chroma_server_http_port\",\"display_name\":\"Chroma Server HTTP Port\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"chroma_server_ssl_enabled\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"chroma_server_ssl_enabled\",\"display_name\":\"Chroma Server SSL Enabled\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"collection_metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"collection_metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"collection_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"langchain\",\"password\":false,\"name\":\"collection_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"ids\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"ids\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"metadatas\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadatas\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":true},\"persist\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"persist\",\"display_name\":\"Persist\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"persist_directory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"persist_directory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"search_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"{}\",\"password\":false,\"name\":\"search_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"NestedDict\",\"list\":false},\"_type\":\"Chroma\"},\"description\":\"Create a Chroma vectorstore from a raw documents.\",\"base_classes\":[\"VectorStore\",\"Chroma\",\"BaseRetriever\",\"VectorStoreRetriever\"],\"display_name\":\"Chroma\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/chroma\",\"beta\":false,\"error\":null},\"FAISS\":{\"template\":{\"documents\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Document\",\"list\":true},\"embedding\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Embeddings\",\"list\":false},\"folder_path\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"folder_path\",\"display_name\":\"Local Path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"ids\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"ids\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"index_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"index_name\",\"display_name\":\"Index Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"metadatas\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadatas\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":true},\"search_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"{}\",\"password\":false,\"name\":\"search_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"NestedDict\",\"list\":false},\"_type\":\"FAISS\"},\"description\":\"Construct FAISS wrapper from raw documents.\",\"base_classes\":[\"FAISS\",\"VectorStore\",\"BaseRetriever\",\"VectorStoreRetriever\"],\"display_name\":\"FAISS\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/faiss\",\"beta\":false,\"error\":null},\"MongoDBAtlasVectorSearch\":{\"template\":{\"collection\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"collection\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Collection[MongoDBDocumentType]\",\"list\":false},\"documents\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Document\",\"list\":true},\"embedding\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Embeddings\",\"list\":false},\"collection_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"collection_name\",\"display_name\":\"Collection Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"db_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"db_name\",\"display_name\":\"Database Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"index_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"index_name\",\"display_name\":\"Index Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"metadatas\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadatas\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":true},\"mongodb_atlas_cluster_uri\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"mongodb_atlas_cluster_uri\",\"display_name\":\"MongoDB Atlas Cluster URI\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"search_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"{}\",\"password\":false,\"name\":\"search_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"NestedDict\",\"list\":false},\"_type\":\"MongoDBAtlasVectorSearch\"},\"description\":\"Construct a `MongoDB Atlas Vector Search` vector store from raw documents.\",\"base_classes\":[\"MongoDBAtlasVectorSearch\",\"VectorStore\",\"BaseRetriever\",\"VectorStoreRetriever\"],\"display_name\":\"MongoDB Atlas\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/mongodb_atlas\",\"beta\":false,\"error\":null},\"Pinecone\":{\"template\":{\"documents\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Document\",\"list\":true},\"embedding\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":1000,\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Embeddings\",\"list\":false},\"batch_size\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":32,\"password\":false,\"name\":\"batch_size\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"ids\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"ids\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"index_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"index_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"metadatas\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadatas\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":true},\"namespace\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"namespace\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"pinecone_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"pinecone_api_key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"pinecone_env\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"pinecone_env\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"pool_threads\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":4,\"password\":false,\"name\":\"pool_threads\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"search_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"{}\",\"password\":false,\"name\":\"search_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"NestedDict\",\"list\":false},\"text_key\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"text\",\"password\":true,\"name\":\"text_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"upsert_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"upsert_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"Pinecone\"},\"description\":\"Construct Pinecone wrapper from raw documents.\",\"base_classes\":[\"Pinecone\",\"VectorStore\",\"BaseRetriever\",\"VectorStoreRetriever\"],\"display_name\":\"Pinecone\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/pinecone\",\"beta\":false,\"error\":null},\"Qdrant\":{\"template\":{\"documents\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Document\",\"list\":true},\"embedding\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Embeddings\",\"list\":false},\"hnsw_config\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"hnsw_config\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"common_types.HnswConfigDiff\",\"list\":false},\"init_from\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"init_from\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"common_types.InitFrom\",\"list\":false},\"optimizers_config\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"optimizers_config\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"common_types.OptimizersConfigDiff\",\"list\":false},\"quantization_config\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"quantization_config\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"common_types.QuantizationConfig\",\"list\":false},\"wal_config\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"wal_config\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"common_types.WalConfigDiff\",\"list\":false},\"api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"api_key\",\"display_name\":\"API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"batch_size\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":64,\"password\":false,\"name\":\"batch_size\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"collection_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"collection_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"content_payload_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"page_content\",\"password\":false,\"name\":\"content_payload_key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"distance_func\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"Cosine\",\"password\":false,\"name\":\"distance_func\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"force_recreate\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"force_recreate\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"grpc_port\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":6334,\"password\":false,\"name\":\"grpc_port\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"host\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"host\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"https\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"https\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"ids\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"ids\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"location\":{\"required\":false,\"placeholder\":\":memory:\",\"show\":true,\"multiline\":false,\"value\":\":memory:\",\"password\":false,\"name\":\"location\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"metadata_payload_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"metadata\",\"password\":false,\"name\":\"metadata_payload_key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"metadatas\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadatas\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":true},\"on_disk\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"on_disk\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"on_disk_payload\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"on_disk_payload\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"path\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"path\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"port\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":6333,\"password\":false,\"name\":\"port\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"prefer_grpc\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"prefer_grpc\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"prefix\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"password\":false,\"name\":\"prefix\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"replication_factor\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"replication_factor\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"search_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"{}\",\"password\":false,\"name\":\"search_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"NestedDict\",\"list\":false},\"shard_number\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"shard_number\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"timeout\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"timeout\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"float\",\"list\":false},\"url\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"url\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"vector_name\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"vector_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"write_consistency_factor\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"write_consistency_factor\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"_type\":\"Qdrant\"},\"description\":\"Construct Qdrant wrapper from a list of texts.\",\"base_classes\":[\"VectorStore\",\"Qdrant\",\"BaseRetriever\",\"VectorStoreRetriever\"],\"display_name\":\"Qdrant\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/qdrant\",\"beta\":false,\"error\":null},\"SupabaseVectorStore\":{\"template\":{\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"supabase.client.Client\",\"list\":false},\"documents\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Document\",\"list\":true},\"embedding\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Embeddings\",\"list\":false},\"ids\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"ids\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"metadatas\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadatas\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":true},\"query_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"query_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"search_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"{}\",\"password\":false,\"name\":\"search_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"NestedDict\",\"list\":false},\"supabase_service_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":true,\"name\":\"supabase_service_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"supabase_url\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"supabase_url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"table_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"table_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"SupabaseVectorStore\"},\"description\":\"Return VectorStore initialized from texts and embeddings.\",\"base_classes\":[\"SupabaseVectorStore\",\"VectorStore\",\"BaseRetriever\",\"VectorStoreRetriever\"],\"display_name\":\"Supabase\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/supabase\",\"beta\":false,\"error\":null},\"Weaviate\":{\"template\":{\"client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"weaviate.Client\",\"list\":false},\"documents\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Document\",\"list\":true},\"embedding\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Embeddings\",\"list\":false},\"relevance_score_fn\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"relevance_score_fn\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Callable[[float], float]\",\"list\":false},\"batch_size\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"batch_size\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"by_text\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"by_text\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"client_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"{}\",\"password\":false,\"name\":\"client_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"code\",\"list\":false},\"index_name\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"index_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"metadatas\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"metadatas\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":true},\"search_kwargs\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"{}\",\"password\":false,\"name\":\"search_kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"NestedDict\",\"list\":false},\"text_key\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"text\",\"password\":true,\"name\":\"text_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"weaviate_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"weaviate_api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"weaviate_url\":{\"required\":true,\"placeholder\":\"http://localhost:8080\",\"show\":true,\"multiline\":false,\"value\":\"http://localhost:8080\",\"password\":false,\"name\":\"weaviate_url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"Weaviate\"},\"description\":\"Construct Weaviate wrapper from raw documents.\",\"base_classes\":[\"Weaviate\",\"VectorStore\",\"BaseRetriever\",\"VectorStoreRetriever\"],\"display_name\":\"Weaviate\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/weaviate\",\"beta\":false,\"error\":null},\"Vectara\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Optional, Union\\nfrom langflow import CustomComponent\\n\\nfrom langchain.vectorstores import Vectara\\nfrom langchain.schema import Document\\nfrom langchain.vectorstores.base import VectorStore\\nfrom langchain.schema import BaseRetriever\\n\\n\\nclass VectaraComponent(CustomComponent):\\n display_name: str = \\\"Vectara\\\"\\n description: str = \\\"Implementation of Vector Store using Vectara\\\"\\n documentation = (\\n \\\"https://python.langchain.com/docs/integrations/vectorstores/vectara\\\"\\n )\\n beta = True\\n # api key should be password = True\\n field_config = {\\n \\\"vectara_customer_id\\\": {\\\"display_name\\\": \\\"Vectara Customer ID\\\"},\\n \\\"vectara_corpus_id\\\": {\\\"display_name\\\": \\\"Vectara Corpus ID\\\"},\\n \\\"vectara_api_key\\\": {\\\"display_name\\\": \\\"Vectara API Key\\\", \\\"password\\\": True},\\n \\\"code\\\": {\\\"show\\\": False},\\n \\\"documents\\\": {\\\"display_name\\\": \\\"Documents\\\"},\\n }\\n\\n def build(\\n self,\\n vectara_customer_id: str,\\n vectara_corpus_id: str,\\n vectara_api_key: str,\\n documents: Optional[Document] = None,\\n ) -> Union[VectorStore, BaseRetriever]:\\n # If documents, then we need to create a Vectara instance using .from_documents\\n if documents is not None:\\n return Vectara.from_documents(\\n documents=documents, # type: ignore\\n vectara_customer_id=vectara_customer_id,\\n vectara_corpus_id=vectara_corpus_id,\\n vectara_api_key=vectara_api_key,\\n source=\\\"langflow\\\",\\n )\\n\\n return Vectara(\\n vectara_customer_id=vectara_customer_id,\\n vectara_corpus_id=vectara_corpus_id,\\n vectara_api_key=vectara_api_key,\\n source=\\\"langflow\\\",\\n )\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"documents\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Document\",\"list\":false},\"vectara_api_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"vectara_api_key\",\"display_name\":\"Vectara API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"vectara_corpus_id\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"vectara_corpus_id\",\"display_name\":\"Vectara Corpus ID\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"vectara_customer_id\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"vectara_customer_id\",\"display_name\":\"Vectara Customer ID\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"Implementation of Vector Store using Vectara\",\"base_classes\":[\"VectorStore\",\"BaseRetriever\"],\"display_name\":\"Vectara\",\"custom_fields\":{\"documents\":null,\"vectara_api_key\":null,\"vectara_corpus_id\":null,\"vectara_customer_id\":null},\"output_types\":[\"Vectara\"],\"documentation\":\"https://python.langchain.com/docs/integrations/vectorstores/vectara\",\"beta\":true,\"error\":null},\"Chroma (1)\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Optional, Union\\nfrom langflow import CustomComponent\\n\\nfrom langchain.vectorstores import Chroma\\nfrom langchain.schema import Document\\nfrom langchain.vectorstores.base import VectorStore\\nfrom langchain.schema import BaseRetriever\\nfrom langchain.embeddings.base import Embeddings\\nimport chromadb # type: ignore\\n\\n\\nclass ChromaComponent(CustomComponent):\\n \\\"\\\"\\\"\\n A custom component for implementing a Vector Store using Chroma.\\n \\\"\\\"\\\"\\n\\n display_name: str = \\\"Chroma (Custom Component)\\\"\\n description: str = \\\"Implementation of Vector Store using Chroma\\\"\\n documentation = \\\"https://python.langchain.com/docs/integrations/vectorstores/chroma\\\"\\n beta = True\\n\\n def build_config(self):\\n \\\"\\\"\\\"\\n Builds the configuration for the component.\\n\\n Returns:\\n - dict: A dictionary containing the configuration options for the component.\\n \\\"\\\"\\\"\\n return {\\n \\\"collection_name\\\": {\\\"display_name\\\": \\\"Collection Name\\\", \\\"value\\\": \\\"langflow\\\"},\\n \\\"persist\\\": {\\\"display_name\\\": \\\"Persist\\\"},\\n \\\"persist_directory\\\": {\\\"display_name\\\": \\\"Persist Directory\\\"},\\n \\\"code\\\": {\\\"show\\\": False, \\\"display_name\\\": \\\"Code\\\"},\\n \\\"documents\\\": {\\\"display_name\\\": \\\"Documents\\\", \\\"is_list\\\": True},\\n \\\"embedding\\\": {\\\"display_name\\\": \\\"Embedding\\\"},\\n \\\"chroma_server_cors_allow_origins\\\": {\\n \\\"display_name\\\": \\\"Server CORS Allow Origins\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"chroma_server_host\\\": {\\\"display_name\\\": \\\"Server Host\\\", \\\"advanced\\\": True},\\n \\\"chroma_server_port\\\": {\\\"display_name\\\": \\\"Server Port\\\", \\\"advanced\\\": True},\\n \\\"chroma_server_grpc_port\\\": {\\n \\\"display_name\\\": \\\"Server gRPC Port\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"chroma_server_ssl_enabled\\\": {\\n \\\"display_name\\\": \\\"Server SSL Enabled\\\",\\n \\\"advanced\\\": True,\\n },\\n }\\n\\n def build(\\n self,\\n collection_name: str,\\n persist: bool,\\n chroma_server_ssl_enabled: bool,\\n persist_directory: Optional[str] = None,\\n embedding: Optional[Embeddings] = None,\\n documents: Optional[Document] = None,\\n chroma_server_cors_allow_origins: Optional[str] = None,\\n chroma_server_host: Optional[str] = None,\\n chroma_server_port: Optional[int] = None,\\n chroma_server_grpc_port: Optional[int] = None,\\n ) -> Union[VectorStore, BaseRetriever]:\\n \\\"\\\"\\\"\\n Builds the Vector Store or BaseRetriever object.\\n\\n Args:\\n - collection_name (str): The name of the collection.\\n - persist_directory (Optional[str]): The directory to persist the Vector Store to.\\n - chroma_server_ssl_enabled (bool): Whether to enable SSL for the Chroma server.\\n - persist (bool): Whether to persist the Vector Store or not.\\n - embedding (Optional[Embeddings]): The embeddings to use for the Vector Store.\\n - documents (Optional[Document]): The documents to use for the Vector Store.\\n - chroma_server_cors_allow_origins (Optional[str]): The CORS allow origins for the Chroma server.\\n - chroma_server_host (Optional[str]): The host for the Chroma server.\\n - chroma_server_port (Optional[int]): The port for the Chroma server.\\n - chroma_server_grpc_port (Optional[int]): The gRPC port for the Chroma server.\\n\\n Returns:\\n - Union[VectorStore, BaseRetriever]: The Vector Store or BaseRetriever object.\\n \\\"\\\"\\\"\\n\\n # Chroma settings\\n chroma_settings = None\\n\\n if chroma_server_host is not None:\\n chroma_settings = chromadb.config.Settings(\\n chroma_server_cors_allow_origins=chroma_server_cors_allow_origins\\n or None,\\n chroma_server_host=chroma_server_host,\\n chroma_server_port=chroma_server_port or None,\\n chroma_server_grpc_port=chroma_server_grpc_port or None,\\n chroma_server_ssl_enabled=chroma_server_ssl_enabled,\\n )\\n\\n # If documents, then we need to create a Chroma instance using .from_documents\\n if documents is not None and embedding is not None:\\n return Chroma.from_documents(\\n documents=documents, # type: ignore\\n persist_directory=persist_directory if persist else None,\\n collection_name=collection_name,\\n embedding=embedding,\\n client_settings=chroma_settings,\\n )\\n\\n return Chroma(\\n persist_directory=persist_directory, client_settings=chroma_settings\\n )\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"chroma_server_cors_allow_origins\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"chroma_server_cors_allow_origins\",\"display_name\":\"Server CORS Allow Origins\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"chroma_server_grpc_port\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"chroma_server_grpc_port\",\"display_name\":\"Server gRPC Port\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"chroma_server_host\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"chroma_server_host\",\"display_name\":\"Server Host\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"chroma_server_port\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"chroma_server_port\",\"display_name\":\"Server Port\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"chroma_server_ssl_enabled\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"chroma_server_ssl_enabled\",\"display_name\":\"Server SSL Enabled\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"collection_name\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"langflow\",\"password\":false,\"name\":\"collection_name\",\"display_name\":\"Collection Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"documents\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Document\",\"list\":true},\"embedding\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Embeddings\",\"list\":false},\"persist\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"persist\",\"display_name\":\"Persist\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"persist_directory\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"persist_directory\",\"display_name\":\"Persist Directory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"Implementation of Vector Store using Chroma\",\"base_classes\":[\"VectorStore\",\"BaseRetriever\"],\"display_name\":\"Chroma (Custom Component)\",\"custom_fields\":{\"chroma_server_cors_allow_origins\":null,\"chroma_server_grpc_port\":null,\"chroma_server_host\":null,\"chroma_server_port\":null,\"chroma_server_ssl_enabled\":null,\"collection_name\":null,\"documents\":null,\"embedding\":null,\"persist\":null,\"persist_directory\":null},\"output_types\":[\"Chroma\"],\"documentation\":\"https://python.langchain.com/docs/integrations/vectorstores/chroma\",\"beta\":true,\"error\":null}},\"documentloaders\":{\"AZLyricsLoader\":{\"template\":{\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"web_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"web_path\",\"display_name\":\"Web Page\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"AZLyricsLoader\"},\"description\":\"Load `AZLyrics` webpages.\",\"base_classes\":[\"Document\"],\"display_name\":\"AZLyricsLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/azlyrics\",\"beta\":false,\"error\":null},\"AirbyteJSONLoader\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"suffixes\":[\".json\"],\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\"json\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"AirbyteJSONLoader\"},\"description\":\"Load local `Airbyte` json files.\",\"base_classes\":[\"Document\"],\"display_name\":\"AirbyteJSONLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/airbyte_json\",\"beta\":false,\"error\":null},\"BSHTMLLoader\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"suffixes\":[\".html\"],\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\"html\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"BSHTMLLoader\"},\"description\":\"Load `HTML` files and parse them with `beautiful soup`.\",\"base_classes\":[\"Document\"],\"display_name\":\"BSHTMLLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/how_to/html\",\"beta\":false,\"error\":null},\"CSVLoader\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"suffixes\":[\".csv\"],\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\"csv\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"CSVLoader\"},\"description\":\"Load a `CSV` file into a list of Documents.\",\"base_classes\":[\"Document\"],\"display_name\":\"CSVLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/csv\",\"beta\":false,\"error\":null},\"CoNLLULoader\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"suffixes\":[\".csv\"],\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\"csv\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"CoNLLULoader\"},\"description\":\"Load `CoNLL-U` files.\",\"base_classes\":[\"Document\"],\"display_name\":\"CoNLLULoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/conll-u\",\"beta\":false,\"error\":null},\"CollegeConfidentialLoader\":{\"template\":{\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"web_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"web_path\",\"display_name\":\"Web Page\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"CollegeConfidentialLoader\"},\"description\":\"Load `College Confidential` webpages.\",\"base_classes\":[\"Document\"],\"display_name\":\"CollegeConfidentialLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/college_confidential\",\"beta\":false,\"error\":null},\"DirectoryLoader\":{\"template\":{\"glob\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"**/*.txt\",\"password\":false,\"name\":\"glob\",\"display_name\":\"glob\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"load_hidden\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"False\",\"password\":false,\"name\":\"load_hidden\",\"display_name\":\"Load hidden files\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"max_concurrency\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":10,\"password\":false,\"name\":\"max_concurrency\",\"display_name\":\"Max concurrency\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"path\",\"display_name\":\"Local directory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"recursive\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"True\",\"password\":false,\"name\":\"recursive\",\"display_name\":\"Recursive\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"silent_errors\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"False\",\"password\":false,\"name\":\"silent_errors\",\"display_name\":\"Silent errors\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"use_multithreading\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"True\",\"password\":false,\"name\":\"use_multithreading\",\"display_name\":\"Use multithreading\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"DirectoryLoader\"},\"description\":\"Load from a directory.\",\"base_classes\":[\"Document\"],\"display_name\":\"DirectoryLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/how_to/file_directory\",\"beta\":false,\"error\":null},\"EverNoteLoader\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"suffixes\":[\".xml\"],\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\"xml\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"EverNoteLoader\"},\"description\":\"Load from `EverNote`.\",\"base_classes\":[\"Document\"],\"display_name\":\"EverNoteLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/evernote\",\"beta\":false,\"error\":null},\"FacebookChatLoader\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"suffixes\":[\".json\"],\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\"json\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"FacebookChatLoader\"},\"description\":\"Load `Facebook Chat` messages directory dump.\",\"base_classes\":[\"Document\"],\"display_name\":\"FacebookChatLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/facebook_chat\",\"beta\":false,\"error\":null},\"GitLoader\":{\"template\":{\"branch\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"branch\",\"display_name\":\"Branch\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"clone_url\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"clone_url\",\"display_name\":\"Clone URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"file_filter\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"file_filter\",\"display_name\":\"File extensions (comma-separated)\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"repo_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"repo_path\",\"display_name\":\"Path to repository\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"GitLoader\"},\"description\":\"Load `Git` repository files.\",\"base_classes\":[\"Document\"],\"display_name\":\"GitLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/git\",\"beta\":false,\"error\":null},\"GitbookLoader\":{\"template\":{\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"web_page\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"web_page\",\"display_name\":\"Web Page\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"GitbookLoader\"},\"description\":\"Load `GitBook` data.\",\"base_classes\":[\"Document\"],\"display_name\":\"GitbookLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/gitbook\",\"beta\":false,\"error\":null},\"GutenbergLoader\":{\"template\":{\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"web_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"web_path\",\"display_name\":\"Web Page\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"GutenbergLoader\"},\"description\":\"Load from `Gutenberg.org`.\",\"base_classes\":[\"Document\"],\"display_name\":\"GutenbergLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/gutenberg\",\"beta\":false,\"error\":null},\"HNLoader\":{\"template\":{\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"web_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"web_path\",\"display_name\":\"Web Page\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"HNLoader\"},\"description\":\"Load `Hacker News` data.\",\"base_classes\":[\"Document\"],\"display_name\":\"HNLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/hacker_news\",\"beta\":false,\"error\":null},\"IFixitLoader\":{\"template\":{\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"web_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"web_path\",\"display_name\":\"Web Page\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"IFixitLoader\"},\"description\":\"Load `iFixit` repair guides, device wikis and answers.\",\"base_classes\":[\"Document\"],\"display_name\":\"IFixitLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/ifixit\",\"beta\":false,\"error\":null},\"IMSDbLoader\":{\"template\":{\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"web_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"web_path\",\"display_name\":\"Web Page\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"IMSDbLoader\"},\"description\":\"Load `IMSDb` webpages.\",\"base_classes\":[\"Document\"],\"display_name\":\"IMSDbLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/imsdb\",\"beta\":false,\"error\":null},\"NotionDirectoryLoader\":{\"template\":{\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"path\",\"display_name\":\"Local directory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"NotionDirectoryLoader\"},\"description\":\"Load `Notion directory` dump.\",\"base_classes\":[\"Document\"],\"display_name\":\"NotionDirectoryLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/notion\",\"beta\":false,\"error\":null},\"PyPDFLoader\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"suffixes\":[\".pdf\"],\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\"pdf\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"PyPDFLoader\"},\"description\":\"Load PDF using pypdf into list of documents.\",\"base_classes\":[\"Document\"],\"display_name\":\"PyPDFLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/how_to/pdf\",\"beta\":false,\"error\":null},\"PyPDFDirectoryLoader\":{\"template\":{\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"path\",\"display_name\":\"Local directory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"PyPDFDirectoryLoader\"},\"description\":\"Load a directory with `PDF` files using `pypdf` and chunks at character level.\",\"base_classes\":[\"Document\"],\"display_name\":\"PyPDFDirectoryLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/how_to/pdf\",\"beta\":false,\"error\":null},\"ReadTheDocsLoader\":{\"template\":{\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"path\",\"display_name\":\"Local directory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"ReadTheDocsLoader\"},\"description\":\"Load `ReadTheDocs` documentation directory.\",\"base_classes\":[\"Document\"],\"display_name\":\"ReadTheDocsLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/readthedocs_documentation\",\"beta\":false,\"error\":null},\"SRTLoader\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"suffixes\":[\".srt\"],\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\"srt\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"SRTLoader\"},\"description\":\"Load `.srt` (subtitle) files.\",\"base_classes\":[\"Document\"],\"display_name\":\"SRTLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/subtitle\",\"beta\":false,\"error\":null},\"SlackDirectoryLoader\":{\"template\":{\"zip_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"suffixes\":[\".zip\"],\"password\":false,\"name\":\"zip_path\",\"display_name\":\"Path to zip file\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\"zip\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"workspace_url\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"workspace_url\",\"display_name\":\"Workspace URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"SlackDirectoryLoader\"},\"description\":\"Load from a `Slack` directory dump.\",\"base_classes\":[\"Document\"],\"display_name\":\"SlackDirectoryLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/slack\",\"beta\":false,\"error\":null},\"TextLoader\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"suffixes\":[\".txt\"],\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\"txt\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"TextLoader\"},\"description\":\"Load text file.\",\"base_classes\":[\"Document\"],\"display_name\":\"TextLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/\",\"beta\":false,\"error\":null},\"UnstructuredEmailLoader\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"suffixes\":[\".eml\"],\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\"eml\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"UnstructuredEmailLoader\"},\"description\":\"Load email files using `Unstructured`.\",\"base_classes\":[\"Document\"],\"display_name\":\"UnstructuredEmailLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/email\",\"beta\":false,\"error\":null},\"UnstructuredHTMLLoader\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"suffixes\":[\".html\"],\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\"html\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"UnstructuredHTMLLoader\"},\"description\":\"Load `HTML` files using `Unstructured`.\",\"base_classes\":[\"Document\"],\"display_name\":\"UnstructuredHTMLLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/how_to/html\",\"beta\":false,\"error\":null},\"UnstructuredMarkdownLoader\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"suffixes\":[\".md\"],\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\"md\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"UnstructuredMarkdownLoader\"},\"description\":\"Load `Markdown` files using `Unstructured`.\",\"base_classes\":[\"Document\"],\"display_name\":\"UnstructuredMarkdownLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/how_to/markdown\",\"beta\":false,\"error\":null},\"UnstructuredPowerPointLoader\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"suffixes\":[\".pptx\",\".ppt\"],\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\"pptx\",\"ppt\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"UnstructuredPowerPointLoader\"},\"description\":\"Load `Microsoft PowerPoint` files using `Unstructured`.\",\"base_classes\":[\"Document\"],\"display_name\":\"UnstructuredPowerPointLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/microsoft_powerpoint\",\"beta\":false,\"error\":null},\"UnstructuredWordDocumentLoader\":{\"template\":{\"file_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"suffixes\":[\".docx\",\".doc\"],\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"file\",\"list\":false,\"fileTypes\":[\"docx\",\"doc\"],\"file_path\":null},\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"_type\":\"UnstructuredWordDocumentLoader\"},\"description\":\"Load `Microsoft Word` file using `Unstructured`.\",\"base_classes\":[\"Document\"],\"display_name\":\"UnstructuredWordDocumentLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/microsoft_word\",\"beta\":false,\"error\":null},\"WebBaseLoader\":{\"template\":{\"metadata\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{},\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"web_path\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"web_path\",\"display_name\":\"Web Page\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"WebBaseLoader\"},\"description\":\"Load HTML pages using `urllib` and parse them with `BeautifulSoup'.\",\"base_classes\":[\"Document\"],\"display_name\":\"WebBaseLoader\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/web_base\",\"beta\":false,\"error\":null}},\"textsplitters\":{\"CharacterTextSplitter\":{\"template\":{\"documents\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Document\",\"list\":true},\"chunk_overlap\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":200,\"password\":false,\"name\":\"chunk_overlap\",\"display_name\":\"Chunk Overlap\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"chunk_size\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":1000,\"password\":false,\"name\":\"chunk_size\",\"display_name\":\"Chunk Size\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"separator\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"\\\\n\",\"password\":false,\"name\":\"separator\",\"display_name\":\"Separator\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"CharacterTextSplitter\"},\"description\":\"Splitting text that looks at characters.\",\"base_classes\":[\"Document\"],\"display_name\":\"CharacterTextSplitter\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_transformers/text_splitters/character_text_splitter\",\"beta\":false,\"error\":null},\"LanguageRecursiveTextSplitter\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Optional\\nfrom langflow import CustomComponent\\nfrom langchain.text_splitter import Language\\nfrom langchain.schema import Document\\n\\n\\nclass LanguageRecursiveTextSplitterComponent(CustomComponent):\\n display_name: str = \\\"Language Recursive Text Splitter\\\"\\n description: str = \\\"Split text into chunks of a specified length based on language.\\\"\\n documentation: str = \\\"https://docs.langflow.org/components/text-splitters#languagerecursivetextsplitter\\\"\\n\\n def build_config(self):\\n options = [x.value for x in Language]\\n return {\\n \\\"documents\\\": {\\n \\\"display_name\\\": \\\"Documents\\\",\\n \\\"info\\\": \\\"The documents to split.\\\",\\n },\\n \\\"separator_type\\\": {\\n \\\"display_name\\\": \\\"Separator Type\\\",\\n \\\"info\\\": \\\"The type of separator to use.\\\",\\n \\\"field_type\\\": \\\"str\\\",\\n \\\"options\\\": options,\\n \\\"value\\\": \\\"Python\\\",\\n },\\n \\\"separators\\\": {\\n \\\"display_name\\\": \\\"Separators\\\",\\n \\\"info\\\": \\\"The characters to split on.\\\",\\n \\\"is_list\\\": True,\\n },\\n \\\"chunk_size\\\": {\\n \\\"display_name\\\": \\\"Chunk Size\\\",\\n \\\"info\\\": \\\"The maximum length of each chunk.\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"value\\\": 1000,\\n },\\n \\\"chunk_overlap\\\": {\\n \\\"display_name\\\": \\\"Chunk Overlap\\\",\\n \\\"info\\\": \\\"The amount of overlap between chunks.\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"value\\\": 200,\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n documents: list[Document],\\n chunk_size: Optional[int] = 1000,\\n chunk_overlap: Optional[int] = 200,\\n separator_type: Optional[str] = \\\"Python\\\",\\n ) -> list[Document]:\\n \\\"\\\"\\\"\\n Split text into chunks of a specified length.\\n\\n Args:\\n separators (list[str]): The characters to split on.\\n chunk_size (int): The maximum length of each chunk.\\n chunk_overlap (int): The amount of overlap between chunks.\\n length_function (function): The function to use to calculate the length of the text.\\n\\n Returns:\\n list[str]: The chunks of text.\\n \\\"\\\"\\\"\\n from langchain.text_splitter import RecursiveCharacterTextSplitter\\n\\n # Make sure chunk_size and chunk_overlap are ints\\n if isinstance(chunk_size, str):\\n chunk_size = int(chunk_size)\\n if isinstance(chunk_overlap, str):\\n chunk_overlap = int(chunk_overlap)\\n\\n splitter = RecursiveCharacterTextSplitter.from_language(\\n language=Language(separator_type),\\n chunk_size=chunk_size,\\n chunk_overlap=chunk_overlap,\\n )\\n\\n docs = splitter.split_documents(documents)\\n return docs\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"chunk_overlap\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":200,\"password\":false,\"name\":\"chunk_overlap\",\"display_name\":\"Chunk Overlap\",\"advanced\":false,\"dynamic\":false,\"info\":\"The amount of overlap between chunks.\",\"type\":\"int\",\"list\":false},\"chunk_size\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":1000,\"password\":false,\"name\":\"chunk_size\",\"display_name\":\"Chunk Size\",\"advanced\":false,\"dynamic\":false,\"info\":\"The maximum length of each chunk.\",\"type\":\"int\",\"list\":false},\"documents\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"The documents to split.\",\"type\":\"Document\",\"list\":true},\"separator_type\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"Python\",\"password\":false,\"options\":[\"cpp\",\"go\",\"java\",\"kotlin\",\"js\",\"ts\",\"php\",\"proto\",\"python\",\"rst\",\"ruby\",\"rust\",\"scala\",\"swift\",\"markdown\",\"latex\",\"html\",\"sol\",\"csharp\"],\"name\":\"separator_type\",\"display_name\":\"Separator Type\",\"advanced\":false,\"dynamic\":false,\"info\":\"The type of separator to use.\",\"type\":\"str\",\"list\":true}},\"description\":\"Split text into chunks of a specified length based on language.\",\"base_classes\":[\"Document\"],\"display_name\":\"Language Recursive Text Splitter\",\"custom_fields\":{\"chunk_overlap\":null,\"chunk_size\":null,\"documents\":null,\"separator_type\":null},\"output_types\":[\"LanguageRecursiveTextSplitter\"],\"documentation\":\"https://docs.langflow.org/components/text-splitters#languagerecursivetextsplitter\",\"beta\":true,\"error\":null},\"RecursiveCharacterTextSplitter\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Optional\\nfrom langflow import CustomComponent\\nfrom langchain.schema import Document\\nfrom langflow.utils.util import build_loader_repr_from_documents\\n\\n\\nclass RecursiveCharacterTextSplitterComponent(CustomComponent):\\n display_name: str = \\\"Recursive Character Text Splitter\\\"\\n description: str = \\\"Split text into chunks of a specified length.\\\"\\n documentation: str = \\\"https://docs.langflow.org/components/text-splitters#recursivecharactertextsplitter\\\"\\n\\n def build_config(self):\\n return {\\n \\\"documents\\\": {\\n \\\"display_name\\\": \\\"Documents\\\",\\n \\\"info\\\": \\\"The documents to split.\\\",\\n },\\n \\\"separators\\\": {\\n \\\"display_name\\\": \\\"Separators\\\",\\n \\\"info\\\": 'The characters to split on.\\\\nIf left empty defaults to [\\\"\\\\\\\\n\\\\\\\\n\\\", \\\"\\\\\\\\n\\\", \\\" \\\", \\\"\\\"].',\\n \\\"is_list\\\": True,\\n },\\n \\\"chunk_size\\\": {\\n \\\"display_name\\\": \\\"Chunk Size\\\",\\n \\\"info\\\": \\\"The maximum length of each chunk.\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"value\\\": 1000,\\n },\\n \\\"chunk_overlap\\\": {\\n \\\"display_name\\\": \\\"Chunk Overlap\\\",\\n \\\"info\\\": \\\"The amount of overlap between chunks.\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"value\\\": 200,\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n documents: list[Document],\\n separators: Optional[list[str]] = None,\\n chunk_size: Optional[int] = 1000,\\n chunk_overlap: Optional[int] = 200,\\n ) -> list[Document]:\\n \\\"\\\"\\\"\\n Split text into chunks of a specified length.\\n\\n Args:\\n separators (list[str]): The characters to split on.\\n chunk_size (int): The maximum length of each chunk.\\n chunk_overlap (int): The amount of overlap between chunks.\\n length_function (function): The function to use to calculate the length of the text.\\n\\n Returns:\\n list[str]: The chunks of text.\\n \\\"\\\"\\\"\\n from langchain.text_splitter import RecursiveCharacterTextSplitter\\n\\n if separators == \\\"\\\":\\n separators = None\\n elif separators:\\n # check if the separators list has escaped characters\\n # if there are escaped characters, unescape them\\n separators = [x.encode().decode(\\\"unicode-escape\\\") for x in separators]\\n\\n # Make sure chunk_size and chunk_overlap are ints\\n if isinstance(chunk_size, str):\\n chunk_size = int(chunk_size)\\n if isinstance(chunk_overlap, str):\\n chunk_overlap = int(chunk_overlap)\\n splitter = RecursiveCharacterTextSplitter(\\n separators=separators,\\n chunk_size=chunk_size,\\n chunk_overlap=chunk_overlap,\\n )\\n\\n docs = splitter.split_documents(documents)\\n self.repr_value = build_loader_repr_from_documents(docs)\\n return docs\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"chunk_overlap\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":200,\"password\":false,\"name\":\"chunk_overlap\",\"display_name\":\"Chunk Overlap\",\"advanced\":false,\"dynamic\":false,\"info\":\"The amount of overlap between chunks.\",\"type\":\"int\",\"list\":false},\"chunk_size\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":1000,\"password\":false,\"name\":\"chunk_size\",\"display_name\":\"Chunk Size\",\"advanced\":false,\"dynamic\":false,\"info\":\"The maximum length of each chunk.\",\"type\":\"int\",\"list\":false},\"documents\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"The documents to split.\",\"type\":\"Document\",\"list\":true},\"separators\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"separators\",\"display_name\":\"Separators\",\"advanced\":false,\"dynamic\":false,\"info\":\"The characters to split on.\\nIf left empty defaults to [\\\"\\\\n\\\\n\\\", \\\"\\\\n\\\", \\\" \\\", \\\"\\\"].\",\"type\":\"str\",\"list\":true}},\"description\":\"Split text into chunks of a specified length.\",\"base_classes\":[\"Document\"],\"display_name\":\"Recursive Character Text Splitter\",\"custom_fields\":{\"chunk_overlap\":null,\"chunk_size\":null,\"documents\":null,\"separators\":null},\"output_types\":[\"RecursiveCharacterTextSplitter\"],\"documentation\":\"https://docs.langflow.org/components/text-splitters#recursivecharactertextsplitter\",\"beta\":true,\"error\":null}},\"utilities\":{\"BingSearchAPIWrapper\":{\"template\":{\"bing_search_url\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"bing_search_url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"bing_subscription_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"bing_subscription_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"k\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":10,\"password\":false,\"name\":\"k\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"_type\":\"BingSearchAPIWrapper\"},\"description\":\"Wrapper for Bing Search API.\",\"base_classes\":[\"BingSearchAPIWrapper\"],\"display_name\":\"BingSearchAPIWrapper\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"GoogleSearchAPIWrapper\":{\"template\":{\"google_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"google_api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"google_cse_id\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"google_cse_id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"k\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":10,\"password\":false,\"name\":\"k\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"search_engine\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"search_engine\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"siterestrict\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"siterestrict\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"GoogleSearchAPIWrapper\"},\"description\":\"Wrapper for Google Search API.\",\"base_classes\":[\"GoogleSearchAPIWrapper\"],\"display_name\":\"GoogleSearchAPIWrapper\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"GoogleSerperAPIWrapper\":{\"template\":{\"aiosession\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"aiosession\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"ClientSession\",\"list\":false},\"gl\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"us\",\"password\":false,\"name\":\"gl\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"hl\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"en\",\"password\":false,\"name\":\"hl\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"k\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":10,\"password\":false,\"name\":\"k\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"result_key_for_type\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"{\\n \\\"news\\\": \\\"news\\\",\\n \\\"places\\\": \\\"places\\\",\\n \\\"images\\\": \\\"images\\\",\\n \\\"search\\\": \\\"organic\\\"\\n}\",\"password\":true,\"name\":\"result_key_for_type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"serper_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"serper_api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"tbs\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"tbs\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"type\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"search\",\"password\":false,\"options\":[\"news\",\"search\",\"places\",\"images\"],\"name\":\"type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"_type\":\"GoogleSerperAPIWrapper\"},\"description\":\"Wrapper around the Serper.dev Google Search API.\",\"base_classes\":[\"GoogleSerperAPIWrapper\"],\"display_name\":\"GoogleSerperAPIWrapper\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"SearxSearchWrapper\":{\"template\":{\"aiosession\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"aiosession\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"categories\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"categories\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"engines\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"engines\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":true},\"headers\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"{\\\"Authorization\\\": \\\"Bearer \\\"}\",\"password\":false,\"name\":\"headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"k\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":10,\"password\":false,\"name\":\"k\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"params\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"params\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"query_suffix\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"query_suffix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"searx_host\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"\",\"password\":false,\"name\":\"searx_host\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"unsecure\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"unsecure\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"_type\":\"SearxSearchWrapper\"},\"description\":\"Wrapper for Searx API.\",\"base_classes\":[\"SearxSearchWrapper\"],\"display_name\":\"SearxSearchWrapper\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"SerpAPIWrapper\":{\"template\":{\"aiosession\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"aiosession\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"ClientSession\",\"list\":false},\"params\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"{\\n \\\"engine\\\": \\\"google\\\",\\n \\\"google_domain\\\": \\\"google.com\\\",\\n \\\"gl\\\": \\\"us\\\",\\n \\\"hl\\\": \\\"en\\\"\\n}\",\"password\":false,\"name\":\"params\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false},\"search_engine\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"search_engine\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"serpapi_api_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"serpapi_api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"SerpAPIWrapper\"},\"description\":\"Wrapper around SerpAPI.\",\"base_classes\":[\"SerpAPIWrapper\"],\"display_name\":\"SerpAPIWrapper\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"WikipediaAPIWrapper\":{\"template\":{\"doc_content_chars_max\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":4000,\"password\":false,\"name\":\"doc_content_chars_max\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"lang\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":\"en\",\"password\":false,\"name\":\"lang\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"load_all_available_meta\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":false,\"password\":false,\"name\":\"load_all_available_meta\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"bool\",\"list\":false},\"top_k_results\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"value\":3,\"password\":false,\"name\":\"top_k_results\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"int\",\"list\":false},\"wiki_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"wiki_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"_type\":\"WikipediaAPIWrapper\"},\"description\":\"Wrapper around WikipediaAPI.\",\"base_classes\":[\"WikipediaAPIWrapper\"],\"display_name\":\"WikipediaAPIWrapper\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"WolframAlphaAPIWrapper\":{\"template\":{\"wolfram_alpha_appid\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"wolfram_alpha_appid\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"wolfram_client\":{\"required\":false,\"placeholder\":\"\",\"show\":false,\"multiline\":false,\"password\":false,\"name\":\"wolfram_client\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Any\",\"list\":false},\"_type\":\"WolframAlphaAPIWrapper\"},\"description\":\"Wrapper for Wolfram Alpha.\",\"base_classes\":[\"WolframAlphaAPIWrapper\"],\"display_name\":\"WolframAlphaAPIWrapper\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":false,\"error\":null},\"GetRequest\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langchain.schema import Document\\nfrom langflow.services.database.models.base import orjson_dumps\\nimport requests\\nfrom typing import Optional\\n\\n\\nclass GetRequest(CustomComponent):\\n display_name: str = \\\"GET Request\\\"\\n description: str = \\\"Make a GET request to the given URL.\\\"\\n output_types: list[str] = [\\\"Document\\\"]\\n documentation: str = \\\"https://docs.langflow.org/components/utilities#get-request\\\"\\n beta = True\\n field_config = {\\n \\\"url\\\": {\\n \\\"display_name\\\": \\\"URL\\\",\\n \\\"info\\\": \\\"The URL to make the request to\\\",\\n \\\"is_list\\\": True,\\n },\\n \\\"headers\\\": {\\n \\\"display_name\\\": \\\"Headers\\\",\\n \\\"info\\\": \\\"The headers to send with the request.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n \\\"timeout\\\": {\\n \\\"display_name\\\": \\\"Timeout\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"info\\\": \\\"The timeout to use for the request.\\\",\\n \\\"value\\\": 5,\\n },\\n }\\n\\n def get_document(\\n self, session: requests.Session, url: str, headers: Optional[dict], timeout: int\\n ) -> Document:\\n try:\\n response = session.get(url, headers=headers, timeout=int(timeout))\\n try:\\n response_json = response.json()\\n result = orjson_dumps(response_json, indent_2=False)\\n except Exception:\\n result = response.text\\n self.repr_value = result\\n return Document(\\n page_content=result,\\n metadata={\\n \\\"source\\\": url,\\n \\\"headers\\\": headers,\\n \\\"status_code\\\": response.status_code,\\n },\\n )\\n except requests.Timeout:\\n return Document(\\n page_content=\\\"Request Timed Out\\\",\\n metadata={\\\"source\\\": url, \\\"headers\\\": headers, \\\"status_code\\\": 408},\\n )\\n except Exception as exc:\\n return Document(\\n page_content=str(exc),\\n metadata={\\\"source\\\": url, \\\"headers\\\": headers, \\\"status_code\\\": 500},\\n )\\n\\n def build(\\n self,\\n url: str,\\n headers: Optional[dict] = None,\\n timeout: int = 5,\\n ) -> list[Document]:\\n if headers is None:\\n headers = {}\\n urls = url if isinstance(url, list) else [url]\\n with requests.Session() as session:\\n documents = [self.get_document(session, u, headers, timeout) for u in urls]\\n self.repr_value = documents\\n return documents\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"headers\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"headers\",\"display_name\":\"Headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"The headers to send with the request.\",\"type\":\"dict\",\"list\":false},\"timeout\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":5,\"password\":false,\"name\":\"timeout\",\"display_name\":\"Timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"The timeout to use for the request.\",\"type\":\"int\",\"list\":false},\"url\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"url\",\"display_name\":\"URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"The URL to make the request to\",\"type\":\"str\",\"list\":true}},\"description\":\"Make a GET request to the given URL.\",\"base_classes\":[\"Document\"],\"display_name\":\"GET Request\",\"custom_fields\":{\"headers\":null,\"timeout\":null,\"url\":null},\"output_types\":[\"GetRequest\"],\"documentation\":\"https://docs.langflow.org/components/utilities#get-request\",\"beta\":true,\"error\":null},\"PostRequest\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langchain.schema import Document\\nfrom langflow.services.database.models.base import orjson_dumps\\nimport requests\\nfrom typing import Optional\\n\\n\\nclass PostRequest(CustomComponent):\\n display_name: str = \\\"POST Request\\\"\\n description: str = \\\"Make a POST request to the given URL.\\\"\\n output_types: list[str] = [\\\"Document\\\"]\\n documentation: str = \\\"https://docs.langflow.org/components/utilities#post-request\\\"\\n beta = True\\n field_config = {\\n \\\"url\\\": {\\\"display_name\\\": \\\"URL\\\", \\\"info\\\": \\\"The URL to make the request to.\\\"},\\n \\\"headers\\\": {\\n \\\"display_name\\\": \\\"Headers\\\",\\n \\\"info\\\": \\\"The headers to send with the request.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n \\\"document\\\": {\\\"display_name\\\": \\\"Document\\\"},\\n }\\n\\n def post_document(\\n self,\\n session: requests.Session,\\n document: Document,\\n url: str,\\n headers: Optional[dict] = None,\\n ) -> Document:\\n try:\\n response = session.post(url, headers=headers, data=document.page_content)\\n try:\\n response_json = response.json()\\n result = orjson_dumps(response_json, indent_2=False)\\n except Exception:\\n result = response.text\\n self.repr_value = result\\n return Document(\\n page_content=result,\\n metadata={\\n \\\"source\\\": url,\\n \\\"headers\\\": headers,\\n \\\"status_code\\\": response,\\n },\\n )\\n except Exception as exc:\\n return Document(\\n page_content=str(exc),\\n metadata={\\n \\\"source\\\": url,\\n \\\"headers\\\": headers,\\n \\\"status_code\\\": 500,\\n },\\n )\\n\\n def build(\\n self,\\n document: Document,\\n url: str,\\n headers: Optional[dict] = None,\\n ) -> list[Document]:\\n if headers is None:\\n headers = {}\\n\\n if not isinstance(document, list) and isinstance(document, Document):\\n documents: list[Document] = [document]\\n elif isinstance(document, list) and all(\\n isinstance(doc, Document) for doc in document\\n ):\\n documents = document\\n else:\\n raise ValueError(\\\"document must be a Document or a list of Documents\\\")\\n\\n with requests.Session() as session:\\n documents = [\\n self.post_document(session, doc, url, headers) for doc in documents\\n ]\\n self.repr_value = documents\\n return documents\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"document\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"document\",\"display_name\":\"Document\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Document\",\"list\":false},\"headers\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"headers\",\"display_name\":\"Headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"The headers to send with the request.\",\"type\":\"dict\",\"list\":false},\"url\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"url\",\"display_name\":\"URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"The URL to make the request to.\",\"type\":\"str\",\"list\":false}},\"description\":\"Make a POST request to the given URL.\",\"base_classes\":[\"Document\"],\"display_name\":\"POST Request\",\"custom_fields\":{\"document\":null,\"headers\":null,\"url\":null},\"output_types\":[\"PostRequest\"],\"documentation\":\"https://docs.langflow.org/components/utilities#post-request\",\"beta\":true,\"error\":null},\"UpdateRequest\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import List, Optional\\nimport requests\\nfrom langflow import CustomComponent\\nfrom langchain.schema import Document\\nfrom langflow.services.database.models.base import orjson_dumps\\n\\n\\nclass UpdateRequest(CustomComponent):\\n display_name: str = \\\"Update Request\\\"\\n description: str = \\\"Make a PATCH request to the given URL.\\\"\\n output_types: list[str] = [\\\"Document\\\"]\\n documentation: str = \\\"https://docs.langflow.org/components/utilities#update-request\\\"\\n beta = True\\n field_config = {\\n \\\"url\\\": {\\\"display_name\\\": \\\"URL\\\", \\\"info\\\": \\\"The URL to make the request to.\\\"},\\n \\\"headers\\\": {\\n \\\"display_name\\\": \\\"Headers\\\",\\n \\\"field_type\\\": \\\"NestedDict\\\",\\n \\\"info\\\": \\\"The headers to send with the request.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n \\\"document\\\": {\\\"display_name\\\": \\\"Document\\\"},\\n \\\"method\\\": {\\n \\\"display_name\\\": \\\"Method\\\",\\n \\\"field_type\\\": \\\"str\\\",\\n \\\"info\\\": \\\"The HTTP method to use.\\\",\\n \\\"options\\\": [\\\"PATCH\\\", \\\"PUT\\\"],\\n \\\"value\\\": \\\"PATCH\\\",\\n },\\n }\\n\\n def update_document(\\n self,\\n session: requests.Session,\\n document: Document,\\n url: str,\\n headers: Optional[dict] = None,\\n method: str = \\\"PATCH\\\",\\n ) -> Document:\\n try:\\n if method == \\\"PATCH\\\":\\n response = session.patch(\\n url, headers=headers, data=document.page_content\\n )\\n elif method == \\\"PUT\\\":\\n response = session.put(url, headers=headers, data=document.page_content)\\n else:\\n raise ValueError(f\\\"Unsupported method: {method}\\\")\\n try:\\n response_json = response.json()\\n result = orjson_dumps(response_json, indent_2=False)\\n except Exception:\\n result = response.text\\n self.repr_value = result\\n return Document(\\n page_content=result,\\n metadata={\\n \\\"source\\\": url,\\n \\\"headers\\\": headers,\\n \\\"status_code\\\": response.status_code,\\n },\\n )\\n except Exception as exc:\\n return Document(\\n page_content=str(exc),\\n metadata={\\\"source\\\": url, \\\"headers\\\": headers, \\\"status_code\\\": 500},\\n )\\n\\n def build(\\n self,\\n method: str,\\n document: Document,\\n url: str,\\n headers: Optional[dict] = None,\\n ) -> List[Document]:\\n if headers is None:\\n headers = {}\\n\\n if not isinstance(document, list) and isinstance(document, Document):\\n documents: list[Document] = [document]\\n elif isinstance(document, list) and all(\\n isinstance(doc, Document) for doc in document\\n ):\\n documents = document\\n else:\\n raise ValueError(\\\"document must be a Document or a list of Documents\\\")\\n\\n with requests.Session() as session:\\n documents = [\\n self.update_document(session, doc, url, headers, method)\\n for doc in documents\\n ]\\n self.repr_value = documents\\n return documents\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"document\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"document\",\"display_name\":\"Document\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Document\",\"list\":false},\"headers\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"headers\",\"display_name\":\"Headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"The headers to send with the request.\",\"type\":\"NestedDict\",\"list\":false},\"method\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"PATCH\",\"password\":false,\"options\":[\"PATCH\",\"PUT\"],\"name\":\"method\",\"display_name\":\"Method\",\"advanced\":false,\"dynamic\":false,\"info\":\"The HTTP method to use.\",\"type\":\"str\",\"list\":true},\"url\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"url\",\"display_name\":\"URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"The URL to make the request to.\",\"type\":\"str\",\"list\":false}},\"description\":\"Make a PATCH request to the given URL.\",\"base_classes\":[\"Document\"],\"display_name\":\"Update Request\",\"custom_fields\":{\"document\":null,\"headers\":null,\"method\":null,\"url\":null},\"output_types\":[\"UpdateRequest\"],\"documentation\":\"https://docs.langflow.org/components/utilities#update-request\",\"beta\":true,\"error\":null},\"JSONDocumentBuilder\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"### JSON Document Builder\\n\\n# Build a Document containing a JSON object using a key and another Document page content.\\n\\n# **Params**\\n\\n# - **Key:** The key to use for the JSON object.\\n# - **Document:** The Document page to use for the JSON object.\\n\\n# **Output**\\n\\n# - **Document:** The Document containing the JSON object.\\n\\nfrom langflow import CustomComponent\\nfrom langchain.schema import Document\\nfrom langflow.services.database.models.base import orjson_dumps\\n\\n\\nclass JSONDocumentBuilder(CustomComponent):\\n display_name: str = \\\"JSON Document Builder\\\"\\n description: str = \\\"Build a Document containing a JSON object using a key and another Document page content.\\\"\\n output_types: list[str] = [\\\"Document\\\"]\\n beta = True\\n documentation: str = (\\n \\\"https://docs.langflow.org/components/utilities#json-document-builder\\\"\\n )\\n\\n field_config = {\\n \\\"key\\\": {\\\"display_name\\\": \\\"Key\\\"},\\n \\\"document\\\": {\\\"display_name\\\": \\\"Document\\\"},\\n }\\n\\n def build(\\n self,\\n key: str,\\n document: Document,\\n ) -> Document:\\n documents = None\\n if isinstance(document, list):\\n documents = [\\n Document(\\n page_content=orjson_dumps({key: doc.page_content}, indent_2=False)\\n )\\n for doc in document\\n ]\\n elif isinstance(document, Document):\\n documents = Document(\\n page_content=orjson_dumps({key: document.page_content}, indent_2=False)\\n )\\n else:\\n raise TypeError(\\n f\\\"Expected Document or list of Documents, got {type(document)}\\\"\\n )\\n self.repr_value = documents\\n return documents\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"document\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"document\",\"display_name\":\"Document\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"Document\",\"list\":false},\"key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"key\",\"display_name\":\"Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false}},\"description\":\"Build a Document containing a JSON object using a key and another Document page content.\",\"base_classes\":[\"Document\"],\"display_name\":\"JSON Document Builder\",\"custom_fields\":{\"document\":null,\"key\":null},\"output_types\":[\"JSONDocumentBuilder\"],\"documentation\":\"https://docs.langflow.org/components/utilities#json-document-builder\",\"beta\":true,\"error\":null}},\"output_parsers\":{\"ResponseSchema\":{\"template\":{\"description\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"password\":false,\"name\":\"description\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"name\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"type\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"string\",\"password\":false,\"name\":\"type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"ResponseSchema\"},\"description\":\"A schema for a response from a structured output parser.\",\"base_classes\":[\"ResponseSchema\"],\"display_name\":\"ResponseSchema\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/output_parsers/structured\",\"beta\":false,\"error\":null},\"StructuredOutputParser\":{\"template\":{\"response_schemas\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"response_schemas\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"ResponseSchema\",\"list\":true},\"_type\":\"StructuredOutputParser\"},\"description\":\"\",\"base_classes\":[\"BaseLLMOutputParser\",\"BaseOutputParser\",\"StructuredOutputParser\"],\"display_name\":\"StructuredOutputParser\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/model_io/output_parsers/structured\",\"beta\":false,\"error\":null}},\"retrievers\":{\"MultiQueryRetriever\":{\"template\":{\"llm\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseLLM\",\"list\":false},\"prompt\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":{\"input_variables\":[\"question\"],\"input_types\":{},\"output_parser\":null,\"partial_variables\":{},\"template\":\"You are an AI language model assistant. Your task is \\n to generate 3 different versions of the given user \\n question to retrieve relevant documents from a vector database. \\n By generating multiple perspectives on the user question, \\n your goal is to help the user overcome some of the limitations \\n of distance-based similarity search. Provide these alternative \\n questions separated by newlines. Original question: {question}\",\"template_format\":\"f-string\",\"validate_template\":true,\"_type\":\"prompt\"},\"password\":false,\"name\":\"prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"PromptTemplate\",\"list\":false},\"retriever\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"retriever\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"BaseRetriever\",\"list\":false},\"parser_key\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"value\":\"lines\",\"password\":false,\"name\":\"parser_key\",\"display_name\":\"Parser Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"_type\":\"MultiQueryRetriever\"},\"description\":\"Initialize from llm using default template.\",\"base_classes\":[\"MultiQueryRetriever\",\"BaseRetriever\"],\"display_name\":\"MultiQueryRetriever\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/retrievers/how_to/MultiQueryRetriever\",\"beta\":false,\"error\":null},\"MetalRetriever\":{\"template\":{\"code\":{\"dynamic\":true,\"required\":true,\"placeholder\":\"\",\"show\":false,\"multiline\":true,\"value\":\"from typing import Optional\\nfrom langflow import CustomComponent\\nfrom langchain.retrievers import MetalRetriever\\nfrom langchain.schema import BaseRetriever\\nfrom metal_sdk.metal import Metal # type: ignore\\n\\n\\nclass MetalRetrieverComponent(CustomComponent):\\n display_name: str = \\\"Metal Retriever\\\"\\n description: str = \\\"Retriever that uses the Metal API.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"api_key\\\": {\\\"display_name\\\": \\\"API Key\\\", \\\"password\\\": True},\\n \\\"client_id\\\": {\\\"display_name\\\": \\\"Client ID\\\", \\\"password\\\": True},\\n \\\"index_id\\\": {\\\"display_name\\\": \\\"Index ID\\\"},\\n \\\"params\\\": {\\\"display_name\\\": \\\"Parameters\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self, api_key: str, client_id: str, index_id: str, params: Optional[dict] = None\\n ) -> BaseRetriever:\\n try:\\n metal = Metal(api_key=api_key, client_id=client_id, index_id=index_id)\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to Metal API.\\\") from e\\n return MetalRetriever(client=metal, params=params or {})\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\",\"api_key\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"api_key\",\"display_name\":\"API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"client_id\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":true,\"name\":\"client_id\",\"display_name\":\"Client ID\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"index_id\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"index_id\",\"display_name\":\"Index ID\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"str\",\"list\":false},\"params\":{\"required\":false,\"placeholder\":\"\",\"show\":true,\"multiline\":false,\"password\":false,\"name\":\"params\",\"display_name\":\"Parameters\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"type\":\"dict\",\"list\":false}},\"description\":\"Retriever that uses the Metal API.\",\"base_classes\":[\"BaseRetriever\"],\"display_name\":\"Metal Retriever\",\"custom_fields\":{\"api_key\":null,\"client_id\":null,\"index_id\":null,\"params\":null},\"output_types\":[\"MetalRetriever\"],\"documentation\":\"\",\"beta\":true,\"error\":null}},\"custom_components\":{\"CustomComponent\":{\"template\":{\"code\":{\"required\":true,\"placeholder\":\"\",\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\n\\nfrom langflow.field_typing import (\\n Tool,\\n PromptTemplate,\\n Chain,\\n BaseChatMemory,\\n BaseLLM,\\n BaseLoader,\\n BaseMemory,\\n BaseOutputParser,\\n BaseRetriever,\\n VectorStore,\\n Embeddings,\\n TextSplitter,\\n Document,\\n AgentExecutor,\\n NestedDict,\\n Data,\\n)\\n\\n\\nclass Component(CustomComponent):\\n display_name: str = \\\"Custom Component\\\"\\n description: str = \\\"Create any custom component you want!\\\"\\n\\n def build_config(self):\\n return {\\\"param\\\": {\\\"display_name\\\": \\\"Parameter\\\"}}\\n\\n def build(self, param: Data) -> Data:\\n return param\\n\\n\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"type\":\"code\",\"list\":false},\"_type\":\"CustomComponent\"},\"description\":null,\"base_classes\":[],\"display_name\":\"Custom Component\",\"custom_fields\":{},\"output_types\":[],\"documentation\":\"\",\"beta\":true,\"error\":null}}}" - }, - "headersSize": -1, - "bodySize": -1, - "redirectURL": "" - }, - "cache": {}, - "timings": { "send": -1, "wait": -1, "receive": 1.031 } + "cache": {}, + "timings": { "send": -1, "wait": -1, "receive": 0.944 } + }, + { + "startedDateTime": "2024-02-28T14:32:30.976Z", + "time": 0.697, + "request": { + "method": "GET", + "url": "http://localhost:3000/api/v1/version", + "httpVersion": "HTTP/1.1", + "cookies": [], + "headers": [ + { "name": "Accept", "value": "application/json, text/plain, */*" }, + { "name": "Accept-Encoding", "value": "gzip, deflate, br, zstd" }, + { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, + { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMzg5ZmIyOS1kYWE2LTQwOGMtYjhjYi1iOGZmOGQxNzM0M2EiLCJleHAiOjE3NDA2NjY3NTB9.ef5W5jwNOeVzU3JZ7ylLYf2MLEJcVxC4-fF7EK9Ecdc" }, + { "name": "Connection", "value": "keep-alive" }, + { "name": "Cookie", "value": "access_token_lf=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMzg5ZmIyOS1kYWE2LTQwOGMtYjhjYi1iOGZmOGQxNzM0M2EiLCJleHAiOjE3NDA2NjY3NTB9.ef5W5jwNOeVzU3JZ7ylLYf2MLEJcVxC4-fF7EK9Ecdc" }, + { "name": "Host", "value": "localhost:3000" }, + { "name": "Referer", "value": "http://localhost:3000/" }, + { "name": "Sec-Fetch-Dest", "value": "empty" }, + { "name": "Sec-Fetch-Mode", "value": "cors" }, + { "name": "Sec-Fetch-Site", "value": "same-origin" }, + { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" }, + { "name": "sec-ch-ua", "value": "\"Chromium\";v=\"123\", \"Not:A-Brand\";v=\"8\"" }, + { "name": "sec-ch-ua-mobile", "value": "?0" }, + { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } + ], + "queryString": [], + "headersSize": -1, + "bodySize": -1 }, - { - "startedDateTime": "2023-08-31T14:55:36.131Z", - "time": 0.743, - "request": { - "method": "GET", - "url": "http://localhost:3000/api/v1/flows/", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Accept", "value": "application/json, text/plain, */*" }, - { "name": "Accept-Encoding", "value": "gzip, deflate, br" }, - { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, - { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiNWIxYjFhZC05M2VjLTRjMjgtYWMxNy01OGMxNDQ0MWI1ZGQiLCJleHAiOjE3MjUwMjk3MzV9.8qhEtryWqA9RbwEP2s20umKdVE7J7jHGoogXZqxLNWk" }, - { "name": "Connection", "value": "keep-alive" }, - { "name": "Cookie", "value": "access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiNWIxYjFhZC05M2VjLTRjMjgtYWMxNy01OGMxNDQ0MWI1ZGQiLCJleHAiOjE3MjUwMjk3MzV9.8qhEtryWqA9RbwEP2s20umKdVE7J7jHGoogXZqxLNWk; refresh_token=auto" }, - { "name": "Host", "value": "localhost:3000" }, - { "name": "Referer", "value": "http://localhost:3000/" }, - { "name": "Sec-Fetch-Dest", "value": "empty" }, - { "name": "Sec-Fetch-Mode", "value": "cors" }, - { "name": "Sec-Fetch-Site", "value": "same-origin" }, - { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36" }, - { "name": "sec-ch-ua", "value": "\"Not)A;Brand\";v=\"24\", \"Chromium\";v=\"116\"" }, - { "name": "sec-ch-ua-mobile", "value": "?0" }, - { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } - ], - "queryString": [], - "headersSize": -1, - "bodySize": -1 + "response": { + "status": 200, + "statusText": "OK", + "httpVersion": "HTTP/1.1", + "cookies": [], + "headers": [ + { "name": "Access-Control-Allow-Origin", "value": "*" }, + { "name": "connection", "value": "close" }, + { "name": "content-length", "value": "19" }, + { "name": "content-type", "value": "application/json" }, + { "name": "date", "value": "Wed, 28 Feb 2024 14:32:30 GMT" }, + { "name": "server", "value": "uvicorn" } + ], + "content": { + "size": -1, + "mimeType": "application/json", + "text": "{\"version\":\"0.6.7\"}" }, - "response": { - "status": 200, - "statusText": "OK", - "httpVersion": "HTTP/1.1", - "cookies": [], - "headers": [ - { "name": "Access-Control-Allow-Origin", "value": "*" }, - { "name": "connection", "value": "close" }, - { "name": "content-length", "value": "2" }, - { "name": "content-type", "value": "application/json" }, - { "name": "date", "value": "Thu, 31 Aug 2023 14:55:35 GMT" }, - { "name": "server", "value": "uvicorn" } - ], - "content": { - "size": -1, - "mimeType": "application/json", - "text": "[]" - }, - "headersSize": -1, - "bodySize": -1, - "redirectURL": "" + "headersSize": -1, + "bodySize": -1, + "redirectURL": "" + }, + "cache": {}, + "timings": { "send": -1, "wait": -1, "receive": 0.697 } + }, + { + "startedDateTime": "2024-02-28T14:32:30.976Z", + "time": 2.771, + "request": { + "method": "GET", + "url": "http://localhost:3000/api/v1/all", + "httpVersion": "HTTP/1.1", + "cookies": [], + "headers": [ + { "name": "Accept", "value": "application/json, text/plain, */*" }, + { "name": "Accept-Encoding", "value": "gzip, deflate, br, zstd" }, + { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, + { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMzg5ZmIyOS1kYWE2LTQwOGMtYjhjYi1iOGZmOGQxNzM0M2EiLCJleHAiOjE3NDA2NjY3NTB9.ef5W5jwNOeVzU3JZ7ylLYf2MLEJcVxC4-fF7EK9Ecdc" }, + { "name": "Connection", "value": "keep-alive" }, + { "name": "Cookie", "value": "access_token_lf=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMzg5ZmIyOS1kYWE2LTQwOGMtYjhjYi1iOGZmOGQxNzM0M2EiLCJleHAiOjE3NDA2NjY3NTB9.ef5W5jwNOeVzU3JZ7ylLYf2MLEJcVxC4-fF7EK9Ecdc" }, + { "name": "Host", "value": "localhost:3000" }, + { "name": "Referer", "value": "http://localhost:3000/" }, + { "name": "Sec-Fetch-Dest", "value": "empty" }, + { "name": "Sec-Fetch-Mode", "value": "cors" }, + { "name": "Sec-Fetch-Site", "value": "same-origin" }, + { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" }, + { "name": "sec-ch-ua", "value": "\"Chromium\";v=\"123\", \"Not:A-Brand\";v=\"8\"" }, + { "name": "sec-ch-ua-mobile", "value": "?0" }, + { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } + ], + "queryString": [], + "headersSize": -1, + "bodySize": -1 + }, + "response": { + "status": 200, + "statusText": "OK", + "httpVersion": "HTTP/1.1", + "cookies": [], + "headers": [ + { "name": "Access-Control-Allow-Origin", "value": "*" }, + { "name": "connection", "value": "close" }, + { "name": "content-length", "value": "633593" }, + { "name": "content-type", "value": "application/json" }, + { "name": "date", "value": "Wed, 28 Feb 2024 14:32:30 GMT" }, + { "name": "server", "value": "uvicorn" } + ], + "content": { + "size": -1, + "mimeType": "application/json", + "text": "{\"chains\":{\"ConversationalRetrievalChain\":{\"template\":{\"callbacks\":{\"type\":\"Callbacks\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"condense_question_llm\":{\"type\":\"BaseLanguageModel\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"condense_question_llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"condense_question_prompt\":{\"type\":\"BasePromptTemplate\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":{\"name\":null,\"input_variables\":[\"chat_history\",\"question\"],\"input_types\":{},\"output_parser\":null,\"partial_variables\":{},\"metadata\":null,\"tags\":null,\"template\":\"Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question, in its original language.\\n\\nChat History:\\n{chat_history}\\nFollow Up Input: {question}\\nStandalone question:\",\"template_format\":\"f-string\",\"validate_template\":false},\"fileTypes\":[],\"password\":false,\"name\":\"condense_question_prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"memory\":{\"type\":\"BaseChatMemory\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"retriever\":{\"type\":\"BaseRetriever\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"retriever\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"chain_type\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"stuff\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"stuff\",\"map_reduce\",\"map_rerank\",\"refine\"],\"name\":\"chain_type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"combine_docs_chain_kwargs\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"combine_docs_chain_kwargs\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"return_source_documents\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":true,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"return_source_documents\",\"display_name\":\"Return source documents\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"verbose\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"password\":false,\"name\":\"verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"ConversationalRetrievalChain\"},\"description\":\"Convenience method to load chain from LLM and retriever.\",\"base_classes\":[\"BaseConversationalRetrievalChain\",\"Runnable\",\"Chain\",\"Generic\",\"Text\",\"RunnableSerializable\",\"Serializable\",\"object\",\"ConversationalRetrievalChain\",\"Callable\"],\"display_name\":\"ConversationalRetrievalChain\",\"documentation\":\"https://python.langchain.com/docs/modules/chains/popular/chat_vector_db\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false,\"output_type\":\"Chain\"},\"LLMCheckerChain\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Callable, Union\\n\\nfrom langchain.chains import LLMCheckerChain\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import BaseLanguageModel, Chain\\n\\n\\nclass LLMCheckerChainComponent(CustomComponent):\\n display_name = \\\"LLMCheckerChain\\\"\\n description = \\\"\\\"\\n documentation = \\\"https://python.langchain.com/docs/modules/chains/additional/llm_checker\\\"\\n\\n def build_config(self):\\n return {\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n }\\n\\n def build(\\n self,\\n llm: BaseLanguageModel,\\n ) -> Union[Chain, Callable]:\\n return LLMCheckerChain.from_llm(llm=llm)\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"\",\"base_classes\":[\"Runnable\",\"Chain\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"object\",\"Callable\"],\"display_name\":\"LLMCheckerChain\",\"documentation\":\"https://python.langchain.com/docs/modules/chains/additional/llm_checker\",\"custom_fields\":{\"llm\":null},\"output_types\":[\"Chain\",\"Callable\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"LLMMathChain\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"llm_chain\":{\"type\":\"LLMChain\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm_chain\",\"display_name\":\"LLM Chain\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"memory\":{\"type\":\"BaseMemory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Callable, Optional, Union\\n\\nfrom langchain.chains import LLMChain, LLMMathChain\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import BaseLanguageModel, BaseMemory, Chain\\n\\n\\nclass LLMMathChainComponent(CustomComponent):\\n display_name = \\\"LLMMathChain\\\"\\n description = \\\"Chain that interprets a prompt and executes python code to do math.\\\"\\n documentation = \\\"https://python.langchain.com/docs/modules/chains/additional/llm_math\\\"\\n\\n def build_config(self):\\n return {\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"llm_chain\\\": {\\\"display_name\\\": \\\"LLM Chain\\\"},\\n \\\"memory\\\": {\\\"display_name\\\": \\\"Memory\\\"},\\n \\\"input_key\\\": {\\\"display_name\\\": \\\"Input Key\\\"},\\n \\\"output_key\\\": {\\\"display_name\\\": \\\"Output Key\\\"},\\n }\\n\\n def build(\\n self,\\n llm: BaseLanguageModel,\\n llm_chain: LLMChain,\\n input_key: str = \\\"question\\\",\\n output_key: str = \\\"answer\\\",\\n memory: Optional[BaseMemory] = None,\\n ) -> Union[LLMMathChain, Callable, Chain]:\\n return LLMMathChain(llm=llm, llm_chain=llm_chain, input_key=input_key, output_key=output_key, memory=memory)\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"input_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"question\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"input_key\",\"display_name\":\"Input Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"output_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"answer\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"output_key\",\"display_name\":\"Output Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Chain that interprets a prompt and executes python code to do math.\",\"base_classes\":[\"LLMMathChain\",\"Runnable\",\"Chain\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"object\",\"Callable\"],\"display_name\":\"LLMMathChain\",\"documentation\":\"https://python.langchain.com/docs/modules/chains/additional/llm_math\",\"custom_fields\":{\"llm\":null,\"llm_chain\":null,\"input_key\":null,\"output_key\":null,\"memory\":null},\"output_types\":[\"LLMMathChain\",\"Callable\",\"Chain\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"RetrievalQA\":{\"template\":{\"combine_documents_chain\":{\"type\":\"BaseCombineDocumentsChain\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"combine_documents_chain\",\"display_name\":\"Combine Documents Chain\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"memory\":{\"type\":\"BaseMemory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"retriever\":{\"type\":\"BaseRetriever\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"retriever\",\"display_name\":\"Retriever\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Callable, Optional, Union\\n\\nfrom langchain.chains.combine_documents.base import BaseCombineDocumentsChain\\nfrom langchain.chains.retrieval_qa.base import BaseRetrievalQA, RetrievalQA\\nfrom langchain_core.documents import Document\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import BaseMemory, BaseRetriever, Text\\n\\n\\nclass RetrievalQAComponent(CustomComponent):\\n display_name = \\\"Retrieval QA\\\"\\n description = \\\"Chain for question-answering against an index.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"combine_documents_chain\\\": {\\\"display_name\\\": \\\"Combine Documents Chain\\\"},\\n \\\"retriever\\\": {\\\"display_name\\\": \\\"Retriever\\\"},\\n \\\"memory\\\": {\\\"display_name\\\": \\\"Memory\\\", \\\"required\\\": False},\\n \\\"input_key\\\": {\\\"display_name\\\": \\\"Input Key\\\", \\\"advanced\\\": True},\\n \\\"output_key\\\": {\\\"display_name\\\": \\\"Output Key\\\", \\\"advanced\\\": True},\\n \\\"return_source_documents\\\": {\\\"display_name\\\": \\\"Return Source Documents\\\"},\\n \\\"inputs\\\": {\\\"display_name\\\": \\\"Input\\\", \\\"input_types\\\": [\\\"Text\\\", \\\"Document\\\"]},\\n }\\n\\n def build(\\n self,\\n combine_documents_chain: BaseCombineDocumentsChain,\\n retriever: BaseRetriever,\\n inputs: str = \\\"\\\",\\n memory: Optional[BaseMemory] = None,\\n input_key: str = \\\"query\\\",\\n output_key: str = \\\"result\\\",\\n return_source_documents: bool = True,\\n ) -> Union[BaseRetrievalQA, Callable, Text]:\\n runnable = RetrievalQA(\\n combine_documents_chain=combine_documents_chain,\\n retriever=retriever,\\n memory=memory,\\n input_key=input_key,\\n output_key=output_key,\\n return_source_documents=return_source_documents,\\n )\\n if isinstance(inputs, Document):\\n inputs = inputs.page_content\\n self.status = runnable\\n result = runnable.invoke({input_key: inputs})\\n result = result.content if hasattr(result, \\\"content\\\") else result\\n # Result is a dict with keys \\\"query\\\", \\\"result\\\" and \\\"source_documents\\\"\\n # for now we just return the result\\n records = self.to_records(result.get(\\\"source_documents\\\"))\\n references_str = \\\"\\\"\\n if return_source_documents:\\n references_str = self.create_references_from_records(records)\\n result_str = result.get(\\\"result\\\")\\n final_result = \\\"\\\\n\\\".join([result_str, references_str])\\n self.status = final_result\\n return final_result\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"input_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"query\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"input_key\",\"display_name\":\"Input Key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"inputs\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"inputs\",\"display_name\":\"Input\",\"advanced\":false,\"input_types\":[\"Text\",\"Document\",\"Text\"],\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"output_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"result\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"output_key\",\"display_name\":\"Output Key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"return_source_documents\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":true,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"return_source_documents\",\"display_name\":\"Return Source Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Chain for question-answering against an index.\",\"base_classes\":[\"Runnable\",\"Chain\",\"BaseRetrievalQA\",\"Generic\",\"Text\",\"RunnableSerializable\",\"Serializable\",\"object\",\"Callable\"],\"display_name\":\"Retrieval QA\",\"documentation\":\"\",\"custom_fields\":{\"combine_documents_chain\":null,\"retriever\":null,\"inputs\":null,\"memory\":null,\"input_key\":null,\"output_key\":null,\"return_source_documents\":null},\"output_types\":[\"BaseRetrievalQA\",\"Callable\",\"Text\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"RetrievalQAWithSourcesChain\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"memory\":{\"type\":\"BaseMemory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"retriever\":{\"type\":\"BaseRetriever\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"retriever\",\"display_name\":\"Retriever\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"chain_type\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"stuff\",\"map_reduce\",\"map_rerank\",\"refine\"],\"name\":\"chain_type\",\"display_name\":\"Chain Type\",\"advanced\":false,\"dynamic\":false,\"info\":\"The type of chain to use to combined Documents.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain.chains import RetrievalQAWithSourcesChain\\nfrom langchain_core.documents import Document\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import BaseLanguageModel, BaseMemory, BaseRetriever, Text\\n\\n\\nclass RetrievalQAWithSourcesChainComponent(CustomComponent):\\n display_name = \\\"RetrievalQAWithSourcesChain\\\"\\n description = \\\"Question-answering with sources over an index.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"chain_type\\\": {\\n \\\"display_name\\\": \\\"Chain Type\\\",\\n \\\"options\\\": [\\\"stuff\\\", \\\"map_reduce\\\", \\\"map_rerank\\\", \\\"refine\\\"],\\n \\\"info\\\": \\\"The type of chain to use to combined Documents.\\\",\\n },\\n \\\"memory\\\": {\\\"display_name\\\": \\\"Memory\\\"},\\n \\\"return_source_documents\\\": {\\\"display_name\\\": \\\"Return Source Documents\\\"},\\n \\\"retriever\\\": {\\\"display_name\\\": \\\"Retriever\\\"},\\n }\\n\\n def build(\\n self,\\n inputs: str,\\n retriever: BaseRetriever,\\n llm: BaseLanguageModel,\\n chain_type: str,\\n memory: Optional[BaseMemory] = None,\\n return_source_documents: Optional[bool] = True,\\n ) -> Text:\\n runnable = RetrievalQAWithSourcesChain.from_chain_type(\\n llm=llm,\\n chain_type=chain_type,\\n memory=memory,\\n return_source_documents=return_source_documents,\\n retriever=retriever,\\n )\\n if isinstance(inputs, Document):\\n inputs = inputs.page_content\\n self.status = runnable\\n input_key = runnable.input_keys[0]\\n result = runnable.invoke({input_key: inputs})\\n result = result.content if hasattr(result, \\\"content\\\") else result\\n # Result is a dict with keys \\\"query\\\", \\\"result\\\" and \\\"source_documents\\\"\\n # for now we just return the result\\n records = self.to_records(result.get(\\\"source_documents\\\"))\\n references_str = \\\"\\\"\\n if return_source_documents:\\n references_str = self.create_references_from_records(records)\\n result_str = result.get(\\\"answer\\\")\\n final_result = \\\"\\\\n\\\".join([result_str, references_str])\\n self.status = final_result\\n return final_result\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"inputs\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"inputs\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"return_source_documents\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":true,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"return_source_documents\",\"display_name\":\"Return Source Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Question-answering with sources over an index.\",\"base_classes\":[\"Text\",\"object\"],\"display_name\":\"RetrievalQAWithSourcesChain\",\"documentation\":\"\",\"custom_fields\":{\"inputs\":null,\"retriever\":null,\"llm\":null,\"chain_type\":null,\"memory\":null,\"return_source_documents\":null},\"output_types\":[\"Text\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"SQLDatabaseChain\":{\"template\":{\"db\":{\"type\":\"SQLDatabase\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"db\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"prompt\":{\"type\":\"BasePromptTemplate\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"SQLDatabaseChain\"},\"description\":\"Create a SQLDatabaseChain from an LLM and a database connection.\",\"base_classes\":[\"Runnable\",\"Chain\",\"Generic\",\"Text\",\"RunnableSerializable\",\"Serializable\",\"object\",\"SQLDatabaseChain\",\"Callable\"],\"display_name\":\"SQLDatabaseChain\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false,\"output_type\":\"Chain\"},\"CombineDocsChain\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"chain_type\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"stuff\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"stuff\",\"map_reduce\",\"map_rerank\",\"refine\"],\"name\":\"chain_type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"load_qa_chain\"},\"description\":\"Load question answering chain.\",\"base_classes\":[\"function\",\"BaseCombineDocumentsChain\"],\"display_name\":\"CombineDocsChain\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false,\"output_type\":\"Chain\"},\"SeriesCharacterChain\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"character\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"character\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"series\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"series\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"SeriesCharacterChain\"},\"description\":\"SeriesCharacterChain is a chain you can use to have a conversation with a character from a series.\",\"base_classes\":[\"Chain\",\"BaseCustomChain\",\"ConversationChain\",\"function\",\"SeriesCharacterChain\",\"LLMChain\"],\"display_name\":\"SeriesCharacterChain\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false,\"output_type\":\"Chain\"},\"MidJourneyPromptChain\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"memory\":{\"type\":\"BaseChatMemory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"MidJourneyPromptChain\"},\"description\":\"MidJourneyPromptChain is a chain you can use to generate new MidJourney prompts.\",\"base_classes\":[\"Chain\",\"BaseCustomChain\",\"MidJourneyPromptChain\",\"ConversationChain\",\"LLMChain\"],\"display_name\":\"MidJourneyPromptChain\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false,\"output_type\":\"Chain\"},\"TimeTravelGuideChain\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"memory\":{\"type\":\"BaseChatMemory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"TimeTravelGuideChain\"},\"description\":\"Time travel guide chain.\",\"base_classes\":[\"Chain\",\"BaseCustomChain\",\"ConversationChain\",\"TimeTravelGuideChain\",\"LLMChain\"],\"display_name\":\"TimeTravelGuideChain\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false,\"output_type\":\"Chain\"},\"LLMChain\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"memory\":{\"type\":\"BaseMemory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"prompt\":{\"type\":\"BasePromptTemplate\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"prompt\",\"display_name\":\"Prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain.chains import LLMChain\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import (\\n BaseLanguageModel,\\n BaseMemory,\\n BasePromptTemplate,\\n Text,\\n)\\n\\n\\nclass LLMChainComponent(CustomComponent):\\n display_name = \\\"LLMChain\\\"\\n description = \\\"Chain to run queries against LLMs\\\"\\n\\n def build_config(self):\\n return {\\n \\\"prompt\\\": {\\\"display_name\\\": \\\"Prompt\\\"},\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"memory\\\": {\\\"display_name\\\": \\\"Memory\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n prompt: BasePromptTemplate,\\n llm: BaseLanguageModel,\\n memory: Optional[BaseMemory] = None,\\n ) -> Text:\\n runnable = LLMChain(prompt=prompt, llm=llm, memory=memory)\\n result_dict = runnable.invoke({})\\n output_key = runnable.output_key\\n result = result_dict[output_key]\\n self.status = result\\n return result\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Chain to run queries against LLMs\",\"base_classes\":[\"Text\",\"object\"],\"display_name\":\"LLMChain\",\"documentation\":\"\",\"custom_fields\":{\"prompt\":null,\"llm\":null,\"memory\":null},\"output_types\":[\"Text\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"SQLGenerator\":{\"template\":{\"db\":{\"type\":\"SQLDatabase\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"db\",\"display_name\":\"Database\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"inputs\":{\"type\":\"Text\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"inputs\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"prompt\":{\"type\":\"PromptTemplate\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"prompt\",\"display_name\":\"Prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"The prompt must contain `{question}`.\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain.chains import create_sql_query_chain\\nfrom langchain_community.utilities.sql_database import SQLDatabase\\nfrom langchain_core.prompts import PromptTemplate\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import BaseLanguageModel, Text\\n\\n\\nclass SQLGeneratorComponent(CustomComponent):\\n display_name = \\\"Natural Language to SQL\\\"\\n description = \\\"Generate SQL from natural language.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"db\\\": {\\\"display_name\\\": \\\"Database\\\"},\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"prompt\\\": {\\n \\\"display_name\\\": \\\"Prompt\\\",\\n \\\"info\\\": \\\"The prompt must contain `{question}`.\\\",\\n },\\n \\\"top_k\\\": {\\n \\\"display_name\\\": \\\"Top K\\\",\\n \\\"info\\\": \\\"The number of results per select statement to return. If 0, no limit.\\\",\\n },\\n }\\n\\n def build(\\n self,\\n inputs: Text,\\n db: SQLDatabase,\\n llm: BaseLanguageModel,\\n top_k: int = 5,\\n prompt: Optional[PromptTemplate] = None,\\n ) -> Text:\\n if top_k > 0:\\n kwargs = {\\n \\\"k\\\": top_k,\\n }\\n if not prompt:\\n sql_query_chain = create_sql_query_chain(llm=llm, db=db, **kwargs)\\n else:\\n template = prompt.template if hasattr(prompt, \\\"template\\\") else prompt\\n # Check if {question} is in the prompt\\n if \\\"{question}\\\" not in template or \\\"question\\\" not in template.input_variables:\\n raise ValueError(\\\"Prompt must contain `{question}` to be used with Natural Language to SQL.\\\")\\n sql_query_chain = create_sql_query_chain(llm=llm, db=db, prompt=prompt, **kwargs)\\n query_writer = sql_query_chain | {\\\"query\\\": lambda x: x.replace(\\\"SQLQuery:\\\", \\\"\\\").strip()}\\n response = query_writer.invoke({\\\"question\\\": inputs})\\n query = response.get(\\\"query\\\")\\n self.status = query\\n return query\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"top_k\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":5,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_k\",\"display_name\":\"Top K\",\"advanced\":false,\"dynamic\":false,\"info\":\"The number of results per select statement to return. If 0, no limit.\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Generate SQL from natural language.\",\"base_classes\":[\"Text\",\"object\"],\"display_name\":\"Natural Language to SQL\",\"documentation\":\"\",\"custom_fields\":{\"inputs\":null,\"db\":null,\"llm\":null,\"top_k\":null,\"prompt\":null},\"output_types\":[\"Text\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"ConversationChain\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"memory\":{\"type\":\"BaseMemory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"Memory to load context from. If none is provided, a ConversationBufferMemory will be used.\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Callable, Optional, Union\\n\\nfrom langchain.chains import ConversationChain\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import BaseLanguageModel, BaseMemory, Chain, Text\\n\\n\\nclass ConversationChainComponent(CustomComponent):\\n display_name = \\\"ConversationChain\\\"\\n description = \\\"Chain to have a conversation and load context from memory.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"prompt\\\": {\\\"display_name\\\": \\\"Prompt\\\"},\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"memory\\\": {\\n \\\"display_name\\\": \\\"Memory\\\",\\n \\\"info\\\": \\\"Memory to load context from. If none is provided, a ConversationBufferMemory will be used.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n inputs: str,\\n llm: BaseLanguageModel,\\n memory: Optional[BaseMemory] = None,\\n ) -> Union[Chain, Callable, Text]:\\n if memory is None:\\n chain = ConversationChain(llm=llm)\\n else:\\n chain = ConversationChain(llm=llm, memory=memory)\\n result = chain.invoke(inputs)\\n # result is an AIMessage which is a subclass of BaseMessage\\n # We need to check if it is a string or a BaseMessage\\n if hasattr(result, \\\"content\\\") and isinstance(result.content, str):\\n self.status = \\\"is message\\\"\\n result = result.content\\n elif isinstance(result, str):\\n self.status = \\\"is_string\\\"\\n result = result\\n else:\\n # is dict\\n result = result.get(\\\"response\\\")\\n self.status = result\\n return result\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"inputs\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"inputs\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Chain to have a conversation and load context from memory.\",\"base_classes\":[\"Runnable\",\"Chain\",\"Generic\",\"Text\",\"RunnableSerializable\",\"Serializable\",\"object\",\"Callable\"],\"display_name\":\"ConversationChain\",\"documentation\":\"\",\"custom_fields\":{\"inputs\":null,\"llm\":null,\"memory\":null},\"output_types\":[\"Chain\",\"Callable\",\"Text\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true}},\"agents\":{\"ZeroShotAgent\":{\"template\":{\"callback_manager\":{\"type\":\"BaseCallbackManager\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"callback_manager\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"output_parser\":{\"type\":\"AgentOutputParser\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"output_parser\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"tools\":{\"type\":\"BaseTool\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"tools\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"format_instructions\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":true,\"value\":\"Use the following format:\\n\\nQuestion: the input question you must answer\\nThought: you should always think about what to do\\nAction: the action to take, should be one of [{tool_names}]\\nAction Input: the input to the action\\nObservation: the result of the action\\n... (this Thought/Action/Action Input/Observation can repeat N times)\\nThought: I now know the final answer\\nFinal Answer: the final answer to the original input question\",\"fileTypes\":[],\"password\":false,\"name\":\"format_instructions\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"input_variables\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"input_variables\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"prefix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"Answer the following questions as best you can. You have access to the following tools:\",\"fileTypes\":[],\"password\":false,\"name\":\"prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"suffix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"Begin!\\n\\nQuestion: {input}\\nThought:{agent_scratchpad}\",\"fileTypes\":[],\"password\":false,\"name\":\"suffix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"ZeroShotAgent\"},\"description\":\"Construct an agent from an LLM and tools.\",\"base_classes\":[\"ZeroShotAgent\",\"Callable\",\"BaseSingleActionAgent\",\"Agent\"],\"display_name\":\"ZeroShotAgent\",\"documentation\":\"https://python.langchain.com/docs/modules/agents/how_to/custom_mrkl_agent\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"JsonAgent\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"toolkit\":{\"type\":\"JsonToolkit\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"toolkit\",\"display_name\":\"Toolkit\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langchain.agents import AgentExecutor, create_json_agent\\nfrom langflow.field_typing import (\\n BaseLanguageModel,\\n)\\nfrom langchain_community.agent_toolkits.json.toolkit import JsonToolkit\\n\\n\\nclass JsonAgentComponent(CustomComponent):\\n display_name = \\\"JsonAgent\\\"\\n description = \\\"Construct a json agent from an LLM and tools.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"toolkit\\\": {\\\"display_name\\\": \\\"Toolkit\\\"},\\n }\\n\\n def build(\\n self,\\n llm: BaseLanguageModel,\\n toolkit: JsonToolkit,\\n ) -> AgentExecutor:\\n return create_json_agent(llm=llm, toolkit=toolkit)\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Construct a json agent from an LLM and tools.\",\"base_classes\":[\"Runnable\",\"Chain\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"AgentExecutor\",\"object\"],\"display_name\":\"JsonAgent\",\"documentation\":\"\",\"custom_fields\":{\"llm\":null,\"toolkit\":null},\"output_types\":[\"AgentExecutor\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"CSVAgent\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[\".csv\"],\"file_path\":\"\",\"password\":false,\"name\":\"path\",\"display_name\":\"Path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import BaseLanguageModel, AgentExecutor\\nfrom langchain_experimental.agents.agent_toolkits.csv.base import create_csv_agent\\n\\n\\nclass CSVAgentComponent(CustomComponent):\\n display_name = \\\"CSVAgent\\\"\\n description = \\\"Construct a CSV agent from a CSV and tools.\\\"\\n documentation = \\\"https://python.langchain.com/docs/modules/agents/toolkits/csv\\\"\\n\\n def build_config(self):\\n return {\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\", \\\"type\\\": BaseLanguageModel},\\n \\\"path\\\": {\\\"display_name\\\": \\\"Path\\\", \\\"field_type\\\": \\\"file\\\", \\\"suffixes\\\": [\\\".csv\\\"], \\\"file_types\\\": [\\\".csv\\\"]},\\n }\\n\\n def build(\\n self,\\n llm: BaseLanguageModel,\\n path: str,\\n ) -> AgentExecutor:\\n # Instantiate and return the CSV agent class with the provided llm and path\\n return create_csv_agent(llm=llm, path=path)\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Construct a CSV agent from a CSV and tools.\",\"base_classes\":[\"Runnable\",\"Chain\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"AgentExecutor\",\"object\"],\"display_name\":\"CSVAgent\",\"documentation\":\"https://python.langchain.com/docs/modules/agents/toolkits/csv\",\"custom_fields\":{\"llm\":null,\"path\":null},\"output_types\":[\"AgentExecutor\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"VectorStoreAgent\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"vector_store_toolkit\":{\"type\":\"VectorStoreToolkit\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"vector_store_toolkit\",\"display_name\":\"Vector Store Info\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langchain.agents import AgentExecutor, create_vectorstore_agent\\nfrom langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreToolkit\\nfrom typing import Union, Callable\\nfrom langflow.field_typing import BaseLanguageModel\\n\\n\\nclass VectorStoreAgentComponent(CustomComponent):\\n display_name = \\\"VectorStoreAgent\\\"\\n description = \\\"Construct an agent from a Vector Store.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"vector_store_toolkit\\\": {\\\"display_name\\\": \\\"Vector Store Info\\\"},\\n }\\n\\n def build(\\n self,\\n llm: BaseLanguageModel,\\n vector_store_toolkit: VectorStoreToolkit,\\n ) -> Union[AgentExecutor, Callable]:\\n return create_vectorstore_agent(llm=llm, toolkit=vector_store_toolkit)\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Construct an agent from a Vector Store.\",\"base_classes\":[\"Runnable\",\"Chain\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"AgentExecutor\",\"object\",\"Callable\"],\"display_name\":\"VectorStoreAgent\",\"documentation\":\"\",\"custom_fields\":{\"llm\":null,\"vector_store_toolkit\":null},\"output_types\":[\"AgentExecutor\",\"Callable\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"VectorStoreRouterAgent\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"vectorstoreroutertoolkit\":{\"type\":\"VectorStoreRouterToolkit\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"vectorstoreroutertoolkit\",\"display_name\":\"Vector Store Router Toolkit\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langchain_core.language_models.base import BaseLanguageModel\\nfrom langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreRouterToolkit\\nfrom langchain.agents import create_vectorstore_router_agent\\nfrom typing import Callable\\n\\n\\nclass VectorStoreRouterAgentComponent(CustomComponent):\\n display_name = \\\"VectorStoreRouterAgent\\\"\\n description = \\\"Construct an agent from a Vector Store Router.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"vectorstoreroutertoolkit\\\": {\\\"display_name\\\": \\\"Vector Store Router Toolkit\\\"},\\n }\\n\\n def build(self, llm: BaseLanguageModel, vectorstoreroutertoolkit: VectorStoreRouterToolkit) -> Callable:\\n return create_vectorstore_router_agent(llm=llm, toolkit=vectorstoreroutertoolkit)\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Construct an agent from a Vector Store Router.\",\"base_classes\":[\"Callable\"],\"display_name\":\"VectorStoreRouterAgent\",\"documentation\":\"\",\"custom_fields\":{\"llm\":null,\"vectorstoreroutertoolkit\":null},\"output_types\":[\"Callable\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"SQLAgent\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom typing import Union, Callable\\nfrom langchain.agents import AgentExecutor\\nfrom langflow.field_typing import BaseLanguageModel\\nfrom langchain_community.agent_toolkits.sql.base import create_sql_agent\\nfrom langchain.sql_database import SQLDatabase\\nfrom langchain_community.agent_toolkits import SQLDatabaseToolkit\\n\\n\\nclass SQLAgentComponent(CustomComponent):\\n display_name = \\\"SQLAgent\\\"\\n description = \\\"Construct an SQL agent from an LLM and tools.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"database_uri\\\": {\\\"display_name\\\": \\\"Database URI\\\"},\\n \\\"verbose\\\": {\\\"display_name\\\": \\\"Verbose\\\", \\\"value\\\": False, \\\"advanced\\\": True},\\n }\\n\\n def build(\\n self,\\n llm: BaseLanguageModel,\\n database_uri: str,\\n verbose: bool = False,\\n ) -> Union[AgentExecutor, Callable]:\\n db = SQLDatabase.from_uri(database_uri)\\n toolkit = SQLDatabaseToolkit(db=db, llm=llm)\\n return create_sql_agent(llm=llm, toolkit=toolkit)\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"database_uri\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"database_uri\",\"display_name\":\"Database URI\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"verbose\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"verbose\",\"display_name\":\"Verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Construct an SQL agent from an LLM and tools.\",\"base_classes\":[\"Runnable\",\"Chain\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"AgentExecutor\",\"object\",\"Callable\"],\"display_name\":\"SQLAgent\",\"documentation\":\"\",\"custom_fields\":{\"llm\":null,\"database_uri\":null,\"verbose\":null},\"output_types\":[\"AgentExecutor\",\"Callable\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"OpenAIConversationalAgent\":{\"template\":{\"memory\":{\"type\":\"BaseMemory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"system_message\":{\"type\":\"SystemMessagePromptTemplate\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"system_message\",\"display_name\":\"System Message\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"tools\":{\"type\":\"Tool\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tools\",\"display_name\":\"Tools\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import List, Optional\\n\\nfrom langchain.agents.agent import AgentExecutor\\nfrom langchain.agents.agent_toolkits.conversational_retrieval.openai_functions import _get_default_system_message\\nfrom langchain.agents.openai_functions_agent.base import OpenAIFunctionsAgent\\nfrom langchain.memory.token_buffer import ConversationTokenBufferMemory\\nfrom langchain.prompts import SystemMessagePromptTemplate\\nfrom langchain.prompts.chat import MessagesPlaceholder\\nfrom langchain.schema.memory import BaseMemory\\nfrom langchain.tools import Tool\\nfrom langchain_community.chat_models import ChatOpenAI\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing.range_spec import RangeSpec\\n\\n\\nclass ConversationalAgent(CustomComponent):\\n display_name: str = \\\"OpenAI Conversational Agent\\\"\\n description: str = \\\"Conversational Agent that can use OpenAI's function calling API\\\"\\n\\n def build_config(self):\\n openai_function_models = [\\n \\\"gpt-4-turbo-preview\\\",\\n \\\"gpt-4-0125-preview\\\",\\n \\\"gpt-4-1106-preview\\\",\\n \\\"gpt-4-vision-preview\\\",\\n \\\"gpt-3.5-turbo-0125\\\",\\n \\\"gpt-3.5-turbo-1106\\\",\\n ]\\n return {\\n \\\"tools\\\": {\\\"display_name\\\": \\\"Tools\\\"},\\n \\\"memory\\\": {\\\"display_name\\\": \\\"Memory\\\"},\\n \\\"system_message\\\": {\\\"display_name\\\": \\\"System Message\\\"},\\n \\\"max_token_limit\\\": {\\\"display_name\\\": \\\"Max Token Limit\\\"},\\n \\\"model_name\\\": {\\n \\\"display_name\\\": \\\"Model Name\\\",\\n \\\"options\\\": openai_function_models,\\n \\\"value\\\": openai_function_models[0],\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"value\\\": 0.2,\\n \\\"range_spec\\\": RangeSpec(min=0, max=2, step=0.1),\\n },\\n }\\n\\n def build(\\n self,\\n model_name: str,\\n openai_api_key: str,\\n tools: List[Tool],\\n openai_api_base: Optional[str] = None,\\n memory: Optional[BaseMemory] = None,\\n system_message: Optional[SystemMessagePromptTemplate] = None,\\n max_token_limit: int = 2000,\\n temperature: float = 0.9,\\n ) -> AgentExecutor:\\n llm = ChatOpenAI(\\n model=model_name,\\n api_key=openai_api_key,\\n base_url=openai_api_base,\\n max_tokens=max_token_limit,\\n temperature=temperature,\\n )\\n if not memory:\\n memory_key = \\\"chat_history\\\"\\n memory = ConversationTokenBufferMemory(\\n memory_key=memory_key,\\n return_messages=True,\\n output_key=\\\"output\\\",\\n llm=llm,\\n max_token_limit=max_token_limit,\\n )\\n else:\\n memory_key = memory.memory_key # type: ignore\\n\\n _system_message = system_message or _get_default_system_message()\\n prompt = OpenAIFunctionsAgent.create_prompt(\\n system_message=_system_message, # type: ignore\\n extra_prompt_messages=[MessagesPlaceholder(variable_name=memory_key)],\\n )\\n agent = OpenAIFunctionsAgent(\\n llm=llm,\\n tools=tools,\\n prompt=prompt, # type: ignore\\n )\\n return AgentExecutor(\\n agent=agent,\\n tools=tools, # type: ignore\\n memory=memory,\\n verbose=True,\\n return_intermediate_steps=True,\\n handle_parsing_errors=True,\\n )\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"max_token_limit\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":2000,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_token_limit\",\"display_name\":\"Max Token Limit\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"model_name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"gpt-4-turbo-preview\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"gpt-4-turbo-preview\",\"gpt-4-0125-preview\",\"gpt-4-1106-preview\",\"gpt-4-vision-preview\",\"gpt-3.5-turbo-0125\",\"gpt-3.5-turbo-1106\"],\"name\":\"model_name\",\"display_name\":\"Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"openai_api_base\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"openai_api_base\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"openai_api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"openai_api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"temperature\":{\"type\":\"float\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.2,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":0.0,\"max\":2.0,\"step\":0.1},\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Conversational Agent that can use OpenAI's function calling API\",\"base_classes\":[\"Runnable\",\"Chain\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"AgentExecutor\",\"object\"],\"display_name\":\"OpenAI Conversational Agent\",\"documentation\":\"\",\"custom_fields\":{\"model_name\":null,\"openai_api_key\":null,\"tools\":null,\"openai_api_base\":null,\"memory\":null,\"system_message\":null,\"max_token_limit\":null,\"temperature\":null},\"output_types\":[\"AgentExecutor\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"AgentInitializer\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"Language Model\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"memory\":{\"type\":\"BaseChatMemory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"memory\",\"display_name\":\"Memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"tools\":{\"type\":\"Tool\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tools\",\"display_name\":\"Tools\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"agent\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"zero-shot-react-description\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"zero-shot-react-description\",\"react-docstore\",\"self-ask-with-search\",\"conversational-react-description\",\"chat-zero-shot-react-description\",\"chat-conversational-react-description\",\"structured-chat-zero-shot-react-description\",\"openai-functions\",\"openai-multi-functions\",\"JsonAgent\",\"CSVAgent\",\"VectorStoreAgent\",\"VectorStoreRouterAgent\",\"SQLAgent\"],\"name\":\"agent\",\"display_name\":\"Agent Type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Callable, List, Optional, Union\\n\\nfrom langchain.agents import AgentExecutor, AgentType, initialize_agent, types\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import BaseChatMemory, BaseLanguageModel, Tool\\n\\n\\nclass AgentInitializerComponent(CustomComponent):\\n display_name: str = \\\"Agent Initializer\\\"\\n description: str = \\\"Initialize a Langchain Agent.\\\"\\n documentation: str = \\\"https://python.langchain.com/docs/modules/agents/agent_types/\\\"\\n\\n def build_config(self):\\n agents = list(types.AGENT_TO_CLASS.keys())\\n # field_type and required are optional\\n return {\\n \\\"agent\\\": {\\\"options\\\": agents, \\\"value\\\": agents[0], \\\"display_name\\\": \\\"Agent Type\\\"},\\n \\\"max_iterations\\\": {\\\"display_name\\\": \\\"Max Iterations\\\", \\\"value\\\": 10},\\n \\\"memory\\\": {\\\"display_name\\\": \\\"Memory\\\"},\\n \\\"tools\\\": {\\\"display_name\\\": \\\"Tools\\\"},\\n \\\"llm\\\": {\\\"display_name\\\": \\\"Language Model\\\"},\\n \\\"code\\\": {\\\"advanced\\\": True},\\n }\\n\\n def build(\\n self,\\n agent: str,\\n llm: BaseLanguageModel,\\n tools: List[Tool],\\n max_iterations: int,\\n memory: Optional[BaseChatMemory] = None,\\n ) -> Union[AgentExecutor, Callable]:\\n agent = AgentType(agent)\\n if memory:\\n return initialize_agent(\\n tools=tools,\\n llm=llm,\\n agent=agent,\\n memory=memory,\\n return_intermediate_steps=True,\\n handle_parsing_errors=True,\\n max_iterations=max_iterations,\\n )\\n return initialize_agent(\\n tools=tools,\\n llm=llm,\\n agent=agent,\\n return_intermediate_steps=True,\\n handle_parsing_errors=True,\\n max_iterations=max_iterations,\\n )\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"max_iterations\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":10,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_iterations\",\"display_name\":\"Max Iterations\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Initialize a Langchain Agent.\",\"base_classes\":[\"Runnable\",\"Chain\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"AgentExecutor\",\"object\",\"Callable\"],\"display_name\":\"Agent Initializer\",\"documentation\":\"https://python.langchain.com/docs/modules/agents/agent_types/\",\"custom_fields\":{\"agent\":null,\"llm\":null,\"tools\":null,\"max_iterations\":null,\"memory\":null},\"output_types\":[\"AgentExecutor\",\"Callable\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true}},\"memories\":{\"ConversationBufferMemory\":{\"template\":{\"chat_memory\":{\"type\":\"BaseChatMessageHistory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"chat_memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"ai_prefix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"AI\",\"fileTypes\":[],\"password\":false,\"name\":\"ai_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"human_prefix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"Human\",\"fileTypes\":[],\"password\":false,\"name\":\"human_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"input_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"input_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Input when more than one variable is available.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"memory_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"chat_history\",\"fileTypes\":[],\"password\":false,\"name\":\"memory_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"output_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"output_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Output (e.g. answer in a ConversationalRetrievalChain)\",\"title_case\":false,\"input_types\":[\"Text\"]},\"return_messages\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"return_messages\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"ConversationBufferMemory\"},\"description\":\"Buffer for storing conversation memory.\",\"base_classes\":[\"BaseMemory\",\"BaseChatMemory\",\"ConversationBufferMemory\",\"Serializable\"],\"display_name\":\"ConversationBufferMemory\",\"documentation\":\"https://python.langchain.com/docs/modules/memory/how_to/buffer\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":true,\"beta\":false},\"ConversationBufferWindowMemory\":{\"template\":{\"chat_memory\":{\"type\":\"BaseChatMessageHistory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"chat_memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"ai_prefix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"AI\",\"fileTypes\":[],\"password\":false,\"name\":\"ai_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"human_prefix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"Human\",\"fileTypes\":[],\"password\":false,\"name\":\"human_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"input_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"input_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Input when more than one variable is available.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"k\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":10,\"fileTypes\":[],\"password\":false,\"name\":\"k\",\"display_name\":\"Memory Size\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"memory_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"chat_history\",\"fileTypes\":[],\"password\":false,\"name\":\"memory_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"output_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"output_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Output (e.g. answer in a ConversationalRetrievalChain)\",\"title_case\":false,\"input_types\":[\"Text\"]},\"return_messages\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"return_messages\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"ConversationBufferWindowMemory\"},\"description\":\"Buffer for storing conversation memory inside a limited size window.\",\"base_classes\":[\"ConversationBufferWindowMemory\",\"BaseMemory\",\"BaseChatMemory\",\"Serializable\"],\"display_name\":\"ConversationBufferWindowMemory\",\"documentation\":\"https://python.langchain.com/docs/modules/memory/how_to/buffer_window\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":true,\"beta\":false},\"ConversationEntityMemory\":{\"template\":{\"chat_memory\":{\"type\":\"BaseChatMessageHistory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"chat_memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"entity_extraction_prompt\":{\"type\":\"BasePromptTemplate\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"entity_extraction_prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"entity_store\":{\"type\":\"BaseEntityStore\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"entity_store\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"entity_summarization_prompt\":{\"type\":\"BasePromptTemplate\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"entity_summarization_prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"ai_prefix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"AI\",\"fileTypes\":[],\"password\":false,\"name\":\"ai_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"chat_history_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"history\",\"fileTypes\":[],\"password\":false,\"name\":\"chat_history_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"entity_cache\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"entity_cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"human_prefix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"Human\",\"fileTypes\":[],\"password\":false,\"name\":\"human_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"input_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"input_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Input when more than one variable is available.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"k\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":10,\"fileTypes\":[],\"password\":false,\"name\":\"k\",\"display_name\":\"Memory Size\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"output_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"output_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Output (e.g. answer in a ConversationalRetrievalChain)\",\"title_case\":false,\"input_types\":[\"Text\"]},\"return_messages\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"return_messages\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"ConversationEntityMemory\"},\"description\":\"Entity extractor & summarizer memory.\",\"base_classes\":[\"ConversationEntityMemory\",\"BaseMemory\",\"BaseChatMemory\",\"Serializable\"],\"display_name\":\"ConversationEntityMemory\",\"documentation\":\"https://python.langchain.com/docs/modules/memory/integrations/entity_memory_with_sqlite\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":true,\"beta\":false},\"ConversationKGMemory\":{\"template\":{\"chat_memory\":{\"type\":\"BaseChatMessageHistory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"chat_memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"entity_extraction_prompt\":{\"type\":\"BasePromptTemplate\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"entity_extraction_prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"kg\":{\"type\":\"NetworkxEntityGraph\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"kg\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"knowledge_extraction_prompt\":{\"type\":\"BasePromptTemplate\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"knowledge_extraction_prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"summary_message_cls\":{\"type\":\"Type[langchain_core.messages.base.BaseMessage]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"summary_message_cls\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"ai_prefix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"AI\",\"fileTypes\":[],\"password\":false,\"name\":\"ai_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"human_prefix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"Human\",\"fileTypes\":[],\"password\":false,\"name\":\"human_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"input_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"input_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Input when more than one variable is available.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"k\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":10,\"fileTypes\":[],\"password\":false,\"name\":\"k\",\"display_name\":\"Memory Size\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"memory_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"chat_history\",\"fileTypes\":[],\"password\":false,\"name\":\"memory_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"output_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"output_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Output (e.g. answer in a ConversationalRetrievalChain)\",\"title_case\":false,\"input_types\":[\"Text\"]},\"return_messages\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"return_messages\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"ConversationKGMemory\"},\"description\":\"Knowledge graph conversation memory.\",\"base_classes\":[\"BaseChatMemory\",\"BaseMemory\",\"ConversationKGMemory\",\"Serializable\"],\"display_name\":\"ConversationKGMemory\",\"documentation\":\"https://python.langchain.com/docs/modules/memory/how_to/kg\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":true,\"beta\":false},\"ConversationSummaryMemory\":{\"template\":{\"chat_memory\":{\"type\":\"BaseChatMessageHistory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"chat_memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"prompt\":{\"type\":\"BasePromptTemplate\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"summary_message_cls\":{\"type\":\"Type[langchain_core.messages.base.BaseMessage]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"summary_message_cls\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"ai_prefix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"AI\",\"fileTypes\":[],\"password\":false,\"name\":\"ai_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"buffer\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"password\":false,\"name\":\"buffer\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"human_prefix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"Human\",\"fileTypes\":[],\"password\":false,\"name\":\"human_prefix\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"input_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"input_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Input when more than one variable is available.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"memory_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"chat_history\",\"fileTypes\":[],\"password\":false,\"name\":\"memory_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"output_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"output_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Output (e.g. answer in a ConversationalRetrievalChain)\",\"title_case\":false,\"input_types\":[\"Text\"]},\"return_messages\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"return_messages\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"ConversationSummaryMemory\"},\"description\":\"Conversation summarizer to chat memory.\",\"base_classes\":[\"BaseChatMemory\",\"Serializable\",\"ConversationSummaryMemory\",\"BaseMemory\",\"SummarizerMixin\"],\"display_name\":\"ConversationSummaryMemory\",\"documentation\":\"https://python.langchain.com/docs/modules/memory/how_to/summary\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":true,\"beta\":false},\"MongoDBChatMessageHistory\":{\"template\":{\"collection_name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"message_store\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"collection_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"connection_string\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"connection_string\",\"advanced\":false,\"dynamic\":false,\"info\":\"MongoDB connection string (e.g mongodb://mongo_user:password123@mongo:27017)\",\"title_case\":false,\"input_types\":[\"Text\"]},\"database_name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"chat_history\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"database_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"session_id\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"session_id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"MongoDBChatMessageHistory\"},\"description\":\"Memory store with MongoDB\",\"base_classes\":[\"BaseChatMessageHistory\",\"MongoDBChatMessageHistory\"],\"display_name\":\"MongoDBChatMessageHistory\",\"documentation\":\"https://python.langchain.com/docs/modules/memory/integrations/mongodb_chat_message_history\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":true,\"beta\":false},\"MotorheadMemory\":{\"template\":{\"chat_memory\":{\"type\":\"BaseChatMessageHistory\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"chat_memory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"api_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"client_id\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"client_id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"context\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"context\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"input_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"input_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Input when more than one variable is available.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"memory_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"chat_history\",\"fileTypes\":[],\"password\":false,\"name\":\"memory_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"output_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"output_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Output (e.g. answer in a ConversationalRetrievalChain)\",\"title_case\":false,\"input_types\":[\"Text\"]},\"return_messages\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"return_messages\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"session_id\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"session_id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"timeout\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"url\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"https://api.getmetal.io/v1/motorhead\",\"fileTypes\":[],\"password\":false,\"name\":\"url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"MotorheadMemory\"},\"description\":\"Chat message memory backed by Motorhead service.\",\"base_classes\":[\"MotorheadMemory\",\"BaseChatMemory\",\"BaseMemory\",\"Serializable\"],\"display_name\":\"MotorheadMemory\",\"documentation\":\"https://python.langchain.com/docs/integrations/memory/motorhead_memory\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":true,\"beta\":false},\"PostgresChatMessageHistory\":{\"template\":{\"connection_string\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"postgresql://postgres:mypassword@localhost/chat_history\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"connection_string\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"session_id\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"session_id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"table_name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"message_store\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"table_name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"PostgresChatMessageHistory\"},\"description\":\"Memory store with Postgres\",\"base_classes\":[\"BaseChatMessageHistory\",\"PostgresChatMessageHistory\"],\"display_name\":\"PostgresChatMessageHistory\",\"documentation\":\"https://python.langchain.com/docs/modules/memory/integrations/postgres_chat_message_history\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":true,\"beta\":false},\"VectorStoreRetrieverMemory\":{\"template\":{\"retriever\":{\"type\":\"VectorStoreRetriever\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"retriever\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"exclude_input_keys\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"exclude_input_keys\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"input_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"input_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The variable to be used as Chat Input when more than one variable is available.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"memory_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"chat_history\",\"fileTypes\":[],\"password\":false,\"name\":\"memory_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"return_docs\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"return_docs\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"return_messages\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"return_messages\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"VectorStoreRetrieverMemory\"},\"description\":\"VectorStoreRetriever-backed memory.\",\"base_classes\":[\"BaseMemory\",\"VectorStoreRetrieverMemory\",\"Serializable\"],\"display_name\":\"VectorStoreRetrieverMemory\",\"documentation\":\"https://python.langchain.com/docs/modules/memory/how_to/vectorstore_retriever_memory\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":true,\"beta\":false}},\"tools\":{\"Calculator\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"Calculator\"},\"description\":\"Useful for when you need to answer questions about math.\",\"base_classes\":[\"BaseTool\",\"Tool\"],\"display_name\":\"Calculator\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"Search\":{\"template\":{\"aiosession\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"aiosession\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"serpapi_api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"serpapi_api_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"Search\"},\"description\":\"A search engine. Useful for when you need to answer questions about current events. Input should be a search query.\",\"base_classes\":[\"BaseTool\",\"Tool\"],\"display_name\":\"Search\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"Tool\":{\"template\":{\"func\":{\"type\":\"Callable\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"func\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"description\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"description\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"return_direct\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"return_direct\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"Tool\"},\"description\":\"Converts a chain, agent or function into a tool.\",\"base_classes\":[\"BaseTool\",\"Tool\"],\"display_name\":\"Tool\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"PythonFunctionTool\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"\\ndef python_function(text: str) -> str:\\n \\\"\\\"\\\"This is a default python function that returns the input text\\\"\\\"\\\"\\n return text\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"description\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"description\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"return_direct\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"return_direct\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"PythonFunctionTool\"},\"description\":\"Python function to be executed.\",\"base_classes\":[\"BaseTool\",\"Tool\"],\"display_name\":\"PythonFunctionTool\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"PythonFunction\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"\\ndef python_function(text: str) -> str:\\n \\\"\\\"\\\"This is a default python function that returns the input text\\\"\\\"\\\"\\n return text\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"PythonFunction\"},\"description\":\"Python function to be executed.\",\"base_classes\":[\"Callable\"],\"display_name\":\"PythonFunction\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"JsonSpec\":{\"template\":{\"path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".json\",\".yaml\",\".yml\"],\"file_path\":\"\",\"password\":false,\"name\":\"path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"max_value_length\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_value_length\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"JsonSpec\"},\"description\":\"\",\"base_classes\":[\"JsonSpec\",\"BaseTool\",\"Tool\"],\"display_name\":\"JsonSpec\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"BingSearchRun\":{\"template\":{\"api_wrapper\":{\"type\":\"BingSearchAPIWrapper\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"api_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_validation_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_validation_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"BingSearchRun\"},\"description\":\"\",\"base_classes\":[\"Runnable\",\"BingSearchRun\",\"Generic\",\"BaseTool\",\"RunnableSerializable\",\"Tool\",\"Serializable\",\"object\"],\"display_name\":\"BingSearchRun\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"GoogleSearchResults\":{\"template\":{\"api_wrapper\":{\"type\":\"GoogleSearchAPIWrapper\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"api_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_validation_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_validation_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"num_results\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":4,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"num_results\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"GoogleSearchResults\"},\"description\":\"\",\"base_classes\":[\"GoogleSearchResults\",\"Runnable\",\"Generic\",\"BaseTool\",\"RunnableSerializable\",\"Tool\",\"Serializable\",\"object\"],\"display_name\":\"GoogleSearchResults\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"GoogleSearchRun\":{\"template\":{\"api_wrapper\":{\"type\":\"GoogleSearchAPIWrapper\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"api_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_validation_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_validation_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"GoogleSearchRun\"},\"description\":\"\",\"base_classes\":[\"Runnable\",\"Generic\",\"BaseTool\",\"RunnableSerializable\",\"Tool\",\"GoogleSearchRun\",\"Serializable\",\"object\"],\"display_name\":\"GoogleSearchRun\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"GoogleSerperRun\":{\"template\":{\"api_wrapper\":{\"type\":\"GoogleSerperAPIWrapper\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"api_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_validation_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_validation_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"GoogleSerperRun\"},\"description\":\"\",\"base_classes\":[\"Runnable\",\"Generic\",\"BaseTool\",\"RunnableSerializable\",\"Tool\",\"Serializable\",\"GoogleSerperRun\",\"object\"],\"display_name\":\"GoogleSerperRun\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"InfoSQLDatabaseTool\":{\"template\":{\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"db\":{\"type\":\"SQLDatabase\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"db\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_validation_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_validation_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"InfoSQLDatabaseTool\"},\"description\":\"\",\"base_classes\":[\"InfoSQLDatabaseTool\",\"Runnable\",\"BaseSQLDatabaseTool\",\"Generic\",\"BaseTool\",\"RunnableSerializable\",\"Tool\",\"Serializable\",\"object\"],\"display_name\":\"InfoSQLDatabaseTool\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"JsonGetValueTool\":{\"template\":{\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"spec\":{\"type\":\"JsonSpec\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"spec\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_validation_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_validation_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"JsonGetValueTool\"},\"description\":\"\",\"base_classes\":[\"Runnable\",\"Generic\",\"BaseTool\",\"RunnableSerializable\",\"Tool\",\"Serializable\",\"object\",\"JsonGetValueTool\"],\"display_name\":\"JsonGetValueTool\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"JsonListKeysTool\":{\"template\":{\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"spec\":{\"type\":\"JsonSpec\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"spec\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_validation_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_validation_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"JsonListKeysTool\"},\"description\":\"\",\"base_classes\":[\"Runnable\",\"Generic\",\"BaseTool\",\"RunnableSerializable\",\"Tool\",\"Serializable\",\"object\",\"JsonListKeysTool\"],\"display_name\":\"JsonListKeysTool\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"ListSQLDatabaseTool\":{\"template\":{\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"db\":{\"type\":\"SQLDatabase\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"db\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_validation_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_validation_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"ListSQLDatabaseTool\"},\"description\":\"\",\"base_classes\":[\"Runnable\",\"BaseSQLDatabaseTool\",\"Generic\",\"BaseTool\",\"RunnableSerializable\",\"Tool\",\"Serializable\",\"object\",\"ListSQLDatabaseTool\"],\"display_name\":\"ListSQLDatabaseTool\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"QuerySQLDataBaseTool\":{\"template\":{\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"db\":{\"type\":\"SQLDatabase\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"db\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_validation_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_validation_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"QuerySQLDataBaseTool\"},\"description\":\"\",\"base_classes\":[\"Runnable\",\"BaseSQLDatabaseTool\",\"Generic\",\"BaseTool\",\"RunnableSerializable\",\"Tool\",\"QuerySQLDataBaseTool\",\"Serializable\",\"object\"],\"display_name\":\"QuerySQLDataBaseTool\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"RequestsDeleteTool\":{\"template\":{\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"requests_wrapper\":{\"type\":\"GenericRequestsWrapper\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"requests_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_validation_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_validation_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"RequestsDeleteTool\"},\"description\":\"\",\"base_classes\":[\"Runnable\",\"Generic\",\"BaseTool\",\"RunnableSerializable\",\"Tool\",\"Serializable\",\"object\",\"RequestsDeleteTool\",\"BaseRequestsTool\"],\"display_name\":\"RequestsDeleteTool\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"RequestsGetTool\":{\"template\":{\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"requests_wrapper\":{\"type\":\"GenericRequestsWrapper\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"requests_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_validation_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_validation_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"RequestsGetTool\"},\"description\":\"\",\"base_classes\":[\"Runnable\",\"Generic\",\"BaseTool\",\"RunnableSerializable\",\"Tool\",\"Serializable\",\"object\",\"RequestsGetTool\",\"BaseRequestsTool\"],\"display_name\":\"RequestsGetTool\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"RequestsPatchTool\":{\"template\":{\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"requests_wrapper\":{\"type\":\"GenericRequestsWrapper\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"requests_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_validation_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_validation_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"RequestsPatchTool\"},\"description\":\"\",\"base_classes\":[\"Runnable\",\"RequestsPatchTool\",\"Generic\",\"BaseTool\",\"RunnableSerializable\",\"Tool\",\"Serializable\",\"object\",\"BaseRequestsTool\"],\"display_name\":\"RequestsPatchTool\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"RequestsPostTool\":{\"template\":{\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"requests_wrapper\":{\"type\":\"GenericRequestsWrapper\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"requests_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_validation_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_validation_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"RequestsPostTool\"},\"description\":\"\",\"base_classes\":[\"Runnable\",\"Generic\",\"BaseTool\",\"RunnableSerializable\",\"Tool\",\"Serializable\",\"RequestsPostTool\",\"object\",\"BaseRequestsTool\"],\"display_name\":\"RequestsPostTool\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"RequestsPutTool\":{\"template\":{\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"requests_wrapper\":{\"type\":\"GenericRequestsWrapper\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"requests_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_validation_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_validation_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"RequestsPutTool\"},\"description\":\"\",\"base_classes\":[\"RequestsPutTool\",\"Runnable\",\"Generic\",\"BaseTool\",\"RunnableSerializable\",\"Tool\",\"Serializable\",\"object\",\"BaseRequestsTool\"],\"display_name\":\"RequestsPutTool\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"WikipediaQueryRun\":{\"template\":{\"api_wrapper\":{\"type\":\"WikipediaAPIWrapper\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"api_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_validation_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_validation_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"WikipediaQueryRun\"},\"description\":\"\",\"base_classes\":[\"Runnable\",\"Generic\",\"BaseTool\",\"RunnableSerializable\",\"Tool\",\"WikipediaQueryRun\",\"Serializable\",\"object\"],\"display_name\":\"WikipediaQueryRun\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"WolframAlphaQueryRun\":{\"template\":{\"api_wrapper\":{\"type\":\"WolframAlphaAPIWrapper\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"api_wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"args_schema\":{\"type\":\"Type[pydantic.v1.main.BaseModel]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"args_schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"callbacks\":{\"type\":\"langchain_core.callbacks.base.BaseCallbackHandler\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"callbacks\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_tool_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_tool_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"handle_validation_error\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"handle_validation_error\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"WolframAlphaQueryRun\"},\"description\":\"\",\"base_classes\":[\"Runnable\",\"WolframAlphaQueryRun\",\"Generic\",\"BaseTool\",\"RunnableSerializable\",\"Tool\",\"Serializable\",\"object\"],\"display_name\":\"WolframAlphaQueryRun\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false}},\"toolkits\":{\"JsonToolkit\":{\"template\":{\"spec\":{\"type\":\"JsonSpec\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"spec\",\"display_name\":\"Spec\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langchain_community.tools.json.tool import JsonSpec\\nfrom langchain_community.agent_toolkits.json.toolkit import JsonToolkit\\n\\n\\nclass JsonToolkitComponent(CustomComponent):\\n display_name = \\\"JsonToolkit\\\"\\n description = \\\"Toolkit for interacting with a JSON spec.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"spec\\\": {\\\"display_name\\\": \\\"Spec\\\", \\\"type\\\": JsonSpec},\\n }\\n\\n def build(self, spec: JsonSpec) -> JsonToolkit:\\n return JsonToolkit(spec=spec)\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Toolkit for interacting with a JSON spec.\",\"base_classes\":[\"BaseToolkit\",\"JsonToolkit\"],\"display_name\":\"JsonToolkit\",\"documentation\":\"\",\"custom_fields\":{\"spec\":null},\"output_types\":[\"JsonToolkit\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"OpenAPIToolkit\":{\"template\":{\"json_agent\":{\"type\":\"AgentExecutor\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"json_agent\",\"display_name\":\"JSON Agent\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"requests_wrapper\":{\"type\":\"TextRequestsWrapper\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"requests_wrapper\",\"display_name\":\"Text Requests Wrapper\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langchain_community.agent_toolkits.openapi.toolkit import BaseToolkit, OpenAPIToolkit\\nfrom langchain_community.utilities.requests import TextRequestsWrapper\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import AgentExecutor\\n\\n\\nclass OpenAPIToolkitComponent(CustomComponent):\\n display_name = \\\"OpenAPIToolkit\\\"\\n description = \\\"Toolkit for interacting with an OpenAPI API.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"json_agent\\\": {\\\"display_name\\\": \\\"JSON Agent\\\"},\\n \\\"requests_wrapper\\\": {\\\"display_name\\\": \\\"Text Requests Wrapper\\\"},\\n }\\n\\n def build(\\n self,\\n json_agent: AgentExecutor,\\n requests_wrapper: TextRequestsWrapper,\\n ) -> BaseToolkit:\\n return OpenAPIToolkit(json_agent=json_agent, requests_wrapper=requests_wrapper)\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Toolkit for interacting with an OpenAPI API.\",\"base_classes\":[\"BaseToolkit\"],\"display_name\":\"OpenAPIToolkit\",\"documentation\":\"\",\"custom_fields\":{\"json_agent\":null,\"requests_wrapper\":null},\"output_types\":[\"BaseToolkit\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"VectorStoreInfo\":{\"template\":{\"vectorstore\":{\"type\":\"VectorStore\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"vectorstore\",\"display_name\":\"VectorStore\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Callable, Union\\n\\nfrom langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreInfo\\nfrom langchain_community.vectorstores import VectorStore\\n\\nfrom langflow import CustomComponent\\n\\n\\nclass VectorStoreInfoComponent(CustomComponent):\\n display_name = \\\"VectorStoreInfo\\\"\\n description = \\\"Information about a VectorStore\\\"\\n\\n def build_config(self):\\n return {\\n \\\"vectorstore\\\": {\\\"display_name\\\": \\\"VectorStore\\\"},\\n \\\"description\\\": {\\\"display_name\\\": \\\"Description\\\", \\\"multiline\\\": True},\\n \\\"name\\\": {\\\"display_name\\\": \\\"Name\\\"},\\n }\\n\\n def build(\\n self,\\n vectorstore: VectorStore,\\n description: str,\\n name: str,\\n ) -> Union[VectorStoreInfo, Callable]:\\n return VectorStoreInfo(vectorstore=vectorstore, description=description, name=name)\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"description\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"description\",\"display_name\":\"Description\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"name\",\"display_name\":\"Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Information about a VectorStore\",\"base_classes\":[\"Callable\",\"VectorStoreInfo\"],\"display_name\":\"VectorStoreInfo\",\"documentation\":\"\",\"custom_fields\":{\"vectorstore\":null,\"description\":null,\"name\":null},\"output_types\":[\"VectorStoreInfo\",\"Callable\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"VectorStoreRouterToolkit\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"vectorstores\":{\"type\":\"VectorStoreInfo\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"vectorstores\",\"display_name\":\"Vector Stores\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom typing import List, Union\\nfrom langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreRouterToolkit\\nfrom langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreInfo\\nfrom langflow.field_typing import BaseLanguageModel, Tool\\n\\n\\nclass VectorStoreRouterToolkitComponent(CustomComponent):\\n display_name = \\\"VectorStoreRouterToolkit\\\"\\n description = \\\"Toolkit for routing between Vector Stores.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"vectorstores\\\": {\\\"display_name\\\": \\\"Vector Stores\\\"},\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n }\\n\\n def build(\\n self, vectorstores: List[VectorStoreInfo], llm: BaseLanguageModel\\n ) -> Union[Tool, VectorStoreRouterToolkit]:\\n print(\\\"vectorstores\\\", vectorstores)\\n print(\\\"llm\\\", llm)\\n return VectorStoreRouterToolkit(vectorstores=vectorstores, llm=llm)\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Toolkit for routing between Vector Stores.\",\"base_classes\":[\"Runnable\",\"BaseToolkit\",\"Generic\",\"VectorStoreRouterToolkit\",\"BaseTool\",\"RunnableSerializable\",\"Tool\",\"Serializable\",\"object\"],\"display_name\":\"VectorStoreRouterToolkit\",\"documentation\":\"\",\"custom_fields\":{\"vectorstores\":null,\"llm\":null},\"output_types\":[\"Tool\",\"VectorStoreRouterToolkit\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"VectorStoreToolkit\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"vectorstore_info\":{\"type\":\"VectorStoreInfo\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"vectorstore_info\",\"display_name\":\"Vector Store Info\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreToolkit\\nfrom langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreInfo\\nfrom langflow.field_typing import (\\n BaseLanguageModel,\\n)\\nfrom langflow.field_typing import (\\n Tool,\\n)\\nfrom typing import Union\\n\\n\\nclass VectorStoreToolkitComponent(CustomComponent):\\n display_name = \\\"VectorStoreToolkit\\\"\\n description = \\\"Toolkit for interacting with a Vector Store.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"vectorstore_info\\\": {\\\"display_name\\\": \\\"Vector Store Info\\\"},\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n }\\n\\n def build(\\n self,\\n vectorstore_info: VectorStoreInfo,\\n llm: BaseLanguageModel,\\n ) -> Union[Tool, VectorStoreToolkit]:\\n return VectorStoreToolkit(vectorstore_info=vectorstore_info, llm=llm)\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Toolkit for interacting with a Vector Store.\",\"base_classes\":[\"Runnable\",\"BaseToolkit\",\"Generic\",\"BaseTool\",\"RunnableSerializable\",\"Tool\",\"Serializable\",\"object\",\"VectorStoreToolkit\"],\"display_name\":\"VectorStoreToolkit\",\"documentation\":\"\",\"custom_fields\":{\"vectorstore_info\":null,\"llm\":null},\"output_types\":[\"Tool\",\"VectorStoreToolkit\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"Metaphor\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import List, Union\\n\\nfrom langchain.agents import tool\\nfrom langchain.agents.agent_toolkits.base import BaseToolkit\\nfrom langchain.tools import Tool\\nfrom metaphor_python import Metaphor # type: ignore\\n\\nfrom langflow import CustomComponent\\n\\n\\nclass MetaphorToolkit(CustomComponent):\\n display_name: str = \\\"Metaphor\\\"\\n description: str = \\\"Metaphor Toolkit\\\"\\n documentation = \\\"https://python.langchain.com/docs/integrations/tools/metaphor_search\\\"\\n beta: bool = True\\n # api key should be password = True\\n field_config = {\\n \\\"metaphor_api_key\\\": {\\\"display_name\\\": \\\"Metaphor API Key\\\", \\\"password\\\": True},\\n \\\"code\\\": {\\\"advanced\\\": True},\\n }\\n\\n def build(\\n self,\\n metaphor_api_key: str,\\n use_autoprompt: bool = True,\\n search_num_results: int = 5,\\n similar_num_results: int = 5,\\n ) -> Union[Tool, BaseToolkit]:\\n # If documents, then we need to create a Vectara instance using .from_documents\\n client = Metaphor(api_key=metaphor_api_key)\\n\\n @tool\\n def search(query: str):\\n \\\"\\\"\\\"Call search engine with a query.\\\"\\\"\\\"\\n return client.search(query, use_autoprompt=use_autoprompt, num_results=search_num_results)\\n\\n @tool\\n def get_contents(ids: List[str]):\\n \\\"\\\"\\\"Get contents of a webpage.\\n\\n The ids passed in should be a list of ids as fetched from `search`.\\n \\\"\\\"\\\"\\n return client.get_contents(ids)\\n\\n @tool\\n def find_similar(url: str):\\n \\\"\\\"\\\"Get search results similar to a given URL.\\n\\n The url passed in should be a URL returned from `search`\\n \\\"\\\"\\\"\\n return client.find_similar(url, num_results=similar_num_results)\\n\\n return [search, get_contents, find_similar] # type: ignore\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"metaphor_api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"metaphor_api_key\",\"display_name\":\"Metaphor API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"search_num_results\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":5,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"search_num_results\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"similar_num_results\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":5,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"similar_num_results\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"use_autoprompt\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":true,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"use_autoprompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Metaphor Toolkit\",\"base_classes\":[\"Runnable\",\"BaseToolkit\",\"Generic\",\"BaseTool\",\"RunnableSerializable\",\"Tool\",\"Serializable\",\"object\"],\"display_name\":\"Metaphor\",\"documentation\":\"https://python.langchain.com/docs/integrations/tools/metaphor_search\",\"custom_fields\":{\"metaphor_api_key\":null,\"use_autoprompt\":null,\"search_num_results\":null,\"similar_num_results\":null},\"output_types\":[\"Tool\",\"BaseToolkit\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true}},\"wrappers\":{\"TextRequestsWrapper\":{\"template\":{\"aiosession\":{\"type\":\"ClientSession\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"aiosession\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"auth\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"auth\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"headers\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"{\\\"Authorization\\\": \\\"Bearer \\\"}\",\"fileTypes\":[],\"password\":false,\"name\":\"headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"response_content_type\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":false,\"multiline\":false,\"value\":\"text\",\"fileTypes\":[],\"password\":false,\"name\":\"response_content_type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"TextRequestsWrapper\"},\"description\":\"Lightweight wrapper around requests library, with async support.\",\"base_classes\":[\"TextRequestsWrapper\",\"GenericRequestsWrapper\"],\"display_name\":\"TextRequestsWrapper\",\"documentation\":\"\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false}},\"embeddings\":{\"OpenAIEmbeddings\":{\"template\":{\"allowed_special\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":[],\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"allowed_special\",\"display_name\":\"Allowed Special\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"chunk_size\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1000,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chunk_size\",\"display_name\":\"Chunk Size\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"client\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"client\",\"display_name\":\"Client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Any, Callable, Dict, List, Optional, Union\\n\\nfrom langchain_openai.embeddings.base import OpenAIEmbeddings\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import NestedDict\\nfrom pydantic.v1.types import SecretStr\\n\\n\\nclass OpenAIEmbeddingsComponent(CustomComponent):\\n display_name = \\\"OpenAIEmbeddings\\\"\\n description = \\\"OpenAI embedding models\\\"\\n\\n def build_config(self):\\n return {\\n \\\"allowed_special\\\": {\\n \\\"display_name\\\": \\\"Allowed Special\\\",\\n \\\"advanced\\\": True,\\n \\\"field_type\\\": \\\"str\\\",\\n \\\"is_list\\\": True,\\n },\\n \\\"default_headers\\\": {\\n \\\"display_name\\\": \\\"Default Headers\\\",\\n \\\"advanced\\\": True,\\n \\\"field_type\\\": \\\"dict\\\",\\n },\\n \\\"default_query\\\": {\\n \\\"display_name\\\": \\\"Default Query\\\",\\n \\\"advanced\\\": True,\\n \\\"field_type\\\": \\\"NestedDict\\\",\\n },\\n \\\"disallowed_special\\\": {\\n \\\"display_name\\\": \\\"Disallowed Special\\\",\\n \\\"advanced\\\": True,\\n \\\"field_type\\\": \\\"str\\\",\\n \\\"is_list\\\": True,\\n },\\n \\\"chunk_size\\\": {\\\"display_name\\\": \\\"Chunk Size\\\", \\\"advanced\\\": True},\\n \\\"client\\\": {\\\"display_name\\\": \\\"Client\\\", \\\"advanced\\\": True},\\n \\\"deployment\\\": {\\\"display_name\\\": \\\"Deployment\\\", \\\"advanced\\\": True},\\n \\\"embedding_ctx_length\\\": {\\n \\\"display_name\\\": \\\"Embedding Context Length\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"max_retries\\\": {\\\"display_name\\\": \\\"Max Retries\\\", \\\"advanced\\\": True},\\n \\\"model\\\": {\\n \\\"display_name\\\": \\\"Model\\\",\\n \\\"advanced\\\": False,\\n \\\"options\\\": [\\\"text-embedding-3-small\\\", \\\"text-embedding-3-large\\\", \\\"text-embedding-ada-002\\\"],\\n },\\n \\\"model_kwargs\\\": {\\\"display_name\\\": \\\"Model Kwargs\\\", \\\"advanced\\\": True},\\n \\\"openai_api_base\\\": {\\\"display_name\\\": \\\"OpenAI API Base\\\", \\\"password\\\": True, \\\"advanced\\\": True},\\n \\\"openai_api_key\\\": {\\\"display_name\\\": \\\"OpenAI API Key\\\", \\\"password\\\": True},\\n \\\"openai_api_type\\\": {\\\"display_name\\\": \\\"OpenAI API Type\\\", \\\"advanced\\\": True, \\\"password\\\": True},\\n \\\"openai_api_version\\\": {\\n \\\"display_name\\\": \\\"OpenAI API Version\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"openai_organization\\\": {\\n \\\"display_name\\\": \\\"OpenAI Organization\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"openai_proxy\\\": {\\\"display_name\\\": \\\"OpenAI Proxy\\\", \\\"advanced\\\": True},\\n \\\"request_timeout\\\": {\\\"display_name\\\": \\\"Request Timeout\\\", \\\"advanced\\\": True},\\n \\\"show_progress_bar\\\": {\\n \\\"display_name\\\": \\\"Show Progress Bar\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"skip_empty\\\": {\\\"display_name\\\": \\\"Skip Empty\\\", \\\"advanced\\\": True},\\n \\\"tiktoken_model_name\\\": {\\\"display_name\\\": \\\"TikToken Model Name\\\"},\\n \\\"tikToken_enable\\\": {\\\"display_name\\\": \\\"TikToken Enable\\\", \\\"advanced\\\": True},\\n }\\n\\n def build(\\n self,\\n default_headers: Optional[Dict[str, str]] = None,\\n default_query: Optional[NestedDict] = {},\\n allowed_special: List[str] = [],\\n disallowed_special: List[str] = [\\\"all\\\"],\\n chunk_size: int = 1000,\\n client: Optional[Any] = None,\\n deployment: str = \\\"text-embedding-3-small\\\",\\n embedding_ctx_length: int = 8191,\\n max_retries: int = 6,\\n model: str = \\\"text-embedding-3-small\\\",\\n model_kwargs: NestedDict = {},\\n openai_api_base: Optional[str] = None,\\n openai_api_key: Optional[str] = \\\"\\\",\\n openai_api_type: Optional[str] = None,\\n openai_api_version: Optional[str] = None,\\n openai_organization: Optional[str] = None,\\n openai_proxy: Optional[str] = None,\\n request_timeout: Optional[float] = None,\\n show_progress_bar: bool = False,\\n skip_empty: bool = False,\\n tiktoken_enable: bool = True,\\n tiktoken_model_name: Optional[str] = None,\\n ) -> Union[OpenAIEmbeddings, Callable]:\\n # This is to avoid errors with Vector Stores (e.g Chroma)\\n if disallowed_special == [\\\"all\\\"]:\\n disallowed_special = \\\"all\\\" # type: ignore\\n\\n api_key = SecretStr(openai_api_key) if openai_api_key else None\\n\\n return OpenAIEmbeddings(\\n tiktoken_enabled=tiktoken_enable,\\n default_headers=default_headers,\\n default_query=default_query,\\n allowed_special=set(allowed_special),\\n disallowed_special=\\\"all\\\",\\n chunk_size=chunk_size,\\n client=client,\\n deployment=deployment,\\n embedding_ctx_length=embedding_ctx_length,\\n max_retries=max_retries,\\n model=model,\\n model_kwargs=model_kwargs,\\n base_url=openai_api_base,\\n api_key=api_key,\\n openai_api_type=openai_api_type,\\n api_version=openai_api_version,\\n organization=openai_organization,\\n openai_proxy=openai_proxy,\\n timeout=request_timeout,\\n show_progress_bar=show_progress_bar,\\n skip_empty=skip_empty,\\n tiktoken_model_name=tiktoken_model_name,\\n )\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"default_headers\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"default_headers\",\"display_name\":\"Default Headers\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"default_query\":{\"type\":\"NestedDict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"default_query\",\"display_name\":\"Default Query\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"deployment\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"text-embedding-3-small\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"deployment\",\"display_name\":\"Deployment\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"disallowed_special\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":[\"all\"],\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"disallowed_special\",\"display_name\":\"Disallowed Special\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"embedding_ctx_length\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":8191,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"embedding_ctx_length\",\"display_name\":\"Embedding Context Length\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"max_retries\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":6,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_retries\",\"display_name\":\"Max Retries\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"model\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"text-embedding-3-small\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"text-embedding-3-small\",\"text-embedding-3-large\",\"text-embedding-ada-002\"],\"name\":\"model\",\"display_name\":\"Model\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"model_kwargs\":{\"type\":\"NestedDict\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model_kwargs\",\"display_name\":\"Model Kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"openai_api_base\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"openai_api_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"openai_api_type\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"openai_api_type\",\"display_name\":\"OpenAI API Type\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"openai_api_version\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"openai_api_version\",\"display_name\":\"OpenAI API Version\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"openai_organization\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"openai_organization\",\"display_name\":\"OpenAI Organization\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"openai_proxy\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"openai_proxy\",\"display_name\":\"OpenAI Proxy\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"request_timeout\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"request_timeout\",\"display_name\":\"Request Timeout\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"show_progress_bar\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"show_progress_bar\",\"display_name\":\"Show Progress Bar\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"skip_empty\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"skip_empty\",\"display_name\":\"Skip Empty\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"tiktoken_enable\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":true,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tiktoken_enable\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"tiktoken_model_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tiktoken_model_name\",\"display_name\":\"TikToken Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"OpenAI embedding models\",\"base_classes\":[\"Embeddings\",\"OpenAIEmbeddings\",\"Callable\"],\"display_name\":\"OpenAIEmbeddings\",\"documentation\":\"\",\"custom_fields\":{\"default_headers\":null,\"default_query\":null,\"allowed_special\":null,\"disallowed_special\":null,\"chunk_size\":null,\"client\":null,\"deployment\":null,\"embedding_ctx_length\":null,\"max_retries\":null,\"model\":null,\"model_kwargs\":null,\"openai_api_base\":null,\"openai_api_key\":null,\"openai_api_type\":null,\"openai_api_version\":null,\"openai_organization\":null,\"openai_proxy\":null,\"request_timeout\":null,\"show_progress_bar\":null,\"skip_empty\":null,\"tiktoken_enable\":null,\"tiktoken_model_name\":null},\"output_types\":[\"OpenAIEmbeddings\",\"Callable\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"CohereEmbeddings\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain_community.embeddings.cohere import CohereEmbeddings\\nfrom langflow import CustomComponent\\n\\n\\nclass CohereEmbeddingsComponent(CustomComponent):\\n display_name = \\\"CohereEmbeddings\\\"\\n description = \\\"Cohere embedding models.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"cohere_api_key\\\": {\\\"display_name\\\": \\\"Cohere API Key\\\", \\\"password\\\": True},\\n \\\"model\\\": {\\\"display_name\\\": \\\"Model\\\", \\\"default\\\": \\\"embed-english-v2.0\\\", \\\"advanced\\\": True},\\n \\\"truncate\\\": {\\\"display_name\\\": \\\"Truncate\\\", \\\"advanced\\\": True},\\n \\\"max_retries\\\": {\\\"display_name\\\": \\\"Max Retries\\\", \\\"advanced\\\": True},\\n \\\"user_agent\\\": {\\\"display_name\\\": \\\"User Agent\\\", \\\"advanced\\\": True},\\n }\\n\\n def build(\\n self,\\n request_timeout: Optional[float] = None,\\n cohere_api_key: str = \\\"\\\",\\n max_retries: Optional[int] = None,\\n model: str = \\\"embed-english-v2.0\\\",\\n truncate: Optional[str] = None,\\n user_agent: str = \\\"langchain\\\",\\n ) -> CohereEmbeddings:\\n return CohereEmbeddings( # type: ignore\\n max_retries=max_retries,\\n user_agent=user_agent,\\n request_timeout=request_timeout,\\n cohere_api_key=cohere_api_key,\\n model=model,\\n truncate=truncate,\\n )\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"cohere_api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"cohere_api_key\",\"display_name\":\"Cohere API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"max_retries\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_retries\",\"display_name\":\"Max Retries\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"model\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"embed-english-v2.0\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model\",\"display_name\":\"Model\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"request_timeout\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"request_timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"truncate\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"truncate\",\"display_name\":\"Truncate\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"user_agent\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"langchain\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"user_agent\",\"display_name\":\"User Agent\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Cohere embedding models.\",\"base_classes\":[\"Embeddings\",\"CohereEmbeddings\"],\"display_name\":\"CohereEmbeddings\",\"documentation\":\"\",\"custom_fields\":{\"request_timeout\":null,\"cohere_api_key\":null,\"max_retries\":null,\"model\":null,\"truncate\":null,\"user_agent\":null},\"output_types\":[\"CohereEmbeddings\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"HuggingFaceEmbeddings\":{\"template\":{\"cache_folder\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"cache_folder\",\"display_name\":\"Cache Folder\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom typing import Optional, Dict\\nfrom langchain_community.embeddings.huggingface import HuggingFaceEmbeddings\\n\\n\\nclass HuggingFaceEmbeddingsComponent(CustomComponent):\\n display_name = \\\"HuggingFaceEmbeddings\\\"\\n description = \\\"HuggingFace sentence_transformers embedding models.\\\"\\n documentation = (\\n \\\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/sentence_transformers\\\"\\n )\\n\\n def build_config(self):\\n return {\\n \\\"cache_folder\\\": {\\\"display_name\\\": \\\"Cache Folder\\\", \\\"advanced\\\": True},\\n \\\"encode_kwargs\\\": {\\\"display_name\\\": \\\"Encode Kwargs\\\", \\\"advanced\\\": True, \\\"field_type\\\": \\\"dict\\\"},\\n \\\"model_kwargs\\\": {\\\"display_name\\\": \\\"Model Kwargs\\\", \\\"field_type\\\": \\\"dict\\\", \\\"advanced\\\": True},\\n \\\"model_name\\\": {\\\"display_name\\\": \\\"Model Name\\\"},\\n \\\"multi_process\\\": {\\\"display_name\\\": \\\"Multi Process\\\", \\\"advanced\\\": True},\\n }\\n\\n def build(\\n self,\\n cache_folder: Optional[str] = None,\\n encode_kwargs: Optional[Dict] = {},\\n model_kwargs: Optional[Dict] = {},\\n model_name: str = \\\"sentence-transformers/all-mpnet-base-v2\\\",\\n multi_process: bool = False,\\n ) -> HuggingFaceEmbeddings:\\n return HuggingFaceEmbeddings(\\n cache_folder=cache_folder,\\n encode_kwargs=encode_kwargs,\\n model_kwargs=model_kwargs,\\n model_name=model_name,\\n multi_process=multi_process,\\n )\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"encode_kwargs\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"encode_kwargs\",\"display_name\":\"Encode Kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"model_kwargs\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model_kwargs\",\"display_name\":\"Model Kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"model_name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"sentence-transformers/all-mpnet-base-v2\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model_name\",\"display_name\":\"Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"multi_process\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"multi_process\",\"display_name\":\"Multi Process\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"HuggingFace sentence_transformers embedding models.\",\"base_classes\":[\"Embeddings\",\"HuggingFaceEmbeddings\"],\"display_name\":\"HuggingFaceEmbeddings\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/sentence_transformers\",\"custom_fields\":{\"cache_folder\":null,\"encode_kwargs\":null,\"model_kwargs\":null,\"model_name\":null,\"multi_process\":null},\"output_types\":[\"HuggingFaceEmbeddings\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"VertexAIEmbeddings\":{\"template\":{\"credentials\":{\"type\":\"file\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".json\"],\"file_path\":\"\",\"password\":false,\"name\":\"credentials\",\"display_name\":\"Credentials\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langchain_community.embeddings import VertexAIEmbeddings\\nfrom typing import Optional, List\\n\\n\\nclass VertexAIEmbeddingsComponent(CustomComponent):\\n display_name = \\\"VertexAIEmbeddings\\\"\\n description = \\\"Google Cloud VertexAI embedding models.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"credentials\\\": {\\n \\\"display_name\\\": \\\"Credentials\\\",\\n \\\"value\\\": \\\"\\\",\\n \\\"file_types\\\": [\\\".json\\\"],\\n \\\"field_type\\\": \\\"file\\\",\\n },\\n \\\"instance\\\": {\\n \\\"display_name\\\": \\\"instance\\\",\\n \\\"advanced\\\": True,\\n \\\"field_type\\\": \\\"dict\\\",\\n },\\n \\\"location\\\": {\\n \\\"display_name\\\": \\\"Location\\\",\\n \\\"value\\\": \\\"us-central1\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"max_output_tokens\\\": {\\\"display_name\\\": \\\"Max Output Tokens\\\", \\\"value\\\": 128},\\n \\\"max_retries\\\": {\\n \\\"display_name\\\": \\\"Max Retries\\\",\\n \\\"value\\\": 6,\\n \\\"advanced\\\": True,\\n },\\n \\\"model_name\\\": {\\n \\\"display_name\\\": \\\"Model Name\\\",\\n \\\"value\\\": \\\"textembedding-gecko\\\",\\n },\\n \\\"n\\\": {\\\"display_name\\\": \\\"N\\\", \\\"value\\\": 1, \\\"advanced\\\": True},\\n \\\"project\\\": {\\\"display_name\\\": \\\"Project\\\", \\\"advanced\\\": True},\\n \\\"request_parallelism\\\": {\\n \\\"display_name\\\": \\\"Request Parallelism\\\",\\n \\\"value\\\": 5,\\n \\\"advanced\\\": True,\\n },\\n \\\"stop\\\": {\\\"display_name\\\": \\\"Stop\\\", \\\"advanced\\\": True},\\n \\\"streaming\\\": {\\n \\\"display_name\\\": \\\"Streaming\\\",\\n \\\"value\\\": False,\\n \\\"advanced\\\": True,\\n },\\n \\\"temperature\\\": {\\\"display_name\\\": \\\"Temperature\\\", \\\"value\\\": 0.0},\\n \\\"top_k\\\": {\\\"display_name\\\": \\\"Top K\\\", \\\"value\\\": 40, \\\"advanced\\\": True},\\n \\\"top_p\\\": {\\\"display_name\\\": \\\"Top P\\\", \\\"value\\\": 0.95, \\\"advanced\\\": True},\\n }\\n\\n def build(\\n self,\\n instance: Optional[str] = None,\\n credentials: Optional[str] = None,\\n location: str = \\\"us-central1\\\",\\n max_output_tokens: int = 128,\\n max_retries: int = 6,\\n model_name: str = \\\"textembedding-gecko\\\",\\n n: int = 1,\\n project: Optional[str] = None,\\n request_parallelism: int = 5,\\n stop: Optional[List[str]] = None,\\n streaming: bool = False,\\n temperature: float = 0.0,\\n top_k: int = 40,\\n top_p: float = 0.95,\\n ) -> VertexAIEmbeddings:\\n return VertexAIEmbeddings(\\n instance=instance,\\n credentials=credentials,\\n location=location,\\n max_output_tokens=max_output_tokens,\\n max_retries=max_retries,\\n model_name=model_name,\\n n=n,\\n project=project,\\n request_parallelism=request_parallelism,\\n stop=stop,\\n streaming=streaming,\\n temperature=temperature,\\n top_k=top_k,\\n top_p=top_p,\\n )\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"instance\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"instance\",\"display_name\":\"instance\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"location\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"us-central1\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"location\",\"display_name\":\"Location\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"max_output_tokens\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":128,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_output_tokens\",\"display_name\":\"Max Output Tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"max_retries\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":6,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_retries\",\"display_name\":\"Max Retries\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"model_name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"textembedding-gecko\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model_name\",\"display_name\":\"Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"n\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"n\",\"display_name\":\"N\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"project\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"project\",\"display_name\":\"Project\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"request_parallelism\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":5,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"request_parallelism\",\"display_name\":\"Request Parallelism\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"stop\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"stop\",\"display_name\":\"Stop\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"streaming\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"streaming\",\"display_name\":\"Streaming\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"temperature\":{\"type\":\"float\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.0,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"top_k\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":40,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_k\",\"display_name\":\"Top K\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"top_p\":{\"type\":\"float\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.95,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_p\",\"display_name\":\"Top P\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Google Cloud VertexAI embedding models.\",\"base_classes\":[\"_VertexAICommon\",\"Embeddings\",\"_VertexAIBase\",\"VertexAIEmbeddings\"],\"display_name\":\"VertexAIEmbeddings\",\"documentation\":\"\",\"custom_fields\":{\"instance\":null,\"credentials\":null,\"location\":null,\"max_output_tokens\":null,\"max_retries\":null,\"model_name\":null,\"n\":null,\"project\":null,\"request_parallelism\":null,\"stop\":null,\"streaming\":null,\"temperature\":null,\"top_k\":null,\"top_p\":null},\"output_types\":[\"VertexAIEmbeddings\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"OllamaEmbeddings\":{\"template\":{\"base_url\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"http://localhost:11434\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"base_url\",\"display_name\":\"Ollama Base URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langflow import CustomComponent\\nfrom langchain.embeddings.base import Embeddings\\nfrom langchain_community.embeddings import OllamaEmbeddings\\n\\n\\nclass OllamaEmbeddingsComponent(CustomComponent):\\n \\\"\\\"\\\"\\n A custom component for implementing an Embeddings Model using Ollama.\\n \\\"\\\"\\\"\\n\\n display_name: str = \\\"Ollama Embeddings\\\"\\n description: str = \\\"Embeddings model from Ollama.\\\"\\n documentation = \\\"https://python.langchain.com/docs/integrations/text_embedding/ollama\\\"\\n beta = True\\n\\n def build_config(self):\\n return {\\n \\\"model\\\": {\\n \\\"display_name\\\": \\\"Ollama Model\\\",\\n },\\n \\\"base_url\\\": {\\\"display_name\\\": \\\"Ollama Base URL\\\"},\\n \\\"temperature\\\": {\\\"display_name\\\": \\\"Model Temperature\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n model: str = \\\"llama2\\\",\\n base_url: str = \\\"http://localhost:11434\\\",\\n temperature: Optional[float] = None,\\n ) -> Embeddings:\\n try:\\n output = OllamaEmbeddings(model=model, base_url=base_url, temperature=temperature) # type: ignore\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to Ollama API.\\\") from e\\n return output\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"model\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"llama2\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model\",\"display_name\":\"Ollama Model\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Model Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Embeddings model from Ollama.\",\"base_classes\":[\"Embeddings\"],\"display_name\":\"Ollama Embeddings\",\"documentation\":\"https://python.langchain.com/docs/integrations/text_embedding/ollama\",\"custom_fields\":{\"model\":null,\"base_url\":null,\"temperature\":null},\"output_types\":[\"Embeddings\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"AmazonBedrockEmbeddings\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain.embeddings.base import Embeddings\\nfrom langchain_community.embeddings import BedrockEmbeddings\\n\\n\\nfrom langflow import CustomComponent\\n\\n\\nclass AmazonBedrockEmeddingsComponent(CustomComponent):\\n \\\"\\\"\\\"\\n A custom component for implementing an Embeddings Model using Amazon Bedrock.\\n \\\"\\\"\\\"\\n\\n display_name: str = \\\"Amazon Bedrock Embeddings\\\"\\n description: str = \\\"Embeddings model from Amazon Bedrock.\\\"\\n documentation = \\\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock\\\"\\n beta = True\\n\\n def build_config(self):\\n return {\\n \\\"model_id\\\": {\\n \\\"display_name\\\": \\\"Model Id\\\",\\n \\\"options\\\": [\\\"amazon.titan-embed-text-v1\\\"],\\n },\\n \\\"credentials_profile_name\\\": {\\\"display_name\\\": \\\"Credentials Profile Name\\\"},\\n \\\"endpoint_url\\\": {\\\"display_name\\\": \\\"Bedrock Endpoint URL\\\"},\\n \\\"region_name\\\": {\\\"display_name\\\": \\\"AWS Region\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n model_id: str = \\\"amazon.titan-embed-text-v1\\\",\\n credentials_profile_name: Optional[str] = None,\\n endpoint_url: Optional[str] = None,\\n region_name: Optional[str] = None,\\n ) -> Embeddings:\\n try:\\n output = BedrockEmbeddings(\\n credentials_profile_name=credentials_profile_name,\\n model_id=model_id,\\n endpoint_url=endpoint_url,\\n region_name=region_name,\\n ) # type: ignore\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to AmazonBedrock API.\\\") from e\\n return output\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"credentials_profile_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"credentials_profile_name\",\"display_name\":\"Credentials Profile Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"endpoint_url\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"endpoint_url\",\"display_name\":\"Bedrock Endpoint URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"model_id\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"amazon.titan-embed-text-v1\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"amazon.titan-embed-text-v1\"],\"name\":\"model_id\",\"display_name\":\"Model Id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"region_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"region_name\",\"display_name\":\"AWS Region\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Embeddings model from Amazon Bedrock.\",\"base_classes\":[\"Embeddings\"],\"display_name\":\"Amazon Bedrock Embeddings\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/text_embedding/integrations/bedrock\",\"custom_fields\":{\"model_id\":null,\"credentials_profile_name\":null,\"endpoint_url\":null,\"region_name\":null},\"output_types\":[\"Embeddings\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"AzureOpenAIEmbeddings\":{\"template\":{\"api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"api_key\",\"display_name\":\"API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"api_version\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"2023-08-01-preview\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"2022-12-01\",\"2023-03-15-preview\",\"2023-05-15\",\"2023-06-01-preview\",\"2023-07-01-preview\",\"2023-08-01-preview\"],\"name\":\"api_version\",\"display_name\":\"API Version\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"azure_deployment\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"azure_deployment\",\"display_name\":\"Deployment Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"azure_endpoint\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"azure_endpoint\",\"display_name\":\"Azure Endpoint\",\"advanced\":false,\"dynamic\":false,\"info\":\"Your Azure endpoint, including the resource.. Example: `https://example-resource.azure.openai.com/`\",\"title_case\":false,\"input_types\":[\"Text\"]},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langchain.embeddings.base import Embeddings\\nfrom langchain_community.embeddings import AzureOpenAIEmbeddings\\n\\nfrom langflow import CustomComponent\\n\\n\\nclass AzureOpenAIEmbeddingsComponent(CustomComponent):\\n display_name: str = \\\"AzureOpenAIEmbeddings\\\"\\n description: str = \\\"Embeddings model from Azure OpenAI.\\\"\\n documentation: str = \\\"https://python.langchain.com/docs/integrations/text_embedding/azureopenai\\\"\\n beta = False\\n\\n API_VERSION_OPTIONS = [\\n \\\"2022-12-01\\\",\\n \\\"2023-03-15-preview\\\",\\n \\\"2023-05-15\\\",\\n \\\"2023-06-01-preview\\\",\\n \\\"2023-07-01-preview\\\",\\n \\\"2023-08-01-preview\\\",\\n ]\\n\\n def build_config(self):\\n return {\\n \\\"azure_endpoint\\\": {\\n \\\"display_name\\\": \\\"Azure Endpoint\\\",\\n \\\"required\\\": True,\\n \\\"info\\\": \\\"Your Azure endpoint, including the resource.. Example: `https://example-resource.azure.openai.com/`\\\",\\n },\\n \\\"azure_deployment\\\": {\\n \\\"display_name\\\": \\\"Deployment Name\\\",\\n \\\"required\\\": True,\\n },\\n \\\"api_version\\\": {\\n \\\"display_name\\\": \\\"API Version\\\",\\n \\\"options\\\": self.API_VERSION_OPTIONS,\\n \\\"value\\\": self.API_VERSION_OPTIONS[-1],\\n \\\"advanced\\\": True,\\n },\\n \\\"api_key\\\": {\\n \\\"display_name\\\": \\\"API Key\\\",\\n \\\"required\\\": True,\\n \\\"password\\\": True,\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n azure_endpoint: str,\\n azure_deployment: str,\\n api_version: str,\\n api_key: str,\\n ) -> Embeddings:\\n try:\\n embeddings = AzureOpenAIEmbeddings(\\n azure_endpoint=azure_endpoint,\\n azure_deployment=azure_deployment,\\n api_version=api_version,\\n api_key=api_key,\\n )\\n\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to AzureOpenAIEmbeddings API.\\\") from e\\n\\n return embeddings\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Embeddings model from Azure OpenAI.\",\"base_classes\":[\"Embeddings\"],\"display_name\":\"AzureOpenAIEmbeddings\",\"documentation\":\"https://python.langchain.com/docs/integrations/text_embedding/azureopenai\",\"custom_fields\":{\"azure_endpoint\":null,\"azure_deployment\":null,\"api_version\":null,\"api_key\":null},\"output_types\":[\"Embeddings\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"HuggingFaceInferenceAPIEmbeddings\":{\"template\":{\"api_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"api_key\",\"display_name\":\"API Key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"api_url\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"http://localhost:8080\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"api_url\",\"display_name\":\"API URL\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"cache_folder\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"cache_folder\",\"display_name\":\"Cache Folder\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Dict, Optional\\n\\nfrom langchain_community.embeddings.huggingface import HuggingFaceInferenceAPIEmbeddings\\nfrom langflow import CustomComponent\\nfrom pydantic.v1.types import SecretStr\\n\\n\\nclass HuggingFaceInferenceAPIEmbeddingsComponent(CustomComponent):\\n display_name = \\\"HuggingFaceInferenceAPIEmbeddings\\\"\\n description = \\\"HuggingFace sentence_transformers embedding models, API version.\\\"\\n documentation = \\\"https://github.com/huggingface/text-embeddings-inference\\\"\\n\\n def build_config(self):\\n return {\\n \\\"api_key\\\": {\\\"display_name\\\": \\\"API Key\\\", \\\"password\\\": True, \\\"advanced\\\": True},\\n \\\"api_url\\\": {\\\"display_name\\\": \\\"API URL\\\", \\\"advanced\\\": True},\\n \\\"model_name\\\": {\\\"display_name\\\": \\\"Model Name\\\"},\\n \\\"cache_folder\\\": {\\\"display_name\\\": \\\"Cache Folder\\\", \\\"advanced\\\": True},\\n \\\"encode_kwargs\\\": {\\\"display_name\\\": \\\"Encode Kwargs\\\", \\\"advanced\\\": True, \\\"field_type\\\": \\\"dict\\\"},\\n \\\"model_kwargs\\\": {\\\"display_name\\\": \\\"Model Kwargs\\\", \\\"field_type\\\": \\\"dict\\\", \\\"advanced\\\": True},\\n \\\"multi_process\\\": {\\\"display_name\\\": \\\"Multi Process\\\", \\\"advanced\\\": True},\\n }\\n\\n def build(\\n self,\\n api_key: Optional[str] = \\\"\\\",\\n api_url: str = \\\"http://localhost:8080\\\",\\n model_name: str = \\\"BAAI/bge-large-en-v1.5\\\",\\n cache_folder: Optional[str] = None,\\n encode_kwargs: Optional[Dict] = {},\\n model_kwargs: Optional[Dict] = {},\\n multi_process: bool = False,\\n ) -> HuggingFaceInferenceAPIEmbeddings:\\n if api_key:\\n secret_api_key = SecretStr(api_key)\\n else:\\n raise ValueError(\\\"API Key is required\\\")\\n return HuggingFaceInferenceAPIEmbeddings(\\n api_key=secret_api_key,\\n api_url=api_url,\\n model_name=model_name,\\n )\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"encode_kwargs\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"encode_kwargs\",\"display_name\":\"Encode Kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"model_kwargs\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model_kwargs\",\"display_name\":\"Model Kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"model_name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"BAAI/bge-large-en-v1.5\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model_name\",\"display_name\":\"Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"multi_process\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"multi_process\",\"display_name\":\"Multi Process\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"HuggingFace sentence_transformers embedding models, API version.\",\"base_classes\":[\"Embeddings\",\"HuggingFaceInferenceAPIEmbeddings\"],\"display_name\":\"HuggingFaceInferenceAPIEmbeddings\",\"documentation\":\"https://github.com/huggingface/text-embeddings-inference\",\"custom_fields\":{\"api_key\":null,\"api_url\":null,\"model_name\":null,\"cache_folder\":null,\"encode_kwargs\":null,\"model_kwargs\":null,\"multi_process\":null},\"output_types\":[\"HuggingFaceInferenceAPIEmbeddings\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true}},\"documentloaders\":{\"AZLyricsLoader\":{\"template\":{\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"web_path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"web_path\",\"display_name\":\"Web Page\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"AZLyricsLoader\"},\"description\":\"Load `AZLyrics` webpages.\",\"base_classes\":[\"Document\"],\"display_name\":\"AZLyricsLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/azlyrics\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"AirbyteJSONLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".json\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"AirbyteJSONLoader\"},\"description\":\"Load local `Airbyte` json files.\",\"base_classes\":[\"Document\"],\"display_name\":\"AirbyteJSONLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/airbyte_json\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"BSHTMLLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".html\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"BSHTMLLoader\"},\"description\":\"Load `HTML` files and parse them with `beautiful soup`.\",\"base_classes\":[\"Document\"],\"display_name\":\"BSHTMLLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/how_to/html\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"CSVLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".csv\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"CSVLoader\"},\"description\":\"Load a `CSV` file into a list of Documents.\",\"base_classes\":[\"Document\"],\"display_name\":\"CSVLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/csv\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"CoNLLULoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".csv\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"CoNLLULoader\"},\"description\":\"Load `CoNLL-U` files.\",\"base_classes\":[\"Document\"],\"display_name\":\"CoNLLULoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/conll-u\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"CollegeConfidentialLoader\":{\"template\":{\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"web_path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"web_path\",\"display_name\":\"Web Page\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CollegeConfidentialLoader\"},\"description\":\"Load `College Confidential` webpages.\",\"base_classes\":[\"Document\"],\"display_name\":\"CollegeConfidentialLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/college_confidential\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"DirectoryLoader\":{\"template\":{\"glob\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"**/*.txt\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"glob\",\"display_name\":\"glob\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"load_hidden\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"False\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"load_hidden\",\"display_name\":\"Load hidden files\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"max_concurrency\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":10,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_concurrency\",\"display_name\":\"Max concurrency\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"path\",\"display_name\":\"Local directory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"recursive\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"True\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"recursive\",\"display_name\":\"Recursive\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"silent_errors\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"False\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"silent_errors\",\"display_name\":\"Silent errors\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"use_multithreading\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"True\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"use_multithreading\",\"display_name\":\"Use multithreading\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"DirectoryLoader\"},\"description\":\"Load from a directory.\",\"base_classes\":[\"Document\"],\"display_name\":\"DirectoryLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/how_to/file_directory\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"EverNoteLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".xml\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"EverNoteLoader\"},\"description\":\"Load from `EverNote`.\",\"base_classes\":[\"Document\"],\"display_name\":\"EverNoteLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/evernote\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"FacebookChatLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".json\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"FacebookChatLoader\"},\"description\":\"Load `Facebook Chat` messages directory dump.\",\"base_classes\":[\"Document\"],\"display_name\":\"FacebookChatLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/facebook_chat\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"GitLoader\":{\"template\":{\"branch\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"branch\",\"display_name\":\"Branch\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"clone_url\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"clone_url\",\"display_name\":\"Clone URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"file_filter\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"file_filter\",\"display_name\":\"File extensions (comma-separated)\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"repo_path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"repo_path\",\"display_name\":\"Path to repository\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"GitLoader\"},\"description\":\"Load `Git` repository files.\",\"base_classes\":[\"Document\"],\"display_name\":\"GitLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/git\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"GitbookLoader\":{\"template\":{\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"web_page\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"web_page\",\"display_name\":\"Web Page\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"GitbookLoader\"},\"description\":\"Load `GitBook` data.\",\"base_classes\":[\"Document\"],\"display_name\":\"GitbookLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/gitbook\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"GutenbergLoader\":{\"template\":{\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"web_path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"web_path\",\"display_name\":\"Web Page\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"GutenbergLoader\"},\"description\":\"Load from `Gutenberg.org`.\",\"base_classes\":[\"Document\"],\"display_name\":\"GutenbergLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/gutenberg\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"HNLoader\":{\"template\":{\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"web_path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"web_path\",\"display_name\":\"Web Page\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"HNLoader\"},\"description\":\"Load `Hacker News` data.\",\"base_classes\":[\"Document\"],\"display_name\":\"HNLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/hacker_news\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"IFixitLoader\":{\"template\":{\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"web_path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"web_path\",\"display_name\":\"Web Page\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"IFixitLoader\"},\"description\":\"Load `iFixit` repair guides, device wikis and answers.\",\"base_classes\":[\"Document\"],\"display_name\":\"IFixitLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/ifixit\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"IMSDbLoader\":{\"template\":{\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"web_path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"web_path\",\"display_name\":\"Web Page\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"IMSDbLoader\"},\"description\":\"Load `IMSDb` webpages.\",\"base_classes\":[\"Document\"],\"display_name\":\"IMSDbLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/imsdb\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"NotionDirectoryLoader\":{\"template\":{\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"path\",\"display_name\":\"Local directory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"NotionDirectoryLoader\"},\"description\":\"Load `Notion directory` dump.\",\"base_classes\":[\"Document\"],\"display_name\":\"NotionDirectoryLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/notion\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"PyPDFLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".pdf\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"PyPDFLoader\"},\"description\":\"Load PDF using pypdf into list of documents.\",\"base_classes\":[\"Document\"],\"display_name\":\"PyPDFLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/how_to/pdf\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"PyPDFDirectoryLoader\":{\"template\":{\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"path\",\"display_name\":\"Local directory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"PyPDFDirectoryLoader\"},\"description\":\"Load a directory with `PDF` files using `pypdf` and chunks at character level.\",\"base_classes\":[\"Document\"],\"display_name\":\"PyPDFDirectoryLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/how_to/pdf\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"ReadTheDocsLoader\":{\"template\":{\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"path\",\"display_name\":\"Local directory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"ReadTheDocsLoader\"},\"description\":\"Load `ReadTheDocs` documentation directory.\",\"base_classes\":[\"Document\"],\"display_name\":\"ReadTheDocsLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/readthedocs_documentation\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"SRTLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".srt\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"SRTLoader\"},\"description\":\"Load `.srt` (subtitle) files.\",\"base_classes\":[\"Document\"],\"display_name\":\"SRTLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/subtitle\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"SlackDirectoryLoader\":{\"template\":{\"zip_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".zip\"],\"file_path\":\"\",\"password\":false,\"name\":\"zip_path\",\"display_name\":\"Path to zip file\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"workspace_url\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"workspace_url\",\"display_name\":\"Workspace URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"SlackDirectoryLoader\"},\"description\":\"Load from a `Slack` directory dump.\",\"base_classes\":[\"Document\"],\"display_name\":\"SlackDirectoryLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/slack\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"TextLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".txt\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"TextLoader\"},\"description\":\"Load text file.\",\"base_classes\":[\"Document\"],\"display_name\":\"TextLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"UnstructuredEmailLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".eml\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"UnstructuredEmailLoader\"},\"description\":\"Load email files using `Unstructured`.\",\"base_classes\":[\"Document\"],\"display_name\":\"UnstructuredEmailLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/email\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"UnstructuredHTMLLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".html\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"UnstructuredHTMLLoader\"},\"description\":\"Load `HTML` files using `Unstructured`.\",\"base_classes\":[\"Document\"],\"display_name\":\"UnstructuredHTMLLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/how_to/html\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"UnstructuredMarkdownLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".md\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"UnstructuredMarkdownLoader\"},\"description\":\"Load `Markdown` files using `Unstructured`.\",\"base_classes\":[\"Document\"],\"display_name\":\"UnstructuredMarkdownLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/how_to/markdown\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"UnstructuredPowerPointLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".pptx\",\".ppt\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"UnstructuredPowerPointLoader\"},\"description\":\"Load `Microsoft PowerPoint` files using `Unstructured`.\",\"base_classes\":[\"Document\"],\"display_name\":\"UnstructuredPowerPointLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/microsoft_powerpoint\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"UnstructuredWordDocumentLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[\".docx\",\".doc\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"UnstructuredWordDocumentLoader\"},\"description\":\"Load `Microsoft Word` file using `Unstructured`.\",\"base_classes\":[\"Document\"],\"display_name\":\"UnstructuredWordDocumentLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/microsoft_word\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"WebBaseLoader\":{\"template\":{\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"web_path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"web_path\",\"display_name\":\"Web Page\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"WebBaseLoader\"},\"description\":\"Load HTML pages using `urllib` and parse them with `BeautifulSoup'.\",\"base_classes\":[\"Document\"],\"display_name\":\"WebBaseLoader\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/document_loaders/integrations/web_base\",\"custom_fields\":{},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"FileLoader\":{\"template\":{\"file_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[\".json\",\".txt\",\".csv\",\".jsonl\",\".html\",\".htm\",\".conllu\",\".enex\",\".msg\",\".pdf\",\".srt\",\".eml\",\".md\",\".mdx\",\".pptx\",\".docx\"],\"file_path\":\"\",\"password\":false,\"name\":\"file_path\",\"display_name\":\"File Path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langchain_core.documents import Document\\n\\nfrom langflow import CustomComponent\\nfrom langflow.utils.constants import LOADERS_INFO\\n\\n\\nclass FileLoaderComponent(CustomComponent):\\n display_name: str = \\\"File Loader\\\"\\n description: str = \\\"Generic File Loader\\\"\\n beta = True\\n\\n def build_config(self):\\n loader_options = [\\\"Automatic\\\"] + [loader_info[\\\"name\\\"] for loader_info in LOADERS_INFO]\\n\\n file_types = []\\n suffixes = []\\n\\n for loader_info in LOADERS_INFO:\\n if \\\"allowedTypes\\\" in loader_info:\\n file_types.extend(loader_info[\\\"allowedTypes\\\"])\\n suffixes.extend([f\\\".{ext}\\\" for ext in loader_info[\\\"allowedTypes\\\"]])\\n\\n return {\\n \\\"file_path\\\": {\\n \\\"display_name\\\": \\\"File Path\\\",\\n \\\"required\\\": True,\\n \\\"field_type\\\": \\\"file\\\",\\n \\\"file_types\\\": [\\n \\\"json\\\",\\n \\\"txt\\\",\\n \\\"csv\\\",\\n \\\"jsonl\\\",\\n \\\"html\\\",\\n \\\"htm\\\",\\n \\\"conllu\\\",\\n \\\"enex\\\",\\n \\\"msg\\\",\\n \\\"pdf\\\",\\n \\\"srt\\\",\\n \\\"eml\\\",\\n \\\"md\\\",\\n \\\"mdx\\\",\\n \\\"pptx\\\",\\n \\\"docx\\\",\\n ],\\n \\\"suffixes\\\": [\\n \\\".json\\\",\\n \\\".txt\\\",\\n \\\".csv\\\",\\n \\\".jsonl\\\",\\n \\\".html\\\",\\n \\\".htm\\\",\\n \\\".conllu\\\",\\n \\\".enex\\\",\\n \\\".msg\\\",\\n \\\".pdf\\\",\\n \\\".srt\\\",\\n \\\".eml\\\",\\n \\\".md\\\",\\n \\\".mdx\\\",\\n \\\".pptx\\\",\\n \\\".docx\\\",\\n ],\\n # \\\"file_types\\\" : file_types,\\n # \\\"suffixes\\\": suffixes,\\n },\\n \\\"loader\\\": {\\n \\\"display_name\\\": \\\"Loader\\\",\\n \\\"is_list\\\": True,\\n \\\"required\\\": True,\\n \\\"options\\\": loader_options,\\n \\\"value\\\": \\\"Automatic\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(self, file_path: str, loader: str) -> Document:\\n file_type = file_path.split(\\\".\\\")[-1]\\n\\n # Map the loader to the correct loader class\\n selected_loader_info = None\\n for loader_info in LOADERS_INFO:\\n if loader_info[\\\"name\\\"] == loader:\\n selected_loader_info = loader_info\\n break\\n\\n if selected_loader_info is None and loader != \\\"Automatic\\\":\\n raise ValueError(f\\\"Loader {loader} not found in the loader info list\\\")\\n\\n if loader == \\\"Automatic\\\":\\n # Determine the loader based on the file type\\n default_loader_info = None\\n for info in LOADERS_INFO:\\n if \\\"defaultFor\\\" in info and file_type in info[\\\"defaultFor\\\"]:\\n default_loader_info = info\\n break\\n\\n if default_loader_info is None:\\n raise ValueError(f\\\"No default loader found for file type: {file_type}\\\")\\n\\n selected_loader_info = default_loader_info\\n if isinstance(selected_loader_info, dict):\\n loader_import: str = selected_loader_info[\\\"import\\\"]\\n else:\\n raise ValueError(f\\\"Loader info for {loader} is not a dict\\\\nLoader info:\\\\n{selected_loader_info}\\\")\\n module_name, class_name = loader_import.rsplit(\\\".\\\", 1)\\n\\n try:\\n # Import the loader class\\n loader_module = __import__(module_name, fromlist=[class_name])\\n loader_instance = getattr(loader_module, class_name)\\n except ImportError as e:\\n raise ValueError(f\\\"Loader {loader} could not be imported\\\\nLoader info:\\\\n{selected_loader_info}\\\") from e\\n\\n result = loader_instance(file_path=file_path)\\n return result.load()\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"loader\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"Automatic\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"Automatic\",\"Airbyte JSON (.jsonl)\",\"JSON (.json)\",\"BeautifulSoup4 HTML (.html, .htm)\",\"CSV (.csv)\",\"CoNLL-U (.conllu)\",\"EverNote (.enex)\",\"Facebook Chat (.json)\",\"Outlook Message (.msg)\",\"PyPDF (.pdf)\",\"Subtitle (.str)\",\"Text (.txt)\",\"Unstructured Email (.eml)\",\"Unstructured HTML (.html, .htm)\",\"Unstructured Markdown (.md)\",\"Unstructured PowerPoint (.pptx)\",\"Unstructured Word (.docx)\"],\"name\":\"loader\",\"display_name\":\"Loader\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Generic File Loader\",\"base_classes\":[\"Serializable\",\"Document\"],\"display_name\":\"File Loader\",\"documentation\":\"\",\"custom_fields\":{\"file_path\":null,\"loader\":null},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"UrlLoader\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import List\\n\\nfrom langchain import document_loaders\\nfrom langchain_core.documents import Document\\n\\nfrom langflow import CustomComponent\\n\\n\\nclass UrlLoaderComponent(CustomComponent):\\n display_name: str = \\\"Url Loader\\\"\\n description: str = \\\"Generic Url Loader Component\\\"\\n\\n def build_config(self):\\n return {\\n \\\"web_path\\\": {\\n \\\"display_name\\\": \\\"Url\\\",\\n \\\"required\\\": True,\\n },\\n \\\"loader\\\": {\\n \\\"display_name\\\": \\\"Loader\\\",\\n \\\"is_list\\\": True,\\n \\\"required\\\": True,\\n \\\"options\\\": [\\n \\\"AZLyricsLoader\\\",\\n \\\"CollegeConfidentialLoader\\\",\\n \\\"GitbookLoader\\\",\\n \\\"HNLoader\\\",\\n \\\"IFixitLoader\\\",\\n \\\"IMSDbLoader\\\",\\n \\\"WebBaseLoader\\\",\\n ],\\n \\\"value\\\": \\\"WebBaseLoader\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(self, web_path: str, loader: str) -> List[Document]:\\n try:\\n loader_instance = getattr(document_loaders, loader)(web_path=web_path)\\n except Exception as e:\\n raise ValueError(f\\\"No loader found for: {web_path}\\\") from e\\n docs = loader_instance.load()\\n avg_length = sum(len(doc.page_content) for doc in docs if hasattr(doc, \\\"page_content\\\")) / len(docs)\\n self.status = f\\\"\\\"\\\"{len(docs)} documents)\\n \\\\nAvg. Document Length (characters): {int(avg_length)}\\n Documents: {docs[:3]}...\\\"\\\"\\\"\\n return docs\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"loader\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"WebBaseLoader\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"AZLyricsLoader\",\"CollegeConfidentialLoader\",\"GitbookLoader\",\"HNLoader\",\"IFixitLoader\",\"IMSDbLoader\",\"WebBaseLoader\"],\"name\":\"loader\",\"display_name\":\"Loader\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"web_path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"web_path\",\"display_name\":\"Url\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Generic Url Loader Component\",\"base_classes\":[\"Serializable\",\"Document\"],\"display_name\":\"Url Loader\",\"documentation\":\"\",\"custom_fields\":{\"web_path\":null,\"loader\":null},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"GatherRecords\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from concurrent import futures\\nfrom pathlib import Path\\nfrom typing import Any, Dict, List\\n\\nfrom langflow import CustomComponent\\nfrom langflow.schema import Record\\n\\n\\nclass GatherRecordsComponent(CustomComponent):\\n display_name = \\\"Gather Records\\\"\\n description = \\\"Gather records from a directory.\\\"\\n\\n def build_config(self) -> Dict[str, Any]:\\n return {\\n \\\"load_hidden\\\": {\\n \\\"display_name\\\": \\\"Load Hidden Files\\\",\\n \\\"value\\\": False,\\n \\\"advanced\\\": True,\\n },\\n \\\"max_concurrency\\\": {\\n \\\"display_name\\\": \\\"Max Concurrency\\\",\\n \\\"value\\\": 10,\\n \\\"advanced\\\": True,\\n },\\n \\\"path\\\": {\\\"display_name\\\": \\\"Local Directory\\\"},\\n \\\"recursive\\\": {\\\"display_name\\\": \\\"Recursive\\\", \\\"value\\\": True, \\\"advanced\\\": True},\\n \\\"use_multithreading\\\": {\\n \\\"display_name\\\": \\\"Use Multithreading\\\",\\n \\\"value\\\": True,\\n \\\"advanced\\\": True,\\n },\\n }\\n\\n def is_hidden(self, path: Path) -> bool:\\n return path.name.startswith(\\\".\\\")\\n\\n def retrieve_file_paths(\\n self,\\n path: str,\\n types: List[str],\\n load_hidden: bool,\\n recursive: bool,\\n depth: int,\\n ) -> List[str]:\\n path_obj = Path(path)\\n if not path_obj.exists() or not path_obj.is_dir():\\n raise ValueError(f\\\"Path {path} must exist and be a directory.\\\")\\n\\n def match_types(p: Path) -> bool:\\n return any(p.suffix == f\\\".{t}\\\" for t in types) if types else True\\n\\n def is_not_hidden(p: Path) -> bool:\\n return not self.is_hidden(p) or load_hidden\\n\\n def walk_level(directory: Path, max_depth: int):\\n directory = directory.resolve()\\n prefix_length = len(directory.parts)\\n for p in directory.rglob(\\\"*\\\" if recursive else \\\"[!.]*\\\"):\\n if len(p.parts) - prefix_length <= max_depth:\\n yield p\\n\\n glob = \\\"**/*\\\" if recursive else \\\"*\\\"\\n paths = walk_level(path_obj, depth) if depth else path_obj.glob(glob)\\n file_paths = [str(p) for p in paths if p.is_file() and match_types(p) and is_not_hidden(p)]\\n\\n return file_paths\\n\\n def parse_file_to_record(self, file_path: str, silent_errors: bool) -> Record:\\n # Use the partition function to load the file\\n from unstructured.partition.auto import partition\\n\\n try:\\n elements = partition(file_path)\\n except Exception as e:\\n if not silent_errors:\\n raise ValueError(f\\\"Error loading file {file_path}: {e}\\\") from e\\n return None\\n\\n # Create a Record\\n text = \\\"\\\\n\\\\n\\\".join([str(el) for el in elements])\\n metadata = elements.metadata if hasattr(elements, \\\"metadata\\\") else {}\\n metadata[\\\"file_path\\\"] = file_path\\n record = Record(text=text, data=metadata)\\n return record\\n\\n def get_elements(\\n self,\\n file_paths: List[str],\\n silent_errors: bool,\\n max_concurrency: int,\\n use_multithreading: bool,\\n ) -> List[Record]:\\n if use_multithreading:\\n records = self.parallel_load_records(file_paths, silent_errors, max_concurrency)\\n else:\\n records = [self.parse_file_to_record(file_path, silent_errors) for file_path in file_paths]\\n records = list(filter(None, records))\\n return records\\n\\n def parallel_load_records(self, file_paths: List[str], silent_errors: bool, max_concurrency: int) -> List[Record]:\\n with futures.ThreadPoolExecutor(max_workers=max_concurrency) as executor:\\n loaded_files = executor.map(\\n lambda file_path: self.parse_file_to_record(file_path, silent_errors),\\n file_paths,\\n )\\n return loaded_files\\n\\n def build(\\n self,\\n path: str,\\n types: List[str] = None,\\n depth: int = 0,\\n max_concurrency: int = 2,\\n load_hidden: bool = False,\\n recursive: bool = True,\\n silent_errors: bool = False,\\n use_multithreading: bool = True,\\n ) -> List[Record]:\\n resolved_path = self.resolve_path(path)\\n file_paths = self.retrieve_file_paths(resolved_path, types, load_hidden, recursive, depth)\\n loaded_records = []\\n\\n if use_multithreading:\\n loaded_records = self.parallel_load_records(file_paths, silent_errors, max_concurrency)\\n else:\\n loaded_records = [self.parse_file_to_record(file_path, silent_errors) for file_path in file_paths]\\n loaded_records = list(filter(None, loaded_records))\\n self.status = loaded_records\\n return loaded_records\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"depth\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"depth\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"load_hidden\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"load_hidden\",\"display_name\":\"Load Hidden Files\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"max_concurrency\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":10,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_concurrency\",\"display_name\":\"Max Concurrency\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"path\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"path\",\"display_name\":\"Local Directory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"recursive\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":true,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"recursive\",\"display_name\":\"Recursive\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"silent_errors\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"silent_errors\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"types\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"types\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"use_multithreading\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":true,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"use_multithreading\",\"display_name\":\"Use Multithreading\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Gather records from a directory.\",\"base_classes\":[\"Record\"],\"display_name\":\"Gather Records\",\"documentation\":\"\",\"custom_fields\":{\"path\":null,\"types\":null,\"depth\":null,\"max_concurrency\":null,\"load_hidden\":null,\"recursive\":null,\"silent_errors\":null,\"use_multithreading\":null},\"output_types\":[\"Record\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true}},\"textsplitters\":{\"CharacterTextSplitter\":{\"template\":{\"documents\":{\"type\":\"Document\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"chunk_overlap\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":200,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chunk_overlap\",\"display_name\":\"Chunk Overlap\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"chunk_size\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1000,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chunk_size\",\"display_name\":\"Chunk Size\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import List\\n\\nfrom langchain.text_splitter import CharacterTextSplitter\\nfrom langchain_core.documents.base import Document\\nfrom langflow import CustomComponent\\n\\n\\nclass CharacterTextSplitterComponent(CustomComponent):\\n display_name = \\\"CharacterTextSplitter\\\"\\n description = \\\"Splitting text that looks at characters.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"documents\\\": {\\\"display_name\\\": \\\"Documents\\\"},\\n \\\"chunk_overlap\\\": {\\\"display_name\\\": \\\"Chunk Overlap\\\", \\\"default\\\": 200},\\n \\\"chunk_size\\\": {\\\"display_name\\\": \\\"Chunk Size\\\", \\\"default\\\": 1000},\\n \\\"separator\\\": {\\\"display_name\\\": \\\"Separator\\\", \\\"default\\\": \\\"\\\\n\\\"},\\n }\\n\\n def build(\\n self,\\n documents: List[Document],\\n chunk_overlap: int = 200,\\n chunk_size: int = 1000,\\n separator: str = \\\"\\\\n\\\",\\n ) -> List[Document]:\\n # separator may come escaped from the frontend\\n separator = separator.encode().decode(\\\"unicode_escape\\\")\\n docs = CharacterTextSplitter(\\n chunk_overlap=chunk_overlap,\\n chunk_size=chunk_size,\\n separator=separator,\\n ).split_documents(documents)\\n self.status = docs\\n return docs\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"separator\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\\\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"separator\",\"display_name\":\"Separator\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Splitting text that looks at characters.\",\"base_classes\":[\"Serializable\",\"Document\"],\"display_name\":\"CharacterTextSplitter\",\"documentation\":\"\",\"custom_fields\":{\"documents\":null,\"chunk_overlap\":null,\"chunk_size\":null,\"separator\":null},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"RecursiveCharacterTextSplitter\":{\"template\":{\"documents\":{\"type\":\"Document\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"The documents to split.\",\"title_case\":false},\"chunk_overlap\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":200,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chunk_overlap\",\"display_name\":\"Chunk Overlap\",\"advanced\":false,\"dynamic\":false,\"info\":\"The amount of overlap between chunks.\",\"title_case\":false},\"chunk_size\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1000,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chunk_size\",\"display_name\":\"Chunk Size\",\"advanced\":false,\"dynamic\":false,\"info\":\"The maximum length of each chunk.\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain_core.documents import Document\\n\\nfrom langflow import CustomComponent\\nfrom langflow.utils.util import build_loader_repr_from_documents\\nfrom langchain.text_splitter import RecursiveCharacterTextSplitter\\n\\n\\nclass RecursiveCharacterTextSplitterComponent(CustomComponent):\\n display_name: str = \\\"Recursive Character Text Splitter\\\"\\n description: str = \\\"Split text into chunks of a specified length.\\\"\\n documentation: str = \\\"https://docs.langflow.org/components/text-splitters#recursivecharactertextsplitter\\\"\\n\\n def build_config(self):\\n return {\\n \\\"documents\\\": {\\n \\\"display_name\\\": \\\"Documents\\\",\\n \\\"info\\\": \\\"The documents to split.\\\",\\n },\\n \\\"separators\\\": {\\n \\\"display_name\\\": \\\"Separators\\\",\\n \\\"info\\\": 'The characters to split on.\\\\nIf left empty defaults to [\\\"\\\\\\\\n\\\\\\\\n\\\", \\\"\\\\\\\\n\\\", \\\" \\\", \\\"\\\"].',\\n \\\"is_list\\\": True,\\n },\\n \\\"chunk_size\\\": {\\n \\\"display_name\\\": \\\"Chunk Size\\\",\\n \\\"info\\\": \\\"The maximum length of each chunk.\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"value\\\": 1000,\\n },\\n \\\"chunk_overlap\\\": {\\n \\\"display_name\\\": \\\"Chunk Overlap\\\",\\n \\\"info\\\": \\\"The amount of overlap between chunks.\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"value\\\": 200,\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n documents: list[Document],\\n separators: Optional[list[str]] = None,\\n chunk_size: Optional[int] = 1000,\\n chunk_overlap: Optional[int] = 200,\\n ) -> list[Document]:\\n \\\"\\\"\\\"\\n Split text into chunks of a specified length.\\n\\n Args:\\n separators (list[str]): The characters to split on.\\n chunk_size (int): The maximum length of each chunk.\\n chunk_overlap (int): The amount of overlap between chunks.\\n length_function (function): The function to use to calculate the length of the text.\\n\\n Returns:\\n list[str]: The chunks of text.\\n \\\"\\\"\\\"\\n\\n if separators == \\\"\\\":\\n separators = None\\n elif separators:\\n # check if the separators list has escaped characters\\n # if there are escaped characters, unescape them\\n separators = [x.encode().decode(\\\"unicode-escape\\\") for x in separators]\\n\\n # Make sure chunk_size and chunk_overlap are ints\\n if isinstance(chunk_size, str):\\n chunk_size = int(chunk_size)\\n if isinstance(chunk_overlap, str):\\n chunk_overlap = int(chunk_overlap)\\n splitter = RecursiveCharacterTextSplitter(\\n separators=separators,\\n chunk_size=chunk_size,\\n chunk_overlap=chunk_overlap,\\n )\\n\\n docs = splitter.split_documents(documents)\\n self.repr_value = build_loader_repr_from_documents(docs)\\n return docs\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"separators\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"separators\",\"display_name\":\"Separators\",\"advanced\":false,\"dynamic\":false,\"info\":\"The characters to split on.\\nIf left empty defaults to [\\\"\\\\n\\\\n\\\", \\\"\\\\n\\\", \\\" \\\", \\\"\\\"].\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Split text into chunks of a specified length.\",\"base_classes\":[\"Serializable\",\"Document\"],\"display_name\":\"Recursive Character Text Splitter\",\"documentation\":\"https://docs.langflow.org/components/text-splitters#recursivecharactertextsplitter\",\"custom_fields\":{\"documents\":null,\"separators\":null,\"chunk_size\":null,\"chunk_overlap\":null},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"LanguageRecursiveTextSplitter\":{\"template\":{\"documents\":{\"type\":\"Document\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"The documents to split.\",\"title_case\":false},\"chunk_overlap\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":200,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chunk_overlap\",\"display_name\":\"Chunk Overlap\",\"advanced\":false,\"dynamic\":false,\"info\":\"The amount of overlap between chunks.\",\"title_case\":false},\"chunk_size\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1000,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chunk_size\",\"display_name\":\"Chunk Size\",\"advanced\":false,\"dynamic\":false,\"info\":\"The maximum length of each chunk.\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain.text_splitter import Language\\nfrom langchain_core.documents import Document\\n\\nfrom langflow import CustomComponent\\n\\n\\nclass LanguageRecursiveTextSplitterComponent(CustomComponent):\\n display_name: str = \\\"Language Recursive Text Splitter\\\"\\n description: str = \\\"Split text into chunks of a specified length based on language.\\\"\\n documentation: str = \\\"https://docs.langflow.org/components/text-splitters#languagerecursivetextsplitter\\\"\\n\\n def build_config(self):\\n options = [x.value for x in Language]\\n return {\\n \\\"documents\\\": {\\n \\\"display_name\\\": \\\"Documents\\\",\\n \\\"info\\\": \\\"The documents to split.\\\",\\n },\\n \\\"separator_type\\\": {\\n \\\"display_name\\\": \\\"Separator Type\\\",\\n \\\"info\\\": \\\"The type of separator to use.\\\",\\n \\\"field_type\\\": \\\"str\\\",\\n \\\"options\\\": options,\\n \\\"value\\\": \\\"Python\\\",\\n },\\n \\\"separators\\\": {\\n \\\"display_name\\\": \\\"Separators\\\",\\n \\\"info\\\": \\\"The characters to split on.\\\",\\n \\\"is_list\\\": True,\\n },\\n \\\"chunk_size\\\": {\\n \\\"display_name\\\": \\\"Chunk Size\\\",\\n \\\"info\\\": \\\"The maximum length of each chunk.\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"value\\\": 1000,\\n },\\n \\\"chunk_overlap\\\": {\\n \\\"display_name\\\": \\\"Chunk Overlap\\\",\\n \\\"info\\\": \\\"The amount of overlap between chunks.\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"value\\\": 200,\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n documents: list[Document],\\n chunk_size: Optional[int] = 1000,\\n chunk_overlap: Optional[int] = 200,\\n separator_type: str = \\\"Python\\\",\\n ) -> list[Document]:\\n \\\"\\\"\\\"\\n Split text into chunks of a specified length.\\n\\n Args:\\n separators (list[str]): The characters to split on.\\n chunk_size (int): The maximum length of each chunk.\\n chunk_overlap (int): The amount of overlap between chunks.\\n length_function (function): The function to use to calculate the length of the text.\\n\\n Returns:\\n list[str]: The chunks of text.\\n \\\"\\\"\\\"\\n from langchain.text_splitter import RecursiveCharacterTextSplitter\\n\\n # Make sure chunk_size and chunk_overlap are ints\\n if isinstance(chunk_size, str):\\n chunk_size = int(chunk_size)\\n if isinstance(chunk_overlap, str):\\n chunk_overlap = int(chunk_overlap)\\n\\n splitter = RecursiveCharacterTextSplitter.from_language(\\n language=Language(separator_type),\\n chunk_size=chunk_size,\\n chunk_overlap=chunk_overlap,\\n )\\n\\n docs = splitter.split_documents(documents)\\n return docs\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"separator_type\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"Python\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"cpp\",\"go\",\"java\",\"kotlin\",\"js\",\"ts\",\"php\",\"proto\",\"python\",\"rst\",\"ruby\",\"rust\",\"scala\",\"swift\",\"markdown\",\"latex\",\"html\",\"sol\",\"csharp\",\"cobol\",\"c\",\"lua\",\"perl\"],\"name\":\"separator_type\",\"display_name\":\"Separator Type\",\"advanced\":false,\"dynamic\":false,\"info\":\"The type of separator to use.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Split text into chunks of a specified length based on language.\",\"base_classes\":[\"Serializable\",\"Document\"],\"display_name\":\"Language Recursive Text Splitter\",\"documentation\":\"https://docs.langflow.org/components/text-splitters#languagerecursivetextsplitter\",\"custom_fields\":{\"documents\":null,\"chunk_size\":null,\"chunk_overlap\":null,\"separator_type\":null},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true}},\"utilities\":{\"BingSearchAPIWrapper\":{\"template\":{\"bing_search_url\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"bing_search_url\",\"display_name\":\"Bing Search URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"bing_subscription_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"bing_subscription_key\",\"display_name\":\"Bing Subscription Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\n\\n# Assuming `BingSearchAPIWrapper` is a class that exists in the context\\n# and has the appropriate methods and attributes.\\n# We need to make sure this class is importable from the context where this code will be running.\\nfrom langchain_community.utilities.bing_search import BingSearchAPIWrapper\\n\\n\\nclass BingSearchAPIWrapperComponent(CustomComponent):\\n display_name = \\\"BingSearchAPIWrapper\\\"\\n description = \\\"Wrapper for Bing Search API.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"bing_search_url\\\": {\\\"display_name\\\": \\\"Bing Search URL\\\"},\\n \\\"bing_subscription_key\\\": {\\n \\\"display_name\\\": \\\"Bing Subscription Key\\\",\\n \\\"password\\\": True,\\n },\\n \\\"k\\\": {\\\"display_name\\\": \\\"Number of results\\\", \\\"advanced\\\": True},\\n # 'k' is not included as it is not shown (show=False)\\n }\\n\\n def build(\\n self,\\n bing_search_url: str,\\n bing_subscription_key: str,\\n k: int = 10,\\n ) -> BingSearchAPIWrapper:\\n # 'k' has a default value and is not shown (show=False), so it is hardcoded here\\n return BingSearchAPIWrapper(bing_search_url=bing_search_url, bing_subscription_key=bing_subscription_key, k=k)\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"k\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":10,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"k\",\"display_name\":\"Number of results\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Wrapper for Bing Search API.\",\"base_classes\":[\"BingSearchAPIWrapper\"],\"display_name\":\"BingSearchAPIWrapper\",\"documentation\":\"\",\"custom_fields\":{\"bing_search_url\":null,\"bing_subscription_key\":null,\"k\":null},\"output_types\":[\"BingSearchAPIWrapper\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"GoogleSearchAPIWrapper\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Callable, Union\\n\\nfrom langchain_community.utilities.google_search import GoogleSearchAPIWrapper\\nfrom langflow import CustomComponent\\n\\n\\nclass GoogleSearchAPIWrapperComponent(CustomComponent):\\n display_name = \\\"GoogleSearchAPIWrapper\\\"\\n description = \\\"Wrapper for Google Search API.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"google_api_key\\\": {\\\"display_name\\\": \\\"Google API Key\\\", \\\"password\\\": True},\\n \\\"google_cse_id\\\": {\\\"display_name\\\": \\\"Google CSE ID\\\", \\\"password\\\": True},\\n }\\n\\n def build(\\n self,\\n google_api_key: str,\\n google_cse_id: str,\\n ) -> Union[GoogleSearchAPIWrapper, Callable]:\\n return GoogleSearchAPIWrapper(google_api_key=google_api_key, google_cse_id=google_cse_id) # type: ignore\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"google_api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"google_api_key\",\"display_name\":\"Google API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"google_cse_id\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"google_cse_id\",\"display_name\":\"Google CSE ID\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Wrapper for Google Search API.\",\"base_classes\":[\"GoogleSearchAPIWrapper\",\"Callable\"],\"display_name\":\"GoogleSearchAPIWrapper\",\"documentation\":\"\",\"custom_fields\":{\"google_api_key\":null,\"google_cse_id\":null},\"output_types\":[\"GoogleSearchAPIWrapper\",\"Callable\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"GoogleSerperAPIWrapper\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Dict\\n\\n# Assuming the existence of GoogleSerperAPIWrapper class in the serper module\\n# If this class does not exist, you would need to create it or import the appropriate class from another module\\nfrom langchain_community.utilities.google_serper import GoogleSerperAPIWrapper\\n\\nfrom langflow import CustomComponent\\n\\n\\nclass GoogleSerperAPIWrapperComponent(CustomComponent):\\n display_name = \\\"GoogleSerperAPIWrapper\\\"\\n description = \\\"Wrapper around the Serper.dev Google Search API.\\\"\\n\\n def build_config(self) -> Dict[str, Dict]:\\n return {\\n \\\"result_key_for_type\\\": {\\n \\\"display_name\\\": \\\"Result Key for Type\\\",\\n \\\"show\\\": True,\\n \\\"multiline\\\": False,\\n \\\"password\\\": False,\\n \\\"advanced\\\": False,\\n \\\"dynamic\\\": False,\\n \\\"info\\\": \\\"\\\",\\n \\\"field_type\\\": \\\"dict\\\",\\n \\\"list\\\": False,\\n \\\"value\\\": {\\n \\\"news\\\": \\\"news\\\",\\n \\\"places\\\": \\\"places\\\",\\n \\\"images\\\": \\\"images\\\",\\n \\\"search\\\": \\\"organic\\\",\\n },\\n },\\n \\\"serper_api_key\\\": {\\n \\\"display_name\\\": \\\"Serper API Key\\\",\\n \\\"show\\\": True,\\n \\\"multiline\\\": False,\\n \\\"password\\\": True,\\n \\\"advanced\\\": False,\\n \\\"dynamic\\\": False,\\n \\\"info\\\": \\\"\\\",\\n \\\"type\\\": \\\"str\\\",\\n \\\"list\\\": False,\\n },\\n }\\n\\n def build(\\n self,\\n serper_api_key: str,\\n ) -> GoogleSerperAPIWrapper:\\n return GoogleSerperAPIWrapper(serper_api_key=serper_api_key)\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"serper_api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"serper_api_key\",\"display_name\":\"Serper API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Wrapper around the Serper.dev Google Search API.\",\"base_classes\":[\"GoogleSerperAPIWrapper\"],\"display_name\":\"GoogleSerperAPIWrapper\",\"documentation\":\"\",\"custom_fields\":{\"serper_api_key\":null},\"output_types\":[\"GoogleSerperAPIWrapper\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"SearxSearchWrapper\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom typing import Optional, Dict\\nfrom langchain_community.utilities.searx_search import SearxSearchWrapper\\n\\n\\nclass SearxSearchWrapperComponent(CustomComponent):\\n display_name = \\\"SearxSearchWrapper\\\"\\n description = \\\"Wrapper for Searx API.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"headers\\\": {\\n \\\"field_type\\\": \\\"dict\\\",\\n \\\"display_name\\\": \\\"Headers\\\",\\n \\\"multiline\\\": True,\\n \\\"value\\\": '{\\\"Authorization\\\": \\\"Bearer \\\"}',\\n },\\n \\\"k\\\": {\\\"display_name\\\": \\\"k\\\", \\\"advanced\\\": True, \\\"field_type\\\": \\\"int\\\", \\\"value\\\": 10},\\n \\\"searx_host\\\": {\\n \\\"display_name\\\": \\\"Searx Host\\\",\\n \\\"field_type\\\": \\\"str\\\",\\n \\\"value\\\": \\\"https://searx.example.com\\\",\\n \\\"advanced\\\": True,\\n },\\n }\\n\\n def build(\\n self,\\n k: int = 10,\\n headers: Optional[Dict[str, str]] = None,\\n searx_host: str = \\\"https://searx.example.com\\\",\\n ) -> SearxSearchWrapper:\\n return SearxSearchWrapper(headers=headers, k=k, searx_host=searx_host)\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"headers\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"{\\\"Authorization\\\": \\\"Bearer \\\"}\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"headers\",\"display_name\":\"Headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"k\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":10,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"k\",\"display_name\":\"k\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"searx_host\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"https://searx.example.com\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"searx_host\",\"display_name\":\"Searx Host\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Wrapper for Searx API.\",\"base_classes\":[\"SearxSearchWrapper\"],\"display_name\":\"SearxSearchWrapper\",\"documentation\":\"\",\"custom_fields\":{\"k\":null,\"headers\":null,\"searx_host\":null},\"output_types\":[\"SearxSearchWrapper\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"SerpAPIWrapper\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Callable, Union\\n\\nfrom langchain_community.utilities.serpapi import SerpAPIWrapper\\nfrom langflow import CustomComponent\\n\\n\\nclass SerpAPIWrapperComponent(CustomComponent):\\n display_name = \\\"SerpAPIWrapper\\\"\\n description = \\\"Wrapper around SerpAPI\\\"\\n\\n def build_config(self):\\n return {\\n \\\"serpapi_api_key\\\": {\\\"display_name\\\": \\\"SerpAPI API Key\\\", \\\"type\\\": \\\"str\\\", \\\"password\\\": True},\\n \\\"params\\\": {\\n \\\"display_name\\\": \\\"Parameters\\\",\\n \\\"type\\\": \\\"dict\\\",\\n \\\"advanced\\\": True,\\n \\\"multiline\\\": True,\\n \\\"value\\\": '{\\\"engine\\\": \\\"google\\\",\\\"google_domain\\\": \\\"google.com\\\",\\\"gl\\\": \\\"us\\\",\\\"hl\\\": \\\"en\\\"}',\\n },\\n }\\n\\n def build(\\n self,\\n serpapi_api_key: str,\\n params: dict,\\n ) -> Union[SerpAPIWrapper, Callable]: # Removed quotes around SerpAPIWrapper\\n return SerpAPIWrapper( # type: ignore\\n serpapi_api_key=serpapi_api_key,\\n params=params,\\n )\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"params\":{\"type\":\"dict\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"{\\\"engine\\\": \\\"google\\\",\\\"google_domain\\\": \\\"google.com\\\",\\\"gl\\\": \\\"us\\\",\\\"hl\\\": \\\"en\\\"}\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"params\",\"display_name\":\"Parameters\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"serpapi_api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"serpapi_api_key\",\"display_name\":\"SerpAPI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Wrapper around SerpAPI\",\"base_classes\":[\"Callable\",\"SerpAPIWrapper\"],\"display_name\":\"SerpAPIWrapper\",\"documentation\":\"\",\"custom_fields\":{\"serpapi_api_key\":null,\"params\":null},\"output_types\":[\"SerpAPIWrapper\",\"Callable\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"WikipediaAPIWrapper\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Callable, Union\\n\\nfrom langchain_community.utilities.wikipedia import WikipediaAPIWrapper\\nfrom langflow import CustomComponent\\n\\n# Assuming WikipediaAPIWrapper is a class that needs to be imported.\\n# The import statement is not included as it is not provided in the JSON\\n# and the actual implementation details are unknown.\\n\\n\\nclass WikipediaAPIWrapperComponent(CustomComponent):\\n display_name = \\\"WikipediaAPIWrapper\\\"\\n description = \\\"Wrapper around WikipediaAPI.\\\"\\n\\n def build_config(self):\\n return {}\\n\\n def build(\\n self,\\n top_k_results: int = 3,\\n lang: str = \\\"en\\\",\\n load_all_available_meta: bool = False,\\n doc_content_chars_max: int = 4000,\\n ) -> Union[WikipediaAPIWrapper, Callable]:\\n return WikipediaAPIWrapper( # type: ignore\\n top_k_results=top_k_results,\\n lang=lang,\\n load_all_available_meta=load_all_available_meta,\\n doc_content_chars_max=doc_content_chars_max,\\n )\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"doc_content_chars_max\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":4000,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"doc_content_chars_max\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"lang\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"en\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"lang\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"load_all_available_meta\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"load_all_available_meta\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"top_k_results\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":3,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_k_results\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Wrapper around WikipediaAPI.\",\"base_classes\":[\"WikipediaAPIWrapper\",\"Callable\"],\"display_name\":\"WikipediaAPIWrapper\",\"documentation\":\"\",\"custom_fields\":{\"top_k_results\":null,\"lang\":null,\"load_all_available_meta\":null,\"doc_content_chars_max\":null},\"output_types\":[\"WikipediaAPIWrapper\",\"Callable\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"WolframAlphaAPIWrapper\":{\"template\":{\"appid\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"appid\",\"display_name\":\"App ID\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Callable, Union\\n\\nfrom langchain_community.utilities.wolfram_alpha import WolframAlphaAPIWrapper\\nfrom langflow import CustomComponent\\n\\n# Since all the fields in the JSON have show=False, we will only create a basic component\\n# without any configurable fields.\\n\\n\\nclass WolframAlphaAPIWrapperComponent(CustomComponent):\\n display_name = \\\"WolframAlphaAPIWrapper\\\"\\n description = \\\"Wrapper for Wolfram Alpha.\\\"\\n\\n def build_config(self):\\n return {\\\"appid\\\": {\\\"display_name\\\": \\\"App ID\\\", \\\"type\\\": \\\"str\\\", \\\"password\\\": True}}\\n\\n def build(self, appid: str) -> Union[Callable, WolframAlphaAPIWrapper]:\\n return WolframAlphaAPIWrapper(wolfram_alpha_appid=appid) # type: ignore\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Wrapper for Wolfram Alpha.\",\"base_classes\":[\"WolframAlphaAPIWrapper\",\"Callable\"],\"display_name\":\"WolframAlphaAPIWrapper\",\"documentation\":\"\",\"custom_fields\":{\"appid\":null},\"output_types\":[\"Callable\",\"WolframAlphaAPIWrapper\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"RunnableExecutor\":{\"template\":{\"runnable\":{\"type\":\"Runnable\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"runnable\",\"display_name\":\"Runnable\",\"advanced\":false,\"dynamic\":false,\"info\":\"The runnable to execute.\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langchain_core.runnables import Runnable\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Text\\n\\n\\nclass RunnableExecComponent(CustomComponent):\\n documentation: str = \\\"http://docs.langflow.org/components/custom\\\"\\n display_name = \\\"Runnable Executor\\\"\\n beta = True\\n\\n def build_config(self):\\n return {\\n \\\"input_key\\\": {\\n \\\"display_name\\\": \\\"Input Key\\\",\\n \\\"info\\\": \\\"The key to use for the input.\\\",\\n },\\n \\\"inputs\\\": {\\n \\\"display_name\\\": \\\"Inputs\\\",\\n \\\"info\\\": \\\"The inputs to pass to the runnable.\\\",\\n },\\n \\\"runnable\\\": {\\n \\\"display_name\\\": \\\"Runnable\\\",\\n \\\"info\\\": \\\"The runnable to execute.\\\",\\n },\\n \\\"output_key\\\": {\\n \\\"display_name\\\": \\\"Output Key\\\",\\n \\\"info\\\": \\\"The key to use for the output.\\\",\\n },\\n }\\n\\n def build(\\n self,\\n input_key: str,\\n inputs: str,\\n runnable: Runnable,\\n output_key: str = \\\"output\\\",\\n ) -> Text:\\n result = runnable.invoke({input_key: inputs})\\n result = result.get(output_key)\\n self.status = result\\n return result\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"input_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"input_key\",\"display_name\":\"Input Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The key to use for the input.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"inputs\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"inputs\",\"display_name\":\"Inputs\",\"advanced\":false,\"dynamic\":false,\"info\":\"The inputs to pass to the runnable.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"output_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"output\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"output_key\",\"display_name\":\"Output Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The key to use for the output.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"base_classes\":[\"Text\",\"object\"],\"display_name\":\"Runnable Executor\",\"documentation\":\"http://docs.langflow.org/components/custom\",\"custom_fields\":{\"input_key\":null,\"inputs\":null,\"runnable\":null,\"output_key\":null},\"output_types\":[\"Text\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"DocumentToRecord\":{\"template\":{\"documents\":{\"type\":\"Document\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import List\\n\\nfrom langchain_core.documents import Document\\n\\nfrom langflow import CustomComponent\\nfrom langflow.schema import Record\\n\\n\\nclass DocumentToRecordComponent(CustomComponent):\\n display_name = \\\"Documents to Records\\\"\\n description = \\\"Convert documents to records.\\\"\\n\\n field_config = {\\n \\\"documents\\\": {\\\"display_name\\\": \\\"Documents\\\"},\\n }\\n\\n def build(self, documents: List[Document]) -> List[Record]:\\n if isinstance(documents, Document):\\n documents = [documents]\\n records = [Record.from_document(document) for document in documents]\\n self.status = records\\n return records\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Convert documents to records.\",\"base_classes\":[\"Record\"],\"display_name\":\"Documents to Records\",\"documentation\":\"\",\"custom_fields\":{\"documents\":null},\"output_types\":[\"Record\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"GetRequest\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nimport requests\\nfrom langchain_core.documents import Document\\nfrom langflow import CustomComponent\\nfrom langflow.services.database.models.base import orjson_dumps\\n\\n\\nclass GetRequest(CustomComponent):\\n display_name: str = \\\"GET Request\\\"\\n description: str = \\\"Make a GET request to the given URL.\\\"\\n output_types: list[str] = [\\\"Document\\\"]\\n documentation: str = \\\"https://docs.langflow.org/components/utilities#get-request\\\"\\n beta: bool = True\\n field_config = {\\n \\\"url\\\": {\\n \\\"display_name\\\": \\\"URL\\\",\\n \\\"info\\\": \\\"The URL to make the request to\\\",\\n \\\"is_list\\\": True,\\n },\\n \\\"headers\\\": {\\n \\\"display_name\\\": \\\"Headers\\\",\\n \\\"info\\\": \\\"The headers to send with the request.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n \\\"timeout\\\": {\\n \\\"display_name\\\": \\\"Timeout\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"info\\\": \\\"The timeout to use for the request.\\\",\\n \\\"value\\\": 5,\\n },\\n }\\n\\n def get_document(self, session: requests.Session, url: str, headers: Optional[dict], timeout: int) -> Document:\\n try:\\n response = session.get(url, headers=headers, timeout=int(timeout))\\n try:\\n response_json = response.json()\\n result = orjson_dumps(response_json, indent_2=False)\\n except Exception:\\n result = response.text\\n self.repr_value = result\\n return Document(\\n page_content=result,\\n metadata={\\n \\\"source\\\": url,\\n \\\"headers\\\": headers,\\n \\\"status_code\\\": response.status_code,\\n },\\n )\\n except requests.Timeout:\\n return Document(\\n page_content=\\\"Request Timed Out\\\",\\n metadata={\\\"source\\\": url, \\\"headers\\\": headers, \\\"status_code\\\": 408},\\n )\\n except Exception as exc:\\n return Document(\\n page_content=str(exc),\\n metadata={\\\"source\\\": url, \\\"headers\\\": headers, \\\"status_code\\\": 500},\\n )\\n\\n def build(\\n self,\\n url: str,\\n headers: Optional[dict] = None,\\n timeout: int = 5,\\n ) -> list[Document]:\\n if headers is None:\\n headers = {}\\n urls = url if isinstance(url, list) else [url]\\n with requests.Session() as session:\\n documents = [self.get_document(session, u, headers, timeout) for u in urls]\\n self.repr_value = documents\\n return documents\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"headers\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"headers\",\"display_name\":\"Headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"The headers to send with the request.\",\"title_case\":false},\"timeout\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":5,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"timeout\",\"display_name\":\"Timeout\",\"advanced\":false,\"dynamic\":false,\"info\":\"The timeout to use for the request.\",\"title_case\":false},\"url\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"url\",\"display_name\":\"URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"The URL to make the request to\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Make a GET request to the given URL.\",\"base_classes\":[\"Serializable\",\"Document\"],\"display_name\":\"GET Request\",\"documentation\":\"https://docs.langflow.org/components/utilities#get-request\",\"custom_fields\":{\"url\":null,\"headers\":null,\"timeout\":null},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"SQLExecutor\":{\"template\":{\"database\":{\"type\":\"SQLDatabase\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"database\",\"display_name\":\"Database\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"add_error\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"add_error\",\"display_name\":\"Add Error\",\"advanced\":false,\"dynamic\":false,\"info\":\"Add the error to the result.\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langchain_community.tools.sql_database.tool import QuerySQLDataBaseTool\\nfrom langchain_experimental.sql.base import SQLDatabase\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Text\\n\\n\\nclass SQLExecutorComponent(CustomComponent):\\n display_name = \\\"SQL Executor\\\"\\n description = \\\"Execute SQL query.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"database\\\": {\\\"display_name\\\": \\\"Database\\\"},\\n \\\"include_columns\\\": {\\n \\\"display_name\\\": \\\"Include Columns\\\",\\n \\\"info\\\": \\\"Include columns in the result.\\\",\\n },\\n \\\"passthrough\\\": {\\n \\\"display_name\\\": \\\"Passthrough\\\",\\n \\\"info\\\": \\\"If an error occurs, return the query instead of raising an exception.\\\",\\n },\\n \\\"add_error\\\": {\\n \\\"display_name\\\": \\\"Add Error\\\",\\n \\\"info\\\": \\\"Add the error to the result.\\\",\\n },\\n }\\n\\n def build(\\n self,\\n query: str,\\n database: SQLDatabase,\\n include_columns: bool = False,\\n passthrough: bool = False,\\n add_error: bool = False,\\n ) -> Text:\\n error = None\\n try:\\n tool = QuerySQLDataBaseTool(db=database)\\n result = tool.run(query, include_columns=include_columns)\\n self.status = result\\n except Exception as e:\\n result = str(e)\\n self.status = result\\n if not passthrough:\\n raise e\\n error = repr(e)\\n\\n if add_error and error is not None:\\n result = f\\\"{result}\\\\n\\\\nError: {error}\\\\n\\\\nQuery: {query}\\\"\\n elif error is not None:\\n # Then we won't add the error to the result\\n # but since we are in passthrough mode, we will return the query\\n result = query\\n\\n return result\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"include_columns\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"include_columns\",\"display_name\":\"Include Columns\",\"advanced\":false,\"dynamic\":false,\"info\":\"Include columns in the result.\",\"title_case\":false},\"passthrough\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"passthrough\",\"display_name\":\"Passthrough\",\"advanced\":false,\"dynamic\":false,\"info\":\"If an error occurs, return the query instead of raising an exception.\",\"title_case\":false},\"query\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"query\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Execute SQL query.\",\"base_classes\":[\"Text\",\"object\"],\"display_name\":\"SQL Executor\",\"documentation\":\"\",\"custom_fields\":{\"query\":null,\"database\":null,\"include_columns\":null,\"passthrough\":null,\"add_error\":null},\"output_types\":[\"Text\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"ShouldRunNext\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"The language model to use for the decision.\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"# Implement ShouldRunNext component\\nfrom langchain_core.prompts import PromptTemplate\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import BaseLanguageModel, Prompt\\n\\n\\nclass ShouldRunNext(CustomComponent):\\n display_name = \\\"Should Run Next\\\"\\n description = \\\"Decides whether to run the next component.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"prompt\\\": {\\n \\\"display_name\\\": \\\"Prompt\\\",\\n \\\"info\\\": \\\"The prompt to use for the decision. It should generate a boolean response (True or False).\\\",\\n },\\n \\\"llm\\\": {\\n \\\"display_name\\\": \\\"LLM\\\",\\n \\\"info\\\": \\\"The language model to use for the decision.\\\",\\n },\\n }\\n\\n def build(self, template: Prompt, llm: BaseLanguageModel, **kwargs) -> dict:\\n # This is a simple component that always returns True\\n prompt_template = PromptTemplate.from_template(template)\\n\\n attributes_to_check = [\\\"text\\\", \\\"page_content\\\"]\\n for key, value in kwargs.items():\\n for attribute in attributes_to_check:\\n if hasattr(value, attribute):\\n kwargs[key] = getattr(value, attribute)\\n\\n chain = prompt_template | llm\\n result = chain.invoke(kwargs)\\n if hasattr(result, \\\"content\\\") and isinstance(result.content, str):\\n result = result.content\\n elif isinstance(result, str):\\n result = result\\n else:\\n result = result.get(\\\"response\\\")\\n\\n if result.lower() not in [\\\"true\\\", \\\"false\\\"]:\\n raise ValueError(\\\"The prompt should generate a boolean response (True or False).\\\")\\n # The string should be the words true or false\\n # if not raise an error\\n bool_result = result.lower() == \\\"true\\\"\\n return {\\\"condition\\\": bool_result, \\\"result\\\": kwargs}\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"template\":{\"type\":\"prompt\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"template\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Decides whether to run the next component.\",\"base_classes\":[\"object\",\"dict\"],\"display_name\":\"Should Run Next\",\"documentation\":\"\",\"custom_fields\":{\"template\":null,\"llm\":null},\"output_types\":[\"dict\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"PythonFunction\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Callable\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Code\\nfrom langflow.interface.custom.utils import get_function\\n\\n\\nclass PythonFunctionComponent(CustomComponent):\\n display_name = \\\"Python Function\\\"\\n description = \\\"Define a Python function.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"function_code\\\": {\\n \\\"display_name\\\": \\\"Code\\\",\\n \\\"info\\\": \\\"The code for the function.\\\",\\n \\\"show\\\": True,\\n },\\n }\\n\\n def build(self, function_code: Code) -> Callable:\\n self.status = function_code\\n func = get_function(function_code)\\n return func\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"function_code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"function_code\",\"display_name\":\"Code\",\"advanced\":false,\"dynamic\":false,\"info\":\"The code for the function.\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Define a Python function.\",\"base_classes\":[\"Callable\"],\"display_name\":\"Python Function\",\"documentation\":\"\",\"custom_fields\":{\"function_code\":null},\"output_types\":[\"Callable\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"PostRequest\":{\"template\":{\"document\":{\"type\":\"Document\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"document\",\"display_name\":\"Document\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nimport requests\\nfrom langchain_core.documents import Document\\nfrom langflow import CustomComponent\\nfrom langflow.services.database.models.base import orjson_dumps\\n\\n\\nclass PostRequest(CustomComponent):\\n display_name: str = \\\"POST Request\\\"\\n description: str = \\\"Make a POST request to the given URL.\\\"\\n output_types: list[str] = [\\\"Document\\\"]\\n documentation: str = \\\"https://docs.langflow.org/components/utilities#post-request\\\"\\n beta: bool = True\\n field_config = {\\n \\\"url\\\": {\\\"display_name\\\": \\\"URL\\\", \\\"info\\\": \\\"The URL to make the request to.\\\"},\\n \\\"headers\\\": {\\n \\\"display_name\\\": \\\"Headers\\\",\\n \\\"info\\\": \\\"The headers to send with the request.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n \\\"document\\\": {\\\"display_name\\\": \\\"Document\\\"},\\n }\\n\\n def post_document(\\n self,\\n session: requests.Session,\\n document: Document,\\n url: str,\\n headers: Optional[dict] = None,\\n ) -> Document:\\n try:\\n response = session.post(url, headers=headers, data=document.page_content)\\n try:\\n response_json = response.json()\\n result = orjson_dumps(response_json, indent_2=False)\\n except Exception:\\n result = response.text\\n self.repr_value = result\\n return Document(\\n page_content=result,\\n metadata={\\n \\\"source\\\": url,\\n \\\"headers\\\": headers,\\n \\\"status_code\\\": response,\\n },\\n )\\n except Exception as exc:\\n return Document(\\n page_content=str(exc),\\n metadata={\\n \\\"source\\\": url,\\n \\\"headers\\\": headers,\\n \\\"status_code\\\": 500,\\n },\\n )\\n\\n def build(\\n self,\\n document: Document,\\n url: str,\\n headers: Optional[dict] = None,\\n ) -> list[Document]:\\n if headers is None:\\n headers = {}\\n\\n if not isinstance(document, list) and isinstance(document, Document):\\n documents: list[Document] = [document]\\n elif isinstance(document, list) and all(isinstance(doc, Document) for doc in document):\\n documents = document\\n else:\\n raise ValueError(\\\"document must be a Document or a list of Documents\\\")\\n\\n with requests.Session() as session:\\n documents = [self.post_document(session, doc, url, headers) for doc in documents]\\n self.repr_value = documents\\n return documents\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"headers\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"headers\",\"display_name\":\"Headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"The headers to send with the request.\",\"title_case\":false},\"url\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"url\",\"display_name\":\"URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"The URL to make the request to.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Make a POST request to the given URL.\",\"base_classes\":[\"Serializable\",\"Document\"],\"display_name\":\"POST Request\",\"documentation\":\"https://docs.langflow.org/components/utilities#post-request\",\"custom_fields\":{\"document\":null,\"url\":null,\"headers\":null},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"IDGenerator\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"import uuid\\n\\nfrom langflow import CustomComponent\\n\\n\\nclass UUIDGeneratorComponent(CustomComponent):\\n documentation: str = \\\"http://docs.langflow.org/components/custom\\\"\\n display_name = \\\"Unique ID Generator\\\"\\n description = \\\"Generates a unique ID.\\\"\\n\\n def generate(self, *args, **kwargs):\\n return str(uuid.uuid4().hex)\\n\\n def build_config(self):\\n return {\\\"unique_id\\\": {\\\"display_name\\\": \\\"Value\\\", \\\"value\\\": self.generate}}\\n\\n def build(self, unique_id: str) -> str:\\n return unique_id\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"unique_id\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"a62d43140aba4c799af4ddc400295790\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"unique_id\",\"display_name\":\"Value\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"refresh\":true,\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Generates a unique ID.\",\"base_classes\":[\"object\",\"str\"],\"display_name\":\"Unique ID Generator\",\"documentation\":\"http://docs.langflow.org/components/custom\",\"custom_fields\":{\"unique_id\":null},\"output_types\":[\"str\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"SQLDatabase\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langchain_experimental.sql.base import SQLDatabase\\n\\nfrom langflow import CustomComponent\\n\\n\\nclass SQLDatabaseComponent(CustomComponent):\\n display_name = \\\"SQLDatabase\\\"\\n description = \\\"SQL Database\\\"\\n\\n def build_config(self):\\n return {\\n \\\"uri\\\": {\\\"display_name\\\": \\\"URI\\\", \\\"info\\\": \\\"URI to the database.\\\"},\\n }\\n\\n def clean_up_uri(self, uri: str) -> str:\\n if uri.startswith(\\\"postgresql://\\\"):\\n uri = uri.replace(\\\"postgresql://\\\", \\\"postgres://\\\")\\n return uri.strip()\\n\\n def build(self, uri: str) -> SQLDatabase:\\n uri = self.clean_up_uri(uri)\\n return SQLDatabase.from_uri(uri)\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"uri\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"uri\",\"display_name\":\"URI\",\"advanced\":false,\"dynamic\":false,\"info\":\"URI to the database.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"SQL Database\",\"base_classes\":[\"object\",\"SQLDatabase\"],\"display_name\":\"SQLDatabase\",\"documentation\":\"\",\"custom_fields\":{\"uri\":null},\"output_types\":[\"SQLDatabase\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"RecordsAsText\":{\"template\":{\"records\":{\"type\":\"Record\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"records\",\"display_name\":\"Records\",\"advanced\":false,\"dynamic\":false,\"info\":\"The records to convert to text.\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Text\\nfrom langflow.schema import Record\\n\\n\\nclass RecordsAsTextComponent(CustomComponent):\\n display_name = \\\"Records to Text\\\"\\n description = \\\"Converts Records a list of Records to text using a template.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"records\\\": {\\n \\\"display_name\\\": \\\"Records\\\",\\n \\\"info\\\": \\\"The records to convert to text.\\\",\\n },\\n \\\"template\\\": {\\n \\\"display_name\\\": \\\"Template\\\",\\n \\\"info\\\": \\\"The template to use for formatting the records. It must contain the keys {text} and {data}.\\\",\\n },\\n }\\n\\n def build(\\n self,\\n records: list[Record],\\n template: str = \\\"Text: {text}\\\\nData: {data}\\\",\\n ) -> Text:\\n if isinstance(records, Record):\\n records = [records]\\n\\n formated_records = [\\n template.format(text=record.text, data=record.data, **record.data)\\n for record in records\\n ]\\n result_string = \\\"\\\\n\\\".join(formated_records)\\n self.status = result_string\\n return result_string\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"template\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"Text: {text}\\\\nData: {data}\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"template\",\"display_name\":\"Template\",\"advanced\":false,\"dynamic\":false,\"info\":\"The template to use for formatting the records. It must contain the keys {text} and {data}.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Converts Records a list of Records to text using a template.\",\"base_classes\":[\"Text\",\"object\"],\"display_name\":\"Records to Text\",\"documentation\":\"\",\"custom_fields\":{\"records\":null,\"template\":null},\"output_types\":[\"Text\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"UpdateRequest\":{\"template\":{\"document\":{\"type\":\"Document\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"document\",\"display_name\":\"Document\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import List, Optional\\n\\nimport requests\\nfrom langchain_core.documents import Document\\nfrom langflow import CustomComponent\\nfrom langflow.services.database.models.base import orjson_dumps\\n\\n\\nclass UpdateRequest(CustomComponent):\\n display_name: str = \\\"Update Request\\\"\\n description: str = \\\"Make a PATCH request to the given URL.\\\"\\n output_types: list[str] = [\\\"Document\\\"]\\n documentation: str = \\\"https://docs.langflow.org/components/utilities#update-request\\\"\\n beta: bool = True\\n field_config = {\\n \\\"url\\\": {\\\"display_name\\\": \\\"URL\\\", \\\"info\\\": \\\"The URL to make the request to.\\\"},\\n \\\"headers\\\": {\\n \\\"display_name\\\": \\\"Headers\\\",\\n \\\"field_type\\\": \\\"NestedDict\\\",\\n \\\"info\\\": \\\"The headers to send with the request.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n \\\"document\\\": {\\\"display_name\\\": \\\"Document\\\"},\\n \\\"method\\\": {\\n \\\"display_name\\\": \\\"Method\\\",\\n \\\"field_type\\\": \\\"str\\\",\\n \\\"info\\\": \\\"The HTTP method to use.\\\",\\n \\\"options\\\": [\\\"PATCH\\\", \\\"PUT\\\"],\\n \\\"value\\\": \\\"PATCH\\\",\\n },\\n }\\n\\n def update_document(\\n self,\\n session: requests.Session,\\n document: Document,\\n url: str,\\n headers: Optional[dict] = None,\\n method: str = \\\"PATCH\\\",\\n ) -> Document:\\n try:\\n if method == \\\"PATCH\\\":\\n response = session.patch(url, headers=headers, data=document.page_content)\\n elif method == \\\"PUT\\\":\\n response = session.put(url, headers=headers, data=document.page_content)\\n else:\\n raise ValueError(f\\\"Unsupported method: {method}\\\")\\n try:\\n response_json = response.json()\\n result = orjson_dumps(response_json, indent_2=False)\\n except Exception:\\n result = response.text\\n self.repr_value = result\\n return Document(\\n page_content=result,\\n metadata={\\n \\\"source\\\": url,\\n \\\"headers\\\": headers,\\n \\\"status_code\\\": response.status_code,\\n },\\n )\\n except Exception as exc:\\n return Document(\\n page_content=str(exc),\\n metadata={\\\"source\\\": url, \\\"headers\\\": headers, \\\"status_code\\\": 500},\\n )\\n\\n def build(\\n self,\\n method: str,\\n document: Document,\\n url: str,\\n headers: Optional[dict] = None,\\n ) -> List[Document]:\\n if headers is None:\\n headers = {}\\n\\n if not isinstance(document, list) and isinstance(document, Document):\\n documents: list[Document] = [document]\\n elif isinstance(document, list) and all(isinstance(doc, Document) for doc in document):\\n documents = document\\n else:\\n raise ValueError(\\\"document must be a Document or a list of Documents\\\")\\n\\n with requests.Session() as session:\\n documents = [self.update_document(session, doc, url, headers, method) for doc in documents]\\n self.repr_value = documents\\n return documents\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"headers\":{\"type\":\"NestedDict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"headers\",\"display_name\":\"Headers\",\"advanced\":false,\"dynamic\":false,\"info\":\"The headers to send with the request.\",\"title_case\":false},\"method\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"PATCH\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"PATCH\",\"PUT\"],\"name\":\"method\",\"display_name\":\"Method\",\"advanced\":false,\"dynamic\":false,\"info\":\"The HTTP method to use.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"url\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"url\",\"display_name\":\"URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"The URL to make the request to.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Make a PATCH request to the given URL.\",\"base_classes\":[\"Serializable\",\"Document\"],\"display_name\":\"Update Request\",\"documentation\":\"https://docs.langflow.org/components/utilities#update-request\",\"custom_fields\":{\"method\":null,\"document\":null,\"url\":null,\"headers\":null},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"JSONDocumentBuilder\":{\"template\":{\"document\":{\"type\":\"Document\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"document\",\"display_name\":\"Document\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"### JSON Document Builder\\n\\n# Build a Document containing a JSON object using a key and another Document page content.\\n\\n# **Params**\\n\\n# - **Key:** The key to use for the JSON object.\\n# - **Document:** The Document page to use for the JSON object.\\n\\n# **Output**\\n\\n# - **Document:** The Document containing the JSON object.\\n\\nfrom langchain_core.documents import Document\\nfrom langflow import CustomComponent\\nfrom langflow.services.database.models.base import orjson_dumps\\n\\n\\nclass JSONDocumentBuilder(CustomComponent):\\n display_name: str = \\\"JSON Document Builder\\\"\\n description: str = \\\"Build a Document containing a JSON object using a key and another Document page content.\\\"\\n output_types: list[str] = [\\\"Document\\\"]\\n beta = True\\n documentation: str = \\\"https://docs.langflow.org/components/utilities#json-document-builder\\\"\\n\\n field_config = {\\n \\\"key\\\": {\\\"display_name\\\": \\\"Key\\\"},\\n \\\"document\\\": {\\\"display_name\\\": \\\"Document\\\"},\\n }\\n\\n def build(\\n self,\\n key: str,\\n document: Document,\\n ) -> Document:\\n documents = None\\n if isinstance(document, list):\\n documents = [\\n Document(page_content=orjson_dumps({key: doc.page_content}, indent_2=False)) for doc in document\\n ]\\n elif isinstance(document, Document):\\n documents = Document(page_content=orjson_dumps({key: document.page_content}, indent_2=False))\\n else:\\n raise TypeError(f\\\"Expected Document or list of Documents, got {type(document)}\\\")\\n self.repr_value = documents\\n return documents\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"key\",\"display_name\":\"Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Build a Document containing a JSON object using a key and another Document page content.\",\"base_classes\":[\"Serializable\",\"Document\"],\"display_name\":\"JSON Document Builder\",\"documentation\":\"https://docs.langflow.org/components/utilities#json-document-builder\",\"custom_fields\":{\"key\":null,\"document\":null},\"output_types\":[\"Document\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true}},\"output_parsers\":{\"ResponseSchema\":{\"template\":{\"description\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"fileTypes\":[],\"password\":false,\"name\":\"description\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"type\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"string\",\"fileTypes\":[],\"password\":false,\"name\":\"type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"ResponseSchema\"},\"description\":\"A schema for a response from a structured output parser.\",\"base_classes\":[\"ResponseSchema\"],\"display_name\":\"ResponseSchema\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/output_parsers/structured\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"StructuredOutputParser\":{\"template\":{\"response_schemas\":{\"type\":\"ResponseSchema\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"password\":false,\"name\":\"response_schemas\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"StructuredOutputParser\"},\"description\":\"\",\"base_classes\":[\"BaseOutputParser\",\"Runnable\",\"BaseLLMOutputParser\",\"Generic\",\"RunnableSerializable\",\"StructuredOutputParser\",\"Serializable\",\"object\"],\"display_name\":\"StructuredOutputParser\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/output_parsers/structured\",\"custom_fields\":{},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":false}},\"retrievers\":{\"AmazonKendra\":{\"template\":{\"attribute_filter\":{\"type\":\"code\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"attribute_filter\",\"display_name\":\"Attribute Filter\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain.schema import BaseRetriever\\nfrom langchain_community.retrievers import AmazonKendraRetriever\\n\\nfrom langflow import CustomComponent\\n\\n\\nclass AmazonKendraRetrieverComponent(CustomComponent):\\n display_name: str = \\\"Amazon Kendra Retriever\\\"\\n description: str = \\\"Retriever that uses the Amazon Kendra API.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"index_id\\\": {\\\"display_name\\\": \\\"Index ID\\\"},\\n \\\"region_name\\\": {\\\"display_name\\\": \\\"Region Name\\\"},\\n \\\"credentials_profile_name\\\": {\\\"display_name\\\": \\\"Credentials Profile Name\\\"},\\n \\\"attribute_filter\\\": {\\n \\\"display_name\\\": \\\"Attribute Filter\\\",\\n \\\"field_type\\\": \\\"code\\\",\\n },\\n \\\"top_k\\\": {\\\"display_name\\\": \\\"Top K\\\", \\\"field_type\\\": \\\"int\\\"},\\n \\\"user_context\\\": {\\n \\\"display_name\\\": \\\"User Context\\\",\\n \\\"field_type\\\": \\\"code\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n index_id: str,\\n top_k: int = 3,\\n region_name: Optional[str] = None,\\n credentials_profile_name: Optional[str] = None,\\n attribute_filter: Optional[dict] = None,\\n user_context: Optional[dict] = None,\\n ) -> BaseRetriever:\\n try:\\n output = AmazonKendraRetriever(\\n index_id=index_id,\\n top_k=top_k,\\n region_name=region_name,\\n credentials_profile_name=credentials_profile_name,\\n attribute_filter=attribute_filter,\\n user_context=user_context,\\n ) # type: ignore\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to AmazonKendra API.\\\") from e\\n return output\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"credentials_profile_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"credentials_profile_name\",\"display_name\":\"Credentials Profile Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"index_id\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"index_id\",\"display_name\":\"Index ID\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"region_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"region_name\",\"display_name\":\"Region Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"top_k\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":3,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_k\",\"display_name\":\"Top K\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"user_context\":{\"type\":\"code\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"user_context\",\"display_name\":\"User Context\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Retriever that uses the Amazon Kendra API.\",\"base_classes\":[\"Runnable\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"object\",\"BaseRetriever\"],\"display_name\":\"Amazon Kendra Retriever\",\"documentation\":\"\",\"custom_fields\":{\"index_id\":null,\"top_k\":null,\"region_name\":null,\"credentials_profile_name\":null,\"attribute_filter\":null,\"user_context\":null},\"output_types\":[\"BaseRetriever\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"VectaraSelfQueryRetriver\":{\"template\":{\"llm\":{\"type\":\"BaseLanguageModel\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"For self query retriever\",\"title_case\":false},\"vectorstore\":{\"type\":\"VectorStore\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"vectorstore\",\"display_name\":\"Vector Store\",\"advanced\":false,\"dynamic\":false,\"info\":\"Input Vectara Vectore Store\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import List\\nfrom langflow import CustomComponent\\nimport json\\nfrom langchain.schema import BaseRetriever\\nfrom langchain.schema.vectorstore import VectorStore\\nfrom langchain.base_language import BaseLanguageModel\\nfrom langchain.retrievers.self_query.base import SelfQueryRetriever\\nfrom langchain.chains.query_constructor.base import AttributeInfo\\n\\n\\nclass VectaraSelfQueryRetriverComponent(CustomComponent):\\n \\\"\\\"\\\"\\n A custom component for implementing Vectara Self Query Retriever using a vector store.\\n \\\"\\\"\\\"\\n\\n display_name: str = \\\"Vectara Self Query Retriever for Vectara Vector Store\\\"\\n description: str = \\\"Implementation of Vectara Self Query Retriever\\\"\\n documentation = \\\"https://python.langchain.com/docs/integrations/retrievers/self_query/vectara_self_query\\\"\\n beta = True\\n\\n field_config = {\\n \\\"code\\\": {\\\"show\\\": True},\\n \\\"vectorstore\\\": {\\\"display_name\\\": \\\"Vector Store\\\", \\\"info\\\": \\\"Input Vectara Vectore Store\\\"},\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\", \\\"info\\\": \\\"For self query retriever\\\"},\\n \\\"document_content_description\\\": {\\n \\\"display_name\\\": \\\"Document Content Description\\\",\\n \\\"info\\\": \\\"For self query retriever\\\",\\n },\\n \\\"metadata_field_info\\\": {\\n \\\"display_name\\\": \\\"Metadata Field Info\\\",\\n \\\"info\\\": 'Each metadata field info is a string in the form of key value pair dictionary containing additional search metadata.\\\\nExample input: {\\\"name\\\":\\\"speech\\\",\\\"description\\\":\\\"what name of the speech\\\",\\\"type\\\":\\\"string or list[string]\\\"}.\\\\nThe keys should remain constant(name, description, type)',\\n },\\n }\\n\\n def build(\\n self,\\n vectorstore: VectorStore,\\n document_content_description: str,\\n llm: BaseLanguageModel,\\n metadata_field_info: List[str],\\n ) -> BaseRetriever:\\n metadata_field_obj = []\\n\\n for meta in metadata_field_info:\\n meta_obj = json.loads(meta)\\n if \\\"name\\\" not in meta_obj or \\\"description\\\" not in meta_obj or \\\"type\\\" not in meta_obj:\\n raise Exception(\\\"Incorrect metadata field info format.\\\")\\n attribute_info = AttributeInfo(\\n name=meta_obj[\\\"name\\\"],\\n description=meta_obj[\\\"description\\\"],\\n type=meta_obj[\\\"type\\\"],\\n )\\n metadata_field_obj.append(attribute_info)\\n\\n return SelfQueryRetriever.from_llm(\\n llm, vectorstore, document_content_description, metadata_field_obj, verbose=True\\n )\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"document_content_description\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"document_content_description\",\"display_name\":\"Document Content Description\",\"advanced\":false,\"dynamic\":false,\"info\":\"For self query retriever\",\"title_case\":false,\"input_types\":[\"Text\"]},\"metadata_field_info\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata_field_info\",\"display_name\":\"Metadata Field Info\",\"advanced\":false,\"dynamic\":false,\"info\":\"Each metadata field info is a string in the form of key value pair dictionary containing additional search metadata.\\nExample input: {\\\"name\\\":\\\"speech\\\",\\\"description\\\":\\\"what name of the speech\\\",\\\"type\\\":\\\"string or list[string]\\\"}.\\nThe keys should remain constant(name, description, type)\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Implementation of Vectara Self Query Retriever\",\"base_classes\":[\"Runnable\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"object\",\"BaseRetriever\"],\"display_name\":\"Vectara Self Query Retriever for Vectara Vector Store\",\"documentation\":\"https://python.langchain.com/docs/integrations/retrievers/self_query/vectara_self_query\",\"custom_fields\":{\"vectorstore\":null,\"document_content_description\":null,\"llm\":null,\"metadata_field_info\":null},\"output_types\":[\"BaseRetriever\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"MultiQueryRetriever\":{\"template\":{\"llm\":{\"type\":\"BaseLLM\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"llm\",\"display_name\":\"LLM\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"prompt\":{\"type\":\"PromptTemplate\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"prompt\",\"display_name\":\"Prompt\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"retriever\":{\"type\":\"BaseRetriever\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"retriever\",\"display_name\":\"Retriever\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Callable, Optional, Union\\n\\nfrom langchain.retrievers import MultiQueryRetriever\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import BaseLLM, BaseRetriever, PromptTemplate\\n\\n\\nclass MultiQueryRetrieverComponent(CustomComponent):\\n display_name = \\\"MultiQueryRetriever\\\"\\n description = \\\"Initialize from llm using default template.\\\"\\n documentation = \\\"https://python.langchain.com/docs/modules/data_connection/retrievers/how_to/MultiQueryRetriever\\\"\\n\\n def build_config(self):\\n return {\\n \\\"llm\\\": {\\\"display_name\\\": \\\"LLM\\\"},\\n \\\"prompt\\\": {\\n \\\"display_name\\\": \\\"Prompt\\\",\\n \\\"default\\\": {\\n \\\"input_variables\\\": [\\\"question\\\"],\\n \\\"input_types\\\": {},\\n \\\"output_parser\\\": None,\\n \\\"partial_variables\\\": {},\\n \\\"template\\\": \\\"You are an AI language model assistant. Your task is \\\\n\\\"\\n \\\"to generate 3 different versions of the given user \\\\n\\\"\\n \\\"question to retrieve relevant documents from a vector database. \\\\n\\\"\\n \\\"By generating multiple perspectives on the user question, \\\\n\\\"\\n \\\"your goal is to help the user overcome some of the limitations \\\\n\\\"\\n \\\"of distance-based similarity search. Provide these alternative \\\\n\\\"\\n \\\"questions separated by newlines. Original question: {question}\\\",\\n \\\"template_format\\\": \\\"f-string\\\",\\n \\\"validate_template\\\": False,\\n \\\"_type\\\": \\\"prompt\\\",\\n },\\n },\\n \\\"retriever\\\": {\\\"display_name\\\": \\\"Retriever\\\"},\\n \\\"parser_key\\\": {\\\"display_name\\\": \\\"Parser Key\\\", \\\"default\\\": \\\"lines\\\"},\\n }\\n\\n def build(\\n self,\\n llm: BaseLLM,\\n retriever: BaseRetriever,\\n prompt: Optional[PromptTemplate] = None,\\n parser_key: str = \\\"lines\\\",\\n ) -> Union[Callable, MultiQueryRetriever]:\\n if not prompt:\\n return MultiQueryRetriever.from_llm(llm=llm, retriever=retriever, parser_key=parser_key)\\n else:\\n return MultiQueryRetriever.from_llm(llm=llm, retriever=retriever, prompt=prompt, parser_key=parser_key)\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"parser_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"lines\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"parser_key\",\"display_name\":\"Parser Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Initialize from llm using default template.\",\"base_classes\":[],\"display_name\":\"MultiQueryRetriever\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/retrievers/how_to/MultiQueryRetriever\",\"custom_fields\":{\"llm\":null,\"retriever\":null,\"prompt\":null,\"parser_key\":null},\"output_types\":[],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"MetalRetriever\":{\"template\":{\"api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"api_key\",\"display_name\":\"API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"client_id\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"client_id\",\"display_name\":\"Client ID\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain.schema import BaseRetriever\\nfrom langchain_community.retrievers import MetalRetriever\\nfrom metal_sdk.metal import Metal # type: ignore\\n\\nfrom langflow import CustomComponent\\n\\n\\nclass MetalRetrieverComponent(CustomComponent):\\n display_name: str = \\\"Metal Retriever\\\"\\n description: str = \\\"Retriever that uses the Metal API.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"api_key\\\": {\\\"display_name\\\": \\\"API Key\\\", \\\"password\\\": True},\\n \\\"client_id\\\": {\\\"display_name\\\": \\\"Client ID\\\", \\\"password\\\": True},\\n \\\"index_id\\\": {\\\"display_name\\\": \\\"Index ID\\\"},\\n \\\"params\\\": {\\\"display_name\\\": \\\"Parameters\\\"},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(self, api_key: str, client_id: str, index_id: str, params: Optional[dict] = None) -> BaseRetriever:\\n try:\\n metal = Metal(api_key=api_key, client_id=client_id, index_id=index_id)\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to Metal API.\\\") from e\\n return MetalRetriever(client=metal, params=params or {})\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"index_id\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"index_id\",\"display_name\":\"Index ID\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"params\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"params\",\"display_name\":\"Parameters\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Retriever that uses the Metal API.\",\"base_classes\":[\"Runnable\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"object\",\"BaseRetriever\"],\"display_name\":\"Metal Retriever\",\"documentation\":\"\",\"custom_fields\":{\"api_key\":null,\"client_id\":null,\"index_id\":null,\"params\":null},\"output_types\":[\"BaseRetriever\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true}},\"custom_components\":{\"CustomComponent\":{\"template\":{\"param\":{\"type\":\"Data\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"param\",\"display_name\":\"Parameter\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langflow.field_typing import Data\\n\\n\\nclass Component(CustomComponent):\\n documentation: str = \\\"http://docs.langflow.org/components/custom\\\"\\n\\n def build_config(self):\\n return {\\\"param\\\": {\\\"display_name\\\": \\\"Parameter\\\"}}\\n\\n def build(self, param: Data) -> Data:\\n return param\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"base_classes\":[\"object\",\"Data\"],\"display_name\":\"CustomComponent\",\"documentation\":\"http://docs.langflow.org/components/custom\",\"custom_fields\":{\"param\":null},\"output_types\":[\"Data\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true}},\"vectorstores\":{\"Weaviate\":{\"template\":{\"documents\":{\"type\":\"Document\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"embedding\":{\"type\":\"Embeddings\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"api_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"api_key\",\"display_name\":\"API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"attributes\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"attributes\",\"display_name\":\"Attributes\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional, Union\\n\\nimport weaviate # type: ignore\\nfrom langchain.embeddings.base import Embeddings\\nfrom langchain.schema import BaseRetriever, Document\\nfrom langchain_community.vectorstores import VectorStore, Weaviate\\n\\nfrom langflow import CustomComponent\\n\\n\\nclass WeaviateVectorStore(CustomComponent):\\n display_name: str = \\\"Weaviate\\\"\\n description: str = \\\"Implementation of Vector Store using Weaviate\\\"\\n documentation = \\\"https://python.langchain.com/docs/integrations/vectorstores/weaviate\\\"\\n beta = True\\n field_config = {\\n \\\"url\\\": {\\\"display_name\\\": \\\"Weaviate URL\\\", \\\"value\\\": \\\"http://localhost:8080\\\"},\\n \\\"api_key\\\": {\\n \\\"display_name\\\": \\\"API Key\\\",\\n \\\"password\\\": True,\\n \\\"required\\\": False,\\n },\\n \\\"index_name\\\": {\\n \\\"display_name\\\": \\\"Index name\\\",\\n \\\"required\\\": False,\\n },\\n \\\"text_key\\\": {\\\"display_name\\\": \\\"Text Key\\\", \\\"required\\\": False, \\\"advanced\\\": True, \\\"value\\\": \\\"text\\\"},\\n \\\"documents\\\": {\\\"display_name\\\": \\\"Documents\\\", \\\"is_list\\\": True},\\n \\\"embedding\\\": {\\\"display_name\\\": \\\"Embedding\\\"},\\n \\\"attributes\\\": {\\n \\\"display_name\\\": \\\"Attributes\\\",\\n \\\"required\\\": False,\\n \\\"is_list\\\": True,\\n \\\"field_type\\\": \\\"str\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"search_by_text\\\": {\\\"display_name\\\": \\\"Search By Text\\\", \\\"field_type\\\": \\\"bool\\\", \\\"advanced\\\": True},\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n url: str,\\n search_by_text: bool = False,\\n api_key: Optional[str] = None,\\n index_name: Optional[str] = None,\\n text_key: str = \\\"text\\\",\\n embedding: Optional[Embeddings] = None,\\n documents: Optional[Document] = None,\\n attributes: Optional[list] = None,\\n ) -> Union[VectorStore, BaseRetriever]:\\n if api_key:\\n auth_config = weaviate.AuthApiKey(api_key=api_key)\\n client = weaviate.Client(url=url, auth_client_secret=auth_config)\\n else:\\n client = weaviate.Client(url=url)\\n\\n def _to_pascal_case(word: str):\\n if word and not word[0].isupper():\\n word = word.capitalize()\\n\\n if word.isidentifier():\\n return word\\n\\n word = word.replace(\\\"-\\\", \\\" \\\").replace(\\\"_\\\", \\\" \\\")\\n parts = word.split()\\n pascal_case_word = \\\"\\\".join([part.capitalize() for part in parts])\\n\\n return pascal_case_word\\n\\n index_name = _to_pascal_case(index_name) if index_name else None\\n\\n if documents is not None and embedding is not None:\\n return Weaviate.from_documents(\\n client=client,\\n index_name=index_name,\\n documents=documents,\\n embedding=embedding,\\n by_text=search_by_text,\\n )\\n\\n return Weaviate(\\n client=client,\\n index_name=index_name,\\n text_key=text_key,\\n embedding=embedding,\\n by_text=search_by_text,\\n attributes=attributes if attributes is not None else [],\\n )\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"index_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"index_name\",\"display_name\":\"Index name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"search_by_text\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"search_by_text\",\"display_name\":\"Search By Text\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"text_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"text\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"text_key\",\"display_name\":\"Text Key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"url\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"http://localhost:8080\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"url\",\"display_name\":\"Weaviate URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Implementation of Vector Store using Weaviate\",\"base_classes\":[\"Runnable\",\"Generic\",\"VectorStore\",\"RunnableSerializable\",\"Serializable\",\"object\",\"BaseRetriever\"],\"display_name\":\"Weaviate\",\"documentation\":\"https://python.langchain.com/docs/integrations/vectorstores/weaviate\",\"custom_fields\":{\"url\":null,\"search_by_text\":null,\"api_key\":null,\"index_name\":null,\"text_key\":null,\"embedding\":null,\"documents\":null,\"attributes\":null},\"output_types\":[\"VectorStore\",\"BaseRetriever\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"Vectara\":{\"template\":{\"documents\":{\"type\":\"Document\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"If provided, will be upserted to corpus (optional)\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"import tempfile\\nimport urllib\\nimport urllib.request\\nfrom typing import List, Optional, Union\\n\\nfrom langchain_community.embeddings import FakeEmbeddings\\nfrom langchain_community.vectorstores.vectara import Vectara\\nfrom langchain_core.vectorstores import VectorStore\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import BaseRetriever, Document\\n\\n\\nclass VectaraComponent(CustomComponent):\\n display_name: str = \\\"Vectara\\\"\\n description: str = \\\"Implementation of Vector Store using Vectara\\\"\\n documentation = \\\"https://python.langchain.com/docs/integrations/vectorstores/vectara\\\"\\n beta = True\\n field_config = {\\n \\\"vectara_customer_id\\\": {\\n \\\"display_name\\\": \\\"Vectara Customer ID\\\",\\n },\\n \\\"vectara_corpus_id\\\": {\\n \\\"display_name\\\": \\\"Vectara Corpus ID\\\",\\n },\\n \\\"vectara_api_key\\\": {\\n \\\"display_name\\\": \\\"Vectara API Key\\\",\\n \\\"password\\\": True,\\n },\\n \\\"documents\\\": {\\\"display_name\\\": \\\"Documents\\\", \\\"info\\\": \\\"If provided, will be upserted to corpus (optional)\\\"},\\n \\\"files_url\\\": {\\n \\\"display_name\\\": \\\"Files Url\\\",\\n \\\"info\\\": \\\"Make vectara object using url of files (optional)\\\",\\n },\\n }\\n\\n def build(\\n self,\\n vectara_customer_id: str,\\n vectara_corpus_id: str,\\n vectara_api_key: str,\\n files_url: Optional[List[str]] = None,\\n documents: Optional[Document] = None,\\n ) -> Union[VectorStore, BaseRetriever]:\\n source = \\\"Langflow\\\"\\n\\n if documents is not None:\\n return Vectara.from_documents(\\n documents=documents, # type: ignore\\n embedding=FakeEmbeddings(size=768),\\n vectara_customer_id=vectara_customer_id,\\n vectara_corpus_id=vectara_corpus_id,\\n vectara_api_key=vectara_api_key,\\n source=source,\\n )\\n\\n if files_url is not None:\\n files_list = []\\n for url in files_url:\\n name = tempfile.NamedTemporaryFile().name\\n urllib.request.urlretrieve(url, name)\\n files_list.append(name)\\n\\n return Vectara.from_files(\\n files=files_list,\\n embedding=FakeEmbeddings(size=768),\\n vectara_customer_id=vectara_customer_id,\\n vectara_corpus_id=vectara_corpus_id,\\n vectara_api_key=vectara_api_key,\\n source=source,\\n )\\n\\n return Vectara(\\n vectara_customer_id=vectara_customer_id,\\n vectara_corpus_id=vectara_corpus_id,\\n vectara_api_key=vectara_api_key,\\n source=source,\\n )\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"files_url\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"files_url\",\"display_name\":\"Files Url\",\"advanced\":false,\"dynamic\":false,\"info\":\"Make vectara object using url of files (optional)\",\"title_case\":false,\"input_types\":[\"Text\"]},\"vectara_api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"vectara_api_key\",\"display_name\":\"Vectara API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"vectara_corpus_id\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"vectara_corpus_id\",\"display_name\":\"Vectara Corpus ID\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"vectara_customer_id\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"vectara_customer_id\",\"display_name\":\"Vectara Customer ID\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Implementation of Vector Store using Vectara\",\"base_classes\":[\"Runnable\",\"Generic\",\"VectorStore\",\"RunnableSerializable\",\"Serializable\",\"object\",\"BaseRetriever\"],\"display_name\":\"Vectara\",\"documentation\":\"https://python.langchain.com/docs/integrations/vectorstores/vectara\",\"custom_fields\":{\"vectara_customer_id\":null,\"vectara_corpus_id\":null,\"vectara_api_key\":null,\"files_url\":null,\"documents\":null},\"output_types\":[\"VectorStore\",\"BaseRetriever\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"Chroma\":{\"template\":{\"documents\":{\"type\":\"Document\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"embedding\":{\"type\":\"Embeddings\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"chroma_server_cors_allow_origins\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chroma_server_cors_allow_origins\",\"display_name\":\"Server CORS Allow Origins\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"chroma_server_grpc_port\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chroma_server_grpc_port\",\"display_name\":\"Server gRPC Port\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"chroma_server_host\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chroma_server_host\",\"display_name\":\"Server Host\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"chroma_server_port\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chroma_server_port\",\"display_name\":\"Server Port\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"chroma_server_ssl_enabled\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chroma_server_ssl_enabled\",\"display_name\":\"Server SSL Enabled\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import List, Optional, Union\\n\\nimport chromadb # type: ignore\\nfrom langchain.embeddings.base import Embeddings\\nfrom langchain.schema import BaseRetriever, Document\\nfrom langchain_community.vectorstores import VectorStore\\nfrom langchain_community.vectorstores.chroma import Chroma\\n\\nfrom langflow import CustomComponent\\n\\n\\nclass ChromaComponent(CustomComponent):\\n \\\"\\\"\\\"\\n A custom component for implementing a Vector Store using Chroma.\\n \\\"\\\"\\\"\\n\\n display_name: str = \\\"Chroma\\\"\\n description: str = \\\"Implementation of Vector Store using Chroma\\\"\\n documentation = \\\"https://python.langchain.com/docs/integrations/vectorstores/chroma\\\"\\n beta: bool = True\\n icon = \\\"Chroma\\\"\\n\\n def build_config(self):\\n \\\"\\\"\\\"\\n Builds the configuration for the component.\\n\\n Returns:\\n - dict: A dictionary containing the configuration options for the component.\\n \\\"\\\"\\\"\\n return {\\n \\\"collection_name\\\": {\\\"display_name\\\": \\\"Collection Name\\\", \\\"value\\\": \\\"langflow\\\"},\\n \\\"index_directory\\\": {\\\"display_name\\\": \\\"Persist Directory\\\"},\\n \\\"code\\\": {\\\"advanced\\\": True, \\\"display_name\\\": \\\"Code\\\"},\\n \\\"documents\\\": {\\\"display_name\\\": \\\"Documents\\\", \\\"is_list\\\": True},\\n \\\"embedding\\\": {\\\"display_name\\\": \\\"Embedding\\\"},\\n \\\"chroma_server_cors_allow_origins\\\": {\\n \\\"display_name\\\": \\\"Server CORS Allow Origins\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"chroma_server_host\\\": {\\\"display_name\\\": \\\"Server Host\\\", \\\"advanced\\\": True},\\n \\\"chroma_server_port\\\": {\\\"display_name\\\": \\\"Server Port\\\", \\\"advanced\\\": True},\\n \\\"chroma_server_grpc_port\\\": {\\n \\\"display_name\\\": \\\"Server gRPC Port\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"chroma_server_ssl_enabled\\\": {\\n \\\"display_name\\\": \\\"Server SSL Enabled\\\",\\n \\\"advanced\\\": True,\\n },\\n }\\n\\n def build(\\n self,\\n collection_name: str,\\n embedding: Embeddings,\\n chroma_server_ssl_enabled: bool,\\n index_directory: Optional[str] = None,\\n documents: Optional[List[Document]] = None,\\n chroma_server_cors_allow_origins: Optional[str] = None,\\n chroma_server_host: Optional[str] = None,\\n chroma_server_port: Optional[int] = None,\\n chroma_server_grpc_port: Optional[int] = None,\\n ) -> Union[VectorStore, BaseRetriever]:\\n \\\"\\\"\\\"\\n Builds the Vector Store or BaseRetriever object.\\n\\n Args:\\n - collection_name (str): The name of the collection.\\n - index_directory (Optional[str]): The directory to persist the Vector Store to.\\n - chroma_server_ssl_enabled (bool): Whether to enable SSL for the Chroma server.\\n - embedding (Optional[Embeddings]): The embeddings to use for the Vector Store.\\n - documents (Optional[Document]): The documents to use for the Vector Store.\\n - chroma_server_cors_allow_origins (Optional[str]): The CORS allow origins for the Chroma server.\\n - chroma_server_host (Optional[str]): The host for the Chroma server.\\n - chroma_server_port (Optional[int]): The port for the Chroma server.\\n - chroma_server_grpc_port (Optional[int]): The gRPC port for the Chroma server.\\n\\n Returns:\\n - Union[VectorStore, BaseRetriever]: The Vector Store or BaseRetriever object.\\n \\\"\\\"\\\"\\n\\n # Chroma settings\\n chroma_settings = None\\n\\n if chroma_server_host is not None:\\n chroma_settings = chromadb.config.Settings(\\n chroma_server_cors_allow_origins=chroma_server_cors_allow_origins\\n or None,\\n chroma_server_host=chroma_server_host,\\n chroma_server_port=chroma_server_port or None,\\n chroma_server_grpc_port=chroma_server_grpc_port or None,\\n chroma_server_ssl_enabled=chroma_server_ssl_enabled,\\n )\\n\\n # If documents, then we need to create a Chroma instance using .from_documents\\n\\n # Check index_directory and expand it if it is a relative path\\n\\n index_directory = self.resolve_path(index_directory)\\n\\n if documents is not None and embedding is not None:\\n if len(documents) == 0:\\n raise ValueError(\\n \\\"If documents are provided, there must be at least one document.\\\"\\n )\\n chroma = Chroma.from_documents(\\n documents=documents, # type: ignore\\n persist_directory=index_directory,\\n collection_name=collection_name,\\n embedding=embedding,\\n client_settings=chroma_settings,\\n )\\n else:\\n chroma = Chroma(\\n persist_directory=index_directory,\\n client_settings=chroma_settings,\\n embedding_function=embedding,\\n )\\n return chroma\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"collection_name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"langflow\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"collection_name\",\"display_name\":\"Collection Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"index_directory\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"index_directory\",\"display_name\":\"Persist Directory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Implementation of Vector Store using Chroma\",\"icon\":\"Chroma\",\"base_classes\":[\"Runnable\",\"Generic\",\"VectorStore\",\"RunnableSerializable\",\"Serializable\",\"object\",\"BaseRetriever\"],\"display_name\":\"Chroma\",\"documentation\":\"https://python.langchain.com/docs/integrations/vectorstores/chroma\",\"custom_fields\":{\"collection_name\":null,\"embedding\":null,\"chroma_server_ssl_enabled\":null,\"index_directory\":null,\"documents\":null,\"chroma_server_cors_allow_origins\":null,\"chroma_server_host\":null,\"chroma_server_port\":null,\"chroma_server_grpc_port\":null},\"output_types\":[\"VectorStore\",\"BaseRetriever\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"SupabaseVectorStore\":{\"template\":{\"documents\":{\"type\":\"Document\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"embedding\":{\"type\":\"Embeddings\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import List, Union\\n\\nfrom langchain.schema import BaseRetriever\\nfrom langchain_community.vectorstores import VectorStore\\nfrom langchain_community.vectorstores.supabase import SupabaseVectorStore\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Document, Embeddings, NestedDict\\nfrom supabase.client import Client, create_client\\n\\n\\nclass SupabaseComponent(CustomComponent):\\n display_name = \\\"Supabase\\\"\\n description = \\\"Return VectorStore initialized from texts and embeddings.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"documents\\\": {\\\"display_name\\\": \\\"Documents\\\"},\\n \\\"embedding\\\": {\\\"display_name\\\": \\\"Embedding\\\"},\\n \\\"query_name\\\": {\\\"display_name\\\": \\\"Query Name\\\"},\\n \\\"search_kwargs\\\": {\\\"display_name\\\": \\\"Search Kwargs\\\", \\\"advanced\\\": True},\\n \\\"supabase_service_key\\\": {\\\"display_name\\\": \\\"Supabase Service Key\\\"},\\n \\\"supabase_url\\\": {\\\"display_name\\\": \\\"Supabase URL\\\"},\\n \\\"table_name\\\": {\\\"display_name\\\": \\\"Table Name\\\", \\\"advanced\\\": True},\\n }\\n\\n def build(\\n self,\\n embedding: Embeddings,\\n documents: List[Document],\\n query_name: str = \\\"\\\",\\n search_kwargs: NestedDict = {},\\n supabase_service_key: str = \\\"\\\",\\n supabase_url: str = \\\"\\\",\\n table_name: str = \\\"\\\",\\n ) -> Union[VectorStore, SupabaseVectorStore, BaseRetriever]:\\n supabase: Client = create_client(supabase_url, supabase_key=supabase_service_key)\\n return SupabaseVectorStore.from_documents(\\n documents=documents,\\n embedding=embedding,\\n query_name=query_name,\\n search_kwargs=search_kwargs,\\n client=supabase,\\n table_name=table_name,\\n )\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"query_name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"query_name\",\"display_name\":\"Query Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"search_kwargs\":{\"type\":\"NestedDict\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"search_kwargs\",\"display_name\":\"Search Kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"supabase_service_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"supabase_service_key\",\"display_name\":\"Supabase Service Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"supabase_url\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"supabase_url\",\"display_name\":\"Supabase URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"table_name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"table_name\",\"display_name\":\"Table Name\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Return VectorStore initialized from texts and embeddings.\",\"base_classes\":[\"Runnable\",\"Generic\",\"VectorStore\",\"SupabaseVectorStore\",\"RunnableSerializable\",\"Serializable\",\"object\",\"BaseRetriever\"],\"display_name\":\"Supabase\",\"documentation\":\"\",\"custom_fields\":{\"embedding\":null,\"documents\":null,\"query_name\":null,\"search_kwargs\":null,\"supabase_service_key\":null,\"supabase_url\":null,\"table_name\":null},\"output_types\":[\"VectorStore\",\"SupabaseVectorStore\",\"BaseRetriever\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"Redis\":{\"template\":{\"documents\":{\"type\":\"Document\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"embedding\":{\"type\":\"Embeddings\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional, Union\\n\\nfrom langchain.embeddings.base import Embeddings\\nfrom langchain_community.vectorstores import VectorStore\\nfrom langchain_community.vectorstores.redis import Redis\\nfrom langchain_core.documents import Document\\nfrom langchain_core.retrievers import BaseRetriever\\nfrom langflow import CustomComponent\\n\\n\\nclass RedisComponent(CustomComponent):\\n \\\"\\\"\\\"\\n A custom component for implementing a Vector Store using Redis.\\n \\\"\\\"\\\"\\n\\n display_name: str = \\\"Redis\\\"\\n description: str = \\\"Implementation of Vector Store using Redis\\\"\\n documentation = \\\"https://python.langchain.com/docs/integrations/vectorstores/redis\\\"\\n beta = True\\n\\n def build_config(self):\\n \\\"\\\"\\\"\\n Builds the configuration for the component.\\n\\n Returns:\\n - dict: A dictionary containing the configuration options for the component.\\n \\\"\\\"\\\"\\n return {\\n \\\"index_name\\\": {\\\"display_name\\\": \\\"Index Name\\\", \\\"value\\\": \\\"your_index\\\"},\\n \\\"code\\\": {\\\"show\\\": False, \\\"display_name\\\": \\\"Code\\\"},\\n \\\"documents\\\": {\\\"display_name\\\": \\\"Documents\\\", \\\"is_list\\\": True},\\n \\\"embedding\\\": {\\\"display_name\\\": \\\"Embedding\\\"},\\n \\\"schema\\\": {\\\"display_name\\\": \\\"Schema\\\", \\\"file_types\\\": [\\\".yaml\\\"]},\\n \\\"redis_server_url\\\": {\\n \\\"display_name\\\": \\\"Redis Server Connection String\\\",\\n \\\"advanced\\\": False,\\n },\\n \\\"redis_index_name\\\": {\\\"display_name\\\": \\\"Redis Index\\\", \\\"advanced\\\": False},\\n }\\n\\n def build(\\n self,\\n embedding: Embeddings,\\n redis_server_url: str,\\n redis_index_name: str,\\n schema: Optional[str] = None,\\n documents: Optional[Document] = None,\\n ) -> Union[VectorStore, BaseRetriever]:\\n \\\"\\\"\\\"\\n Builds the Vector Store or BaseRetriever object.\\n\\n Args:\\n - embedding (Embeddings): The embeddings to use for the Vector Store.\\n - documents (Optional[Document]): The documents to use for the Vector Store.\\n - redis_index_name (str): The name of the Redis index.\\n - redis_server_url (str): The URL for the Redis server.\\n\\n Returns:\\n - VectorStore: The Vector Store object.\\n \\\"\\\"\\\"\\n if documents is None:\\n if schema is None:\\n raise ValueError(\\\"If no documents are provided, a schema must be provided.\\\")\\n redis_vs = Redis.from_existing_index(\\n embedding=embedding,\\n index_name=redis_index_name,\\n schema=schema,\\n key_prefix=None,\\n redis_url=redis_server_url,\\n )\\n else:\\n redis_vs = Redis.from_documents(\\n documents=documents, # type: ignore\\n embedding=embedding,\\n redis_url=redis_server_url,\\n index_name=redis_index_name,\\n )\\n return redis_vs\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"redis_index_name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"redis_index_name\",\"display_name\":\"Redis Index\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"redis_server_url\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"redis_server_url\",\"display_name\":\"Redis Server Connection String\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"schema\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[\".yaml\"],\"file_path\":\"\",\"password\":false,\"name\":\"schema\",\"display_name\":\"Schema\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Implementation of Vector Store using Redis\",\"base_classes\":[\"Runnable\",\"Generic\",\"VectorStore\",\"RunnableSerializable\",\"Serializable\",\"object\",\"BaseRetriever\"],\"display_name\":\"Redis\",\"documentation\":\"https://python.langchain.com/docs/integrations/vectorstores/redis\",\"custom_fields\":{\"embedding\":null,\"redis_server_url\":null,\"redis_index_name\":null,\"schema\":null,\"documents\":null},\"output_types\":[\"VectorStore\",\"BaseRetriever\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"pgvector\":{\"template\":{\"documents\":{\"type\":\"Document\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"embedding\":{\"type\":\"Embeddings\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional, Union\\n\\nfrom langchain.embeddings.base import Embeddings\\nfrom langchain_community.vectorstores import VectorStore\\nfrom langchain_community.vectorstores.pgvector import PGVector\\nfrom langchain_core.documents import Document\\nfrom langchain_core.retrievers import BaseRetriever\\nfrom langflow import CustomComponent\\n\\n\\nclass PGVectorComponent(CustomComponent):\\n \\\"\\\"\\\"\\n A custom component for implementing a Vector Store using PostgreSQL.\\n \\\"\\\"\\\"\\n\\n display_name: str = \\\"PGVector\\\"\\n description: str = \\\"Implementation of Vector Store using PostgreSQL\\\"\\n documentation = \\\"https://python.langchain.com/docs/integrations/vectorstores/pgvector\\\"\\n\\n def build_config(self):\\n \\\"\\\"\\\"\\n Builds the configuration for the component.\\n\\n Returns:\\n - dict: A dictionary containing the configuration options for the component.\\n \\\"\\\"\\\"\\n return {\\n \\\"code\\\": {\\\"show\\\": False},\\n \\\"documents\\\": {\\\"display_name\\\": \\\"Documents\\\", \\\"is_list\\\": True},\\n \\\"embedding\\\": {\\\"display_name\\\": \\\"Embedding\\\"},\\n \\\"pg_server_url\\\": {\\n \\\"display_name\\\": \\\"PostgreSQL Server Connection String\\\",\\n \\\"advanced\\\": False,\\n },\\n \\\"collection_name\\\": {\\\"display_name\\\": \\\"Table\\\", \\\"advanced\\\": False},\\n }\\n\\n def build(\\n self,\\n embedding: Embeddings,\\n pg_server_url: str,\\n collection_name: str,\\n documents: Optional[Document] = None,\\n ) -> Union[VectorStore, BaseRetriever]:\\n \\\"\\\"\\\"\\n Builds the Vector Store or BaseRetriever object.\\n\\n Args:\\n - embedding (Embeddings): The embeddings to use for the Vector Store.\\n - documents (Optional[Document]): The documents to use for the Vector Store.\\n - collection_name (str): The name of the PG table.\\n - pg_server_url (str): The URL for the PG server.\\n\\n Returns:\\n - VectorStore: The Vector Store object.\\n \\\"\\\"\\\"\\n\\n try:\\n if documents is None:\\n vector_store = PGVector.from_existing_index(\\n embedding=embedding,\\n collection_name=collection_name,\\n connection_string=pg_server_url,\\n )\\n else:\\n vector_store = PGVector.from_documents(\\n embedding=embedding,\\n documents=documents, # type: ignore\\n collection_name=collection_name,\\n connection_string=pg_server_url,\\n )\\n except Exception as e:\\n raise RuntimeError(f\\\"Failed to build PGVector: {e}\\\")\\n return vector_store\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"collection_name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"collection_name\",\"display_name\":\"Table\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"pg_server_url\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"pg_server_url\",\"display_name\":\"PostgreSQL Server Connection String\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Implementation of Vector Store using PostgreSQL\",\"base_classes\":[\"Runnable\",\"Generic\",\"VectorStore\",\"RunnableSerializable\",\"Serializable\",\"object\",\"BaseRetriever\"],\"display_name\":\"PGVector\",\"documentation\":\"https://python.langchain.com/docs/integrations/vectorstores/pgvector\",\"custom_fields\":{\"embedding\":null,\"pg_server_url\":null,\"collection_name\":null,\"documents\":null},\"output_types\":[\"VectorStore\",\"BaseRetriever\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"Pinecone\":{\"template\":{\"documents\":{\"type\":\"Document\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"embedding\":{\"type\":\"Embeddings\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"import os\\nfrom typing import List, Optional, Union\\n\\nimport pinecone # type: ignore\\nfrom langchain.schema import BaseRetriever\\nfrom langchain_community.vectorstores import VectorStore\\nfrom langchain_community.vectorstores.pinecone import Pinecone\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Document, Embeddings\\n\\n\\nclass PineconeComponent(CustomComponent):\\n display_name = \\\"Pinecone\\\"\\n description = \\\"Construct Pinecone wrapper from raw documents.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"documents\\\": {\\\"display_name\\\": \\\"Documents\\\"},\\n \\\"embedding\\\": {\\\"display_name\\\": \\\"Embedding\\\"},\\n \\\"index_name\\\": {\\\"display_name\\\": \\\"Index Name\\\"},\\n \\\"namespace\\\": {\\\"display_name\\\": \\\"Namespace\\\"},\\n \\\"pinecone_api_key\\\": {\\\"display_name\\\": \\\"Pinecone API Key\\\", \\\"default\\\": \\\"\\\", \\\"password\\\": True, \\\"required\\\": True},\\n \\\"pinecone_env\\\": {\\\"display_name\\\": \\\"Pinecone Environment\\\", \\\"default\\\": \\\"\\\", \\\"required\\\": True},\\n \\\"search_kwargs\\\": {\\\"display_name\\\": \\\"Search Kwargs\\\", \\\"default\\\": \\\"{}\\\"},\\n \\\"pool_threads\\\": {\\\"display_name\\\": \\\"Pool Threads\\\", \\\"default\\\": 1, \\\"advanced\\\": True},\\n }\\n\\n def build(\\n self,\\n embedding: Embeddings,\\n pinecone_env: str,\\n documents: List[Document],\\n text_key: str = \\\"text\\\",\\n pool_threads: int = 4,\\n index_name: Optional[str] = None,\\n pinecone_api_key: Optional[str] = None,\\n namespace: Optional[str] = \\\"default\\\",\\n ) -> Union[VectorStore, Pinecone, BaseRetriever]:\\n if pinecone_api_key is None or pinecone_env is None:\\n raise ValueError(\\\"Pinecone API Key and Environment are required.\\\")\\n if os.getenv(\\\"PINECONE_API_KEY\\\") is None and pinecone_api_key is None:\\n raise ValueError(\\\"Pinecone API Key is required.\\\")\\n\\n pinecone.init(api_key=pinecone_api_key, environment=pinecone_env) # type: ignore\\n if not index_name:\\n raise ValueError(\\\"Index Name is required.\\\")\\n if documents:\\n return Pinecone.from_documents(\\n documents=documents,\\n embedding=embedding,\\n index_name=index_name,\\n pool_threads=pool_threads,\\n namespace=namespace,\\n text_key=text_key,\\n )\\n\\n return Pinecone.from_existing_index(\\n index_name=index_name,\\n embedding=embedding,\\n text_key=text_key,\\n namespace=namespace,\\n pool_threads=pool_threads,\\n )\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"index_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"index_name\",\"display_name\":\"Index Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"namespace\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"default\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"namespace\",\"display_name\":\"Namespace\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"pinecone_api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"pinecone_api_key\",\"display_name\":\"Pinecone API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"pinecone_env\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"pinecone_env\",\"display_name\":\"Pinecone Environment\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"pool_threads\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":4,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"pool_threads\",\"display_name\":\"Pool Threads\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"text_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"text\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"text_key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Construct Pinecone wrapper from raw documents.\",\"base_classes\":[\"Runnable\",\"Generic\",\"VectorStore\",\"Pinecone\",\"RunnableSerializable\",\"Serializable\",\"object\",\"BaseRetriever\"],\"display_name\":\"Pinecone\",\"documentation\":\"\",\"custom_fields\":{\"embedding\":null,\"pinecone_env\":null,\"documents\":null,\"text_key\":null,\"pool_threads\":null,\"index_name\":null,\"pinecone_api_key\":null,\"namespace\":null},\"output_types\":[\"VectorStore\",\"Pinecone\",\"BaseRetriever\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"Qdrant\":{\"template\":{\"documents\":{\"type\":\"Document\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"embedding\":{\"type\":\"Embeddings\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"api_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"api_key\",\"display_name\":\"API Key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional, Union\\n\\nfrom langchain.schema import BaseRetriever\\nfrom langchain_community.vectorstores import VectorStore\\nfrom langchain_community.vectorstores.qdrant import Qdrant\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Document, Embeddings, NestedDict\\n\\n\\nclass QdrantComponent(CustomComponent):\\n display_name = \\\"Qdrant\\\"\\n description = \\\"Construct Qdrant wrapper from a list of texts.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"documents\\\": {\\\"display_name\\\": \\\"Documents\\\"},\\n \\\"embedding\\\": {\\\"display_name\\\": \\\"Embedding\\\"},\\n \\\"api_key\\\": {\\\"display_name\\\": \\\"API Key\\\", \\\"password\\\": True, \\\"advanced\\\": True},\\n \\\"collection_name\\\": {\\\"display_name\\\": \\\"Collection Name\\\"},\\n \\\"content_payload_key\\\": {\\\"display_name\\\": \\\"Content Payload Key\\\", \\\"advanced\\\": True},\\n \\\"distance_func\\\": {\\\"display_name\\\": \\\"Distance Function\\\", \\\"advanced\\\": True},\\n \\\"grpc_port\\\": {\\\"display_name\\\": \\\"gRPC Port\\\", \\\"advanced\\\": True},\\n \\\"host\\\": {\\\"display_name\\\": \\\"Host\\\", \\\"advanced\\\": True},\\n \\\"https\\\": {\\\"display_name\\\": \\\"HTTPS\\\", \\\"advanced\\\": True},\\n \\\"location\\\": {\\\"display_name\\\": \\\"Location\\\", \\\"advanced\\\": True},\\n \\\"metadata_payload_key\\\": {\\\"display_name\\\": \\\"Metadata Payload Key\\\", \\\"advanced\\\": True},\\n \\\"path\\\": {\\\"display_name\\\": \\\"Path\\\", \\\"advanced\\\": True},\\n \\\"port\\\": {\\\"display_name\\\": \\\"Port\\\", \\\"advanced\\\": True},\\n \\\"prefer_grpc\\\": {\\\"display_name\\\": \\\"Prefer gRPC\\\", \\\"advanced\\\": True},\\n \\\"prefix\\\": {\\\"display_name\\\": \\\"Prefix\\\", \\\"advanced\\\": True},\\n \\\"search_kwargs\\\": {\\\"display_name\\\": \\\"Search Kwargs\\\", \\\"advanced\\\": True},\\n \\\"timeout\\\": {\\\"display_name\\\": \\\"Timeout\\\", \\\"advanced\\\": True},\\n \\\"url\\\": {\\\"display_name\\\": \\\"URL\\\", \\\"advanced\\\": True},\\n }\\n\\n def build(\\n self,\\n embedding: Embeddings,\\n collection_name: str,\\n documents: Optional[Document] = None,\\n api_key: Optional[str] = None,\\n content_payload_key: str = \\\"page_content\\\",\\n distance_func: str = \\\"Cosine\\\",\\n grpc_port: int = 6334,\\n https: bool = False,\\n host: Optional[str] = None,\\n location: Optional[str] = None,\\n metadata_payload_key: str = \\\"metadata\\\",\\n path: Optional[str] = None,\\n port: Optional[int] = 6333,\\n prefer_grpc: bool = False,\\n prefix: Optional[str] = None,\\n search_kwargs: Optional[NestedDict] = None,\\n timeout: Optional[int] = None,\\n url: Optional[str] = None,\\n ) -> Union[VectorStore, Qdrant, BaseRetriever]:\\n if documents is None:\\n from qdrant_client import QdrantClient\\n\\n client = QdrantClient(\\n location=location,\\n url=host,\\n port=port,\\n grpc_port=grpc_port,\\n https=https,\\n prefix=prefix,\\n timeout=timeout,\\n prefer_grpc=prefer_grpc,\\n metadata_payload_key=metadata_payload_key,\\n content_payload_key=content_payload_key,\\n api_key=api_key,\\n collection_name=collection_name,\\n host=host,\\n path=path,\\n )\\n vs = Qdrant(\\n client=client,\\n collection_name=collection_name,\\n embeddings=embedding,\\n )\\n return vs\\n else:\\n vs = Qdrant.from_documents(\\n documents=documents, # type: ignore\\n embedding=embedding,\\n api_key=api_key,\\n collection_name=collection_name,\\n content_payload_key=content_payload_key,\\n distance_func=distance_func,\\n grpc_port=grpc_port,\\n host=host,\\n https=https,\\n location=location,\\n metadata_payload_key=metadata_payload_key,\\n path=path,\\n port=port,\\n prefer_grpc=prefer_grpc,\\n prefix=prefix,\\n search_kwargs=search_kwargs,\\n timeout=timeout,\\n url=url,\\n )\\n return vs\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"collection_name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"collection_name\",\"display_name\":\"Collection Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"content_payload_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"page_content\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"content_payload_key\",\"display_name\":\"Content Payload Key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"distance_func\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"Cosine\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"distance_func\",\"display_name\":\"Distance Function\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"grpc_port\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":6334,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"grpc_port\",\"display_name\":\"gRPC Port\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"host\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"host\",\"display_name\":\"Host\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"https\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"https\",\"display_name\":\"HTTPS\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"location\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"location\",\"display_name\":\"Location\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"metadata_payload_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"metadata\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata_payload_key\",\"display_name\":\"Metadata Payload Key\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"path\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"path\",\"display_name\":\"Path\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"port\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":6333,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"port\",\"display_name\":\"Port\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"prefer_grpc\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"prefer_grpc\",\"display_name\":\"Prefer gRPC\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"prefix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"prefix\",\"display_name\":\"Prefix\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"search_kwargs\":{\"type\":\"NestedDict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"search_kwargs\",\"display_name\":\"Search Kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"timeout\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"timeout\",\"display_name\":\"Timeout\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"url\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"url\",\"display_name\":\"URL\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Construct Qdrant wrapper from a list of texts.\",\"base_classes\":[\"Runnable\",\"Generic\",\"VectorStore\",\"Qdrant\",\"RunnableSerializable\",\"Serializable\",\"object\",\"BaseRetriever\"],\"display_name\":\"Qdrant\",\"documentation\":\"\",\"custom_fields\":{\"embedding\":null,\"collection_name\":null,\"documents\":null,\"api_key\":null,\"content_payload_key\":null,\"distance_func\":null,\"grpc_port\":null,\"https\":null,\"host\":null,\"location\":null,\"metadata_payload_key\":null,\"path\":null,\"port\":null,\"prefer_grpc\":null,\"prefix\":null,\"search_kwargs\":null,\"timeout\":null,\"url\":null},\"output_types\":[\"VectorStore\",\"Qdrant\",\"BaseRetriever\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"MongoDBAtlasVectorSearch\":{\"template\":{\"documents\":{\"type\":\"Document\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"embedding\":{\"type\":\"Embeddings\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import List, Optional\\n\\nfrom langchain_community.vectorstores import MongoDBAtlasVectorSearch\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import (\\n Document,\\n Embeddings,\\n NestedDict,\\n)\\n\\n\\nclass MongoDBAtlasComponent(CustomComponent):\\n display_name = \\\"MongoDB Atlas\\\"\\n description = \\\"Construct a `MongoDB Atlas Vector Search` vector store from raw documents.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"documents\\\": {\\\"display_name\\\": \\\"Documents\\\"},\\n \\\"embedding\\\": {\\\"display_name\\\": \\\"Embedding\\\"},\\n \\\"collection_name\\\": {\\\"display_name\\\": \\\"Collection Name\\\"},\\n \\\"db_name\\\": {\\\"display_name\\\": \\\"Database Name\\\"},\\n \\\"index_name\\\": {\\\"display_name\\\": \\\"Index Name\\\"},\\n \\\"mongodb_atlas_cluster_uri\\\": {\\\"display_name\\\": \\\"MongoDB Atlas Cluster URI\\\"},\\n \\\"search_kwargs\\\": {\\\"display_name\\\": \\\"Search Kwargs\\\", \\\"advanced\\\": True},\\n }\\n\\n def build(\\n self,\\n documents: List[Document],\\n embedding: Embeddings,\\n collection_name: str = \\\"\\\",\\n db_name: str = \\\"\\\",\\n index_name: str = \\\"\\\",\\n mongodb_atlas_cluster_uri: str = \\\"\\\",\\n search_kwargs: Optional[NestedDict] = None,\\n ) -> MongoDBAtlasVectorSearch:\\n search_kwargs = search_kwargs or {}\\n return MongoDBAtlasVectorSearch(\\n documents=documents,\\n embedding=embedding,\\n collection_name=collection_name,\\n db_name=db_name,\\n index_name=index_name,\\n mongodb_atlas_cluster_uri=mongodb_atlas_cluster_uri,\\n search_kwargs=search_kwargs,\\n )\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"collection_name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"collection_name\",\"display_name\":\"Collection Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"db_name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"db_name\",\"display_name\":\"Database Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"index_name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"index_name\",\"display_name\":\"Index Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"mongodb_atlas_cluster_uri\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"mongodb_atlas_cluster_uri\",\"display_name\":\"MongoDB Atlas Cluster URI\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"search_kwargs\":{\"type\":\"NestedDict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"search_kwargs\",\"display_name\":\"Search Kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Construct a `MongoDB Atlas Vector Search` vector store from raw documents.\",\"base_classes\":[\"VectorStore\",\"MongoDBAtlasVectorSearch\"],\"display_name\":\"MongoDB Atlas\",\"documentation\":\"\",\"custom_fields\":{\"documents\":null,\"embedding\":null,\"collection_name\":null,\"db_name\":null,\"index_name\":null,\"mongodb_atlas_cluster_uri\":null,\"search_kwargs\":null},\"output_types\":[\"MongoDBAtlasVectorSearch\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"ChromaSearch\":{\"template\":{\"embedding\":{\"type\":\"Embeddings\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"Embedding model to vectorize inputs (make sure to use same as index)\",\"title_case\":false},\"inputs\":{\"type\":\"Text\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"inputs\",\"display_name\":\"Input\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"chroma_server_cors_allow_origins\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chroma_server_cors_allow_origins\",\"display_name\":\"Server CORS Allow Origins\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"chroma_server_grpc_port\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chroma_server_grpc_port\",\"display_name\":\"Server gRPC Port\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"chroma_server_host\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chroma_server_host\",\"display_name\":\"Server Host\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"chroma_server_port\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chroma_server_port\",\"display_name\":\"Server Port\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"chroma_server_ssl_enabled\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"chroma_server_ssl_enabled\",\"display_name\":\"Server SSL Enabled\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import List, Optional\\n\\nimport chromadb # type: ignore\\nfrom langchain_community.vectorstores.chroma import Chroma\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Embeddings, Text\\nfrom langflow.schema import Record, docs_to_records\\n\\n\\nclass ChromaSearchComponent(CustomComponent):\\n \\\"\\\"\\\"\\n A custom component for implementing a Vector Store using Chroma.\\n \\\"\\\"\\\"\\n\\n display_name: str = \\\"Chroma Search\\\"\\n description: str = \\\"Search a Chroma collection for similar documents.\\\"\\n beta: bool = True\\n icon = \\\"Chroma\\\"\\n\\n def build_config(self):\\n \\\"\\\"\\\"\\n Builds the configuration for the component.\\n\\n Returns:\\n - dict: A dictionary containing the configuration options for the component.\\n \\\"\\\"\\\"\\n return {\\n \\\"inputs\\\": {\\\"display_name\\\": \\\"Input\\\"},\\n \\\"search_type\\\": {\\n \\\"display_name\\\": \\\"Search Type\\\",\\n \\\"options\\\": [\\\"Similarity\\\", \\\"MMR\\\"],\\n },\\n \\\"collection_name\\\": {\\\"display_name\\\": \\\"Collection Name\\\", \\\"value\\\": \\\"langflow\\\"},\\n # \\\"persist\\\": {\\\"display_name\\\": \\\"Persist\\\"},\\n \\\"index_directory\\\": {\\\"display_name\\\": \\\"Index Directory\\\"},\\n \\\"code\\\": {\\\"show\\\": False, \\\"display_name\\\": \\\"Code\\\"},\\n \\\"documents\\\": {\\\"display_name\\\": \\\"Documents\\\", \\\"is_list\\\": True},\\n \\\"embedding\\\": {\\n \\\"display_name\\\": \\\"Embedding\\\",\\n \\\"info\\\": \\\"Embedding model to vectorize inputs (make sure to use same as index)\\\",\\n },\\n \\\"chroma_server_cors_allow_origins\\\": {\\n \\\"display_name\\\": \\\"Server CORS Allow Origins\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"chroma_server_host\\\": {\\\"display_name\\\": \\\"Server Host\\\", \\\"advanced\\\": True},\\n \\\"chroma_server_port\\\": {\\\"display_name\\\": \\\"Server Port\\\", \\\"advanced\\\": True},\\n \\\"chroma_server_grpc_port\\\": {\\n \\\"display_name\\\": \\\"Server gRPC Port\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"chroma_server_ssl_enabled\\\": {\\n \\\"display_name\\\": \\\"Server SSL Enabled\\\",\\n \\\"advanced\\\": True,\\n },\\n }\\n\\n def build(\\n self,\\n inputs: Text,\\n search_type: str,\\n collection_name: str,\\n embedding: Embeddings,\\n chroma_server_ssl_enabled: bool,\\n index_directory: Optional[str] = None,\\n chroma_server_cors_allow_origins: Optional[str] = None,\\n chroma_server_host: Optional[str] = None,\\n chroma_server_port: Optional[int] = None,\\n chroma_server_grpc_port: Optional[int] = None,\\n ) -> List[Record]:\\n \\\"\\\"\\\"\\n Builds the Vector Store or BaseRetriever object.\\n\\n Args:\\n - collection_name (str): The name of the collection.\\n - persist_directory (Optional[str]): The directory to persist the Vector Store to.\\n - chroma_server_ssl_enabled (bool): Whether to enable SSL for the Chroma server.\\n - persist (bool): Whether to persist the Vector Store or not.\\n - embedding (Optional[Embeddings]): The embeddings to use for the Vector Store.\\n - documents (Optional[Document]): The documents to use for the Vector Store.\\n - chroma_server_cors_allow_origins (Optional[str]): The CORS allow origins for the Chroma server.\\n - chroma_server_host (Optional[str]): The host for the Chroma server.\\n - chroma_server_port (Optional[int]): The port for the Chroma server.\\n - chroma_server_grpc_port (Optional[int]): The gRPC port for the Chroma server.\\n\\n Returns:\\n - Union[VectorStore, BaseRetriever]: The Vector Store or BaseRetriever object.\\n \\\"\\\"\\\"\\n\\n # Chroma settings\\n chroma_settings = None\\n\\n if chroma_server_host is not None:\\n chroma_settings = chromadb.config.Settings(\\n chroma_server_cors_allow_origins=chroma_server_cors_allow_origins or None,\\n chroma_server_host=chroma_server_host,\\n chroma_server_port=chroma_server_port or None,\\n chroma_server_grpc_port=chroma_server_grpc_port or None,\\n chroma_server_ssl_enabled=chroma_server_ssl_enabled,\\n )\\n index_directory = self.resolve_path(index_directory)\\n chroma = Chroma(\\n embedding_function=embedding,\\n collection_name=collection_name,\\n persist_directory=index_directory,\\n client_settings=chroma_settings,\\n )\\n\\n # Validate the inputs\\n docs = []\\n if inputs and isinstance(inputs, str):\\n docs = chroma.search(query=inputs, search_type=search_type.lower())\\n else:\\n raise ValueError(\\\"Invalid inputs provided.\\\")\\n return docs_to_records(docs)\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"collection_name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"langflow\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"collection_name\",\"display_name\":\"Collection Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"index_directory\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"index_directory\",\"display_name\":\"Index Directory\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"search_type\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"Similarity\",\"MMR\"],\"name\":\"search_type\",\"display_name\":\"Search Type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Search a Chroma collection for similar documents.\",\"icon\":\"Chroma\",\"base_classes\":[\"Record\"],\"display_name\":\"Chroma Search\",\"documentation\":\"\",\"custom_fields\":{\"inputs\":null,\"search_type\":null,\"collection_name\":null,\"embedding\":null,\"chroma_server_ssl_enabled\":null,\"index_directory\":null,\"chroma_server_cors_allow_origins\":null,\"chroma_server_host\":null,\"chroma_server_port\":null,\"chroma_server_grpc_port\":null},\"output_types\":[\"Record\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"FAISS\":{\"template\":{\"documents\":{\"type\":\"Document\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"documents\",\"display_name\":\"Documents\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"embedding\":{\"type\":\"Embeddings\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"embedding\",\"display_name\":\"Embedding\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import List, Union\\n\\nfrom langchain.schema import BaseRetriever\\nfrom langchain_community.vectorstores import VectorStore\\nfrom langchain_community.vectorstores.faiss import FAISS\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Document, Embeddings\\n\\n\\nclass FAISSComponent(CustomComponent):\\n display_name = \\\"FAISS\\\"\\n description = \\\"Construct FAISS wrapper from raw documents.\\\"\\n documentation = \\\"https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/faiss\\\"\\n\\n def build_config(self):\\n return {\\n \\\"documents\\\": {\\\"display_name\\\": \\\"Documents\\\"},\\n \\\"embedding\\\": {\\\"display_name\\\": \\\"Embedding\\\"},\\n }\\n\\n def build(\\n self,\\n embedding: Embeddings,\\n documents: List[Document],\\n ) -> Union[VectorStore, FAISS, BaseRetriever]:\\n return FAISS.from_documents(documents=documents, embedding=embedding)\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Construct FAISS wrapper from raw documents.\",\"base_classes\":[\"Runnable\",\"FAISS\",\"Generic\",\"VectorStore\",\"RunnableSerializable\",\"Serializable\",\"object\",\"BaseRetriever\"],\"display_name\":\"FAISS\",\"documentation\":\"https://python.langchain.com/docs/modules/data_connection/vectorstores/integrations/faiss\",\"custom_fields\":{\"embedding\":null,\"documents\":null},\"output_types\":[\"VectorStore\",\"FAISS\",\"BaseRetriever\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true}},\"models\":{\"LlamaCppModel\":{\"template\":{\"metadata\":{\"type\":\"Dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"model_kwargs\":{\"type\":\"Dict\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model_kwargs\",\"display_name\":\"Model Kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"model_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[\".bin\"],\"file_path\":\"\",\"password\":false,\"name\":\"model_path\",\"display_name\":\"Model Path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"cache\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"cache\",\"display_name\":\"Cache\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"client\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"client\",\"display_name\":\"Client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Any, Dict, List, Optional\\n\\nfrom langchain_community.llms.llamacpp import LlamaCpp\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Text\\n\\n\\nclass LlamaCppComponent(CustomComponent):\\n display_name = \\\"LlamaCppModel\\\"\\n description = \\\"Generate text using llama.cpp model.\\\"\\n documentation = \\\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/llamacpp\\\"\\n\\n def build_config(self):\\n return {\\n \\\"grammar\\\": {\\\"display_name\\\": \\\"Grammar\\\", \\\"advanced\\\": True},\\n \\\"cache\\\": {\\\"display_name\\\": \\\"Cache\\\", \\\"advanced\\\": True},\\n \\\"client\\\": {\\\"display_name\\\": \\\"Client\\\", \\\"advanced\\\": True},\\n \\\"echo\\\": {\\\"display_name\\\": \\\"Echo\\\", \\\"advanced\\\": True},\\n \\\"f16_kv\\\": {\\\"display_name\\\": \\\"F16 KV\\\", \\\"advanced\\\": True},\\n \\\"grammar_path\\\": {\\\"display_name\\\": \\\"Grammar Path\\\", \\\"advanced\\\": True},\\n \\\"last_n_tokens_size\\\": {\\n \\\"display_name\\\": \\\"Last N Tokens Size\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"logits_all\\\": {\\\"display_name\\\": \\\"Logits All\\\", \\\"advanced\\\": True},\\n \\\"logprobs\\\": {\\\"display_name\\\": \\\"Logprobs\\\", \\\"advanced\\\": True},\\n \\\"lora_base\\\": {\\\"display_name\\\": \\\"Lora Base\\\", \\\"advanced\\\": True},\\n \\\"lora_path\\\": {\\\"display_name\\\": \\\"Lora Path\\\", \\\"advanced\\\": True},\\n \\\"max_tokens\\\": {\\\"display_name\\\": \\\"Max Tokens\\\", \\\"advanced\\\": True},\\n \\\"metadata\\\": {\\\"display_name\\\": \\\"Metadata\\\", \\\"advanced\\\": True},\\n \\\"model_kwargs\\\": {\\\"display_name\\\": \\\"Model Kwargs\\\", \\\"advanced\\\": True},\\n \\\"model_path\\\": {\\n \\\"display_name\\\": \\\"Model Path\\\",\\n \\\"field_type\\\": \\\"file\\\",\\n \\\"file_types\\\": [\\\".bin\\\"],\\n \\\"required\\\": True,\\n },\\n \\\"n_batch\\\": {\\\"display_name\\\": \\\"N Batch\\\", \\\"advanced\\\": True},\\n \\\"n_ctx\\\": {\\\"display_name\\\": \\\"N Ctx\\\", \\\"advanced\\\": True},\\n \\\"n_gpu_layers\\\": {\\\"display_name\\\": \\\"N GPU Layers\\\", \\\"advanced\\\": True},\\n \\\"n_parts\\\": {\\\"display_name\\\": \\\"N Parts\\\", \\\"advanced\\\": True},\\n \\\"n_threads\\\": {\\\"display_name\\\": \\\"N Threads\\\", \\\"advanced\\\": True},\\n \\\"repeat_penalty\\\": {\\\"display_name\\\": \\\"Repeat Penalty\\\", \\\"advanced\\\": True},\\n \\\"rope_freq_base\\\": {\\\"display_name\\\": \\\"Rope Freq Base\\\", \\\"advanced\\\": True},\\n \\\"rope_freq_scale\\\": {\\\"display_name\\\": \\\"Rope Freq Scale\\\", \\\"advanced\\\": True},\\n \\\"seed\\\": {\\\"display_name\\\": \\\"Seed\\\", \\\"advanced\\\": True},\\n \\\"stop\\\": {\\\"display_name\\\": \\\"Stop\\\", \\\"advanced\\\": True},\\n \\\"streaming\\\": {\\\"display_name\\\": \\\"Streaming\\\", \\\"advanced\\\": True},\\n \\\"suffix\\\": {\\\"display_name\\\": \\\"Suffix\\\", \\\"advanced\\\": True},\\n \\\"tags\\\": {\\\"display_name\\\": \\\"Tags\\\", \\\"advanced\\\": True},\\n \\\"temperature\\\": {\\\"display_name\\\": \\\"Temperature\\\"},\\n \\\"top_k\\\": {\\\"display_name\\\": \\\"Top K\\\", \\\"advanced\\\": True},\\n \\\"top_p\\\": {\\\"display_name\\\": \\\"Top P\\\", \\\"advanced\\\": True},\\n \\\"use_mlock\\\": {\\\"display_name\\\": \\\"Use Mlock\\\", \\\"advanced\\\": True},\\n \\\"use_mmap\\\": {\\\"display_name\\\": \\\"Use Mmap\\\", \\\"advanced\\\": True},\\n \\\"verbose\\\": {\\\"display_name\\\": \\\"Verbose\\\", \\\"advanced\\\": True},\\n \\\"vocab_only\\\": {\\\"display_name\\\": \\\"Vocab Only\\\", \\\"advanced\\\": True},\\n \\\"inputs\\\": {\\\"display_name\\\": \\\"Input\\\"},\\n }\\n\\n def build(\\n self,\\n model_path: str,\\n inputs: str,\\n grammar: Optional[str] = None,\\n cache: Optional[bool] = None,\\n client: Optional[Any] = None,\\n echo: Optional[bool] = False,\\n f16_kv: bool = True,\\n grammar_path: Optional[str] = None,\\n last_n_tokens_size: Optional[int] = 64,\\n logits_all: bool = False,\\n logprobs: Optional[int] = None,\\n lora_base: Optional[str] = None,\\n lora_path: Optional[str] = None,\\n max_tokens: Optional[int] = 256,\\n metadata: Optional[Dict] = None,\\n model_kwargs: Dict = {},\\n n_batch: Optional[int] = 8,\\n n_ctx: int = 512,\\n n_gpu_layers: Optional[int] = 1,\\n n_parts: int = -1,\\n n_threads: Optional[int] = 1,\\n repeat_penalty: Optional[float] = 1.1,\\n rope_freq_base: float = 10000.0,\\n rope_freq_scale: float = 1.0,\\n seed: int = -1,\\n stop: Optional[List[str]] = [],\\n streaming: bool = True,\\n suffix: Optional[str] = \\\"\\\",\\n tags: Optional[List[str]] = [],\\n temperature: Optional[float] = 0.8,\\n top_k: Optional[int] = 40,\\n top_p: Optional[float] = 0.95,\\n use_mlock: bool = False,\\n use_mmap: Optional[bool] = True,\\n verbose: bool = True,\\n vocab_only: bool = False,\\n ) -> Text:\\n output = LlamaCpp(\\n model_path=model_path,\\n grammar=grammar,\\n cache=cache,\\n client=client,\\n echo=echo,\\n f16_kv=f16_kv,\\n grammar_path=grammar_path,\\n last_n_tokens_size=last_n_tokens_size,\\n logits_all=logits_all,\\n logprobs=logprobs,\\n lora_base=lora_base,\\n lora_path=lora_path,\\n max_tokens=max_tokens,\\n metadata=metadata,\\n model_kwargs=model_kwargs,\\n n_batch=n_batch,\\n n_ctx=n_ctx,\\n n_gpu_layers=n_gpu_layers,\\n n_parts=n_parts,\\n n_threads=n_threads,\\n repeat_penalty=repeat_penalty,\\n rope_freq_base=rope_freq_base,\\n rope_freq_scale=rope_freq_scale,\\n seed=seed,\\n stop=stop,\\n streaming=streaming,\\n suffix=suffix,\\n tags=tags,\\n temperature=temperature,\\n top_k=top_k,\\n top_p=top_p,\\n use_mlock=use_mlock,\\n use_mmap=use_mmap,\\n verbose=verbose,\\n vocab_only=vocab_only,\\n )\\n message = output.invoke(inputs)\\n result = message.content if hasattr(message, \\\"content\\\") else message\\n self.status = result\\n return result\\n self.status = result\\n return result\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"echo\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"echo\",\"display_name\":\"Echo\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"f16_kv\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":true,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"f16_kv\",\"display_name\":\"F16 KV\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"grammar\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"grammar\",\"display_name\":\"Grammar\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"grammar_path\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"grammar_path\",\"display_name\":\"Grammar Path\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"inputs\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"inputs\",\"display_name\":\"Input\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"last_n_tokens_size\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":64,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"last_n_tokens_size\",\"display_name\":\"Last N Tokens Size\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"logits_all\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"logits_all\",\"display_name\":\"Logits All\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"logprobs\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"logprobs\",\"display_name\":\"Logprobs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"lora_base\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"lora_base\",\"display_name\":\"Lora Base\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"lora_path\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"lora_path\",\"display_name\":\"Lora Path\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"max_tokens\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":256,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_tokens\",\"display_name\":\"Max Tokens\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"n_batch\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":8,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"n_batch\",\"display_name\":\"N Batch\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"n_ctx\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":512,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"n_ctx\",\"display_name\":\"N Ctx\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"n_gpu_layers\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"n_gpu_layers\",\"display_name\":\"N GPU Layers\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"n_parts\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":-1,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"n_parts\",\"display_name\":\"N Parts\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"n_threads\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"n_threads\",\"display_name\":\"N Threads\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"repeat_penalty\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1.1,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"repeat_penalty\",\"display_name\":\"Repeat Penalty\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"rope_freq_base\":{\"type\":\"float\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":10000.0,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"rope_freq_base\",\"display_name\":\"Rope Freq Base\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"rope_freq_scale\":{\"type\":\"float\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1.0,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"rope_freq_scale\",\"display_name\":\"Rope Freq Scale\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"seed\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":-1,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"seed\",\"display_name\":\"Seed\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"stop\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":[],\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"stop\",\"display_name\":\"Stop\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"streaming\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":true,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"streaming\",\"display_name\":\"Streaming\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"suffix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"suffix\",\"display_name\":\"Suffix\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":[],\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"display_name\":\"Tags\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.8,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"top_k\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":40,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_k\",\"display_name\":\"Top K\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"top_p\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.95,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_p\",\"display_name\":\"Top P\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"use_mlock\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"use_mlock\",\"display_name\":\"Use Mlock\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"use_mmap\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":true,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"use_mmap\",\"display_name\":\"Use Mmap\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"verbose\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":true,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"verbose\",\"display_name\":\"Verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"vocab_only\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"vocab_only\",\"display_name\":\"Vocab Only\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Generate text using llama.cpp model.\",\"base_classes\":[\"Text\",\"object\"],\"display_name\":\"LlamaCppModel\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/llamacpp\",\"custom_fields\":{\"model_path\":null,\"inputs\":null,\"grammar\":null,\"cache\":null,\"client\":null,\"echo\":null,\"f16_kv\":null,\"grammar_path\":null,\"last_n_tokens_size\":null,\"logits_all\":null,\"logprobs\":null,\"lora_base\":null,\"lora_path\":null,\"max_tokens\":null,\"metadata\":null,\"model_kwargs\":null,\"n_batch\":null,\"n_ctx\":null,\"n_gpu_layers\":null,\"n_parts\":null,\"n_threads\":null,\"repeat_penalty\":null,\"rope_freq_base\":null,\"rope_freq_scale\":null,\"seed\":null,\"stop\":null,\"streaming\":null,\"suffix\":null,\"tags\":null,\"temperature\":null,\"top_k\":null,\"top_p\":null,\"use_mlock\":null,\"use_mmap\":null,\"verbose\":null,\"vocab_only\":null},\"output_types\":[\"Text\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"BaiduQianfanChatModel\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain_community.chat_models.baidu_qianfan_endpoint import QianfanChatEndpoint\\nfrom pydantic.v1 import SecretStr\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Text\\n\\n\\nclass QianfanChatEndpointComponent(CustomComponent):\\n display_name: str = \\\"QianfanChat Model\\\"\\n description: str = (\\n \\\"Generate text using Baidu Qianfan chat models. Get more detail from \\\"\\n \\\"https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint.\\\"\\n )\\n\\n def build_config(self):\\n return {\\n \\\"model\\\": {\\n \\\"display_name\\\": \\\"Model Name\\\",\\n \\\"options\\\": [\\n \\\"ERNIE-Bot\\\",\\n \\\"ERNIE-Bot-turbo\\\",\\n \\\"BLOOMZ-7B\\\",\\n \\\"Llama-2-7b-chat\\\",\\n \\\"Llama-2-13b-chat\\\",\\n \\\"Llama-2-70b-chat\\\",\\n \\\"Qianfan-BLOOMZ-7B-compressed\\\",\\n \\\"Qianfan-Chinese-Llama-2-7B\\\",\\n \\\"ChatGLM2-6B-32K\\\",\\n \\\"AquilaChat-7B\\\",\\n ],\\n \\\"info\\\": \\\"https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint\\\",\\n \\\"required\\\": True,\\n },\\n \\\"qianfan_ak\\\": {\\n \\\"display_name\\\": \\\"Qianfan Ak\\\",\\n \\\"required\\\": True,\\n \\\"password\\\": True,\\n \\\"info\\\": \\\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\\\",\\n },\\n \\\"qianfan_sk\\\": {\\n \\\"display_name\\\": \\\"Qianfan Sk\\\",\\n \\\"required\\\": True,\\n \\\"password\\\": True,\\n \\\"info\\\": \\\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\\\",\\n },\\n \\\"top_p\\\": {\\n \\\"display_name\\\": \\\"Top p\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\\\",\\n \\\"value\\\": 0.8,\\n },\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\\\",\\n \\\"value\\\": 0.95,\\n },\\n \\\"penalty_score\\\": {\\n \\\"display_name\\\": \\\"Penalty Score\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\\\",\\n \\\"value\\\": 1.0,\\n },\\n \\\"endpoint\\\": {\\n \\\"display_name\\\": \\\"Endpoint\\\",\\n \\\"info\\\": \\\"Endpoint of the Qianfan LLM, required if custom model used.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n \\\"inputs\\\": {\\\"display_name\\\": \\\"Input\\\"},\\n }\\n\\n def build(\\n self,\\n inputs: str,\\n model: str = \\\"ERNIE-Bot-turbo\\\",\\n qianfan_ak: Optional[str] = None,\\n qianfan_sk: Optional[str] = None,\\n top_p: Optional[float] = None,\\n temperature: Optional[float] = None,\\n penalty_score: Optional[float] = None,\\n endpoint: Optional[str] = None,\\n ) -> Text:\\n try:\\n output = QianfanChatEndpoint( # type: ignore\\n model=model,\\n qianfan_ak=SecretStr(qianfan_ak) if qianfan_ak else None,\\n qianfan_sk=SecretStr(qianfan_sk) if qianfan_sk else None,\\n top_p=top_p,\\n temperature=temperature,\\n penalty_score=penalty_score,\\n endpoint=endpoint,\\n )\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to Baidu Qianfan API.\\\") from e\\n message = output.invoke(inputs)\\n result = message.content if hasattr(message, \\\"content\\\") else message\\n self.status = result\\n return result\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"endpoint\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"endpoint\",\"display_name\":\"Endpoint\",\"advanced\":false,\"dynamic\":false,\"info\":\"Endpoint of the Qianfan LLM, required if custom model used.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"inputs\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"inputs\",\"display_name\":\"Input\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"model\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"ERNIE-Bot-turbo\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"ERNIE-Bot\",\"ERNIE-Bot-turbo\",\"BLOOMZ-7B\",\"Llama-2-7b-chat\",\"Llama-2-13b-chat\",\"Llama-2-70b-chat\",\"Qianfan-BLOOMZ-7B-compressed\",\"Qianfan-Chinese-Llama-2-7B\",\"ChatGLM2-6B-32K\",\"AquilaChat-7B\"],\"name\":\"model\",\"display_name\":\"Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint\",\"title_case\":false,\"input_types\":[\"Text\"]},\"penalty_score\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1.0,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"penalty_score\",\"display_name\":\"Penalty Score\",\"advanced\":false,\"dynamic\":false,\"info\":\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"qianfan_ak\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"qianfan_ak\",\"display_name\":\"Qianfan Ak\",\"advanced\":false,\"dynamic\":false,\"info\":\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\",\"title_case\":false,\"input_types\":[\"Text\"]},\"qianfan_sk\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"qianfan_sk\",\"display_name\":\"Qianfan Sk\",\"advanced\":false,\"dynamic\":false,\"info\":\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\",\"title_case\":false,\"input_types\":[\"Text\"]},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.95,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"top_p\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.8,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_p\",\"display_name\":\"Top p\",\"advanced\":false,\"dynamic\":false,\"info\":\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Generate text using Baidu Qianfan chat models. Get more detail from https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint.\",\"base_classes\":[\"Text\",\"object\"],\"display_name\":\"QianfanChat Model\",\"documentation\":\"\",\"custom_fields\":{\"inputs\":null,\"model\":null,\"qianfan_ak\":null,\"qianfan_sk\":null,\"top_p\":null,\"temperature\":null,\"penalty_score\":null,\"endpoint\":null},\"output_types\":[\"Text\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"GoogleGenerativeAIModel\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain_google_genai import ChatGoogleGenerativeAI # type: ignore\\nfrom pydantic.v1.types import SecretStr\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import RangeSpec, Text\\n\\n\\nclass GoogleGenerativeAIComponent(CustomComponent):\\n display_name: str = \\\"Google Generative AIModel\\\"\\n description: str = \\\"Generate text using Google Generative AI to generate text.\\\"\\n documentation: str = \\\"http://docs.langflow.org/components/custom\\\"\\n\\n def build_config(self):\\n return {\\n \\\"google_api_key\\\": {\\n \\\"display_name\\\": \\\"Google API Key\\\",\\n \\\"info\\\": \\\"The Google API Key to use for the Google Generative AI.\\\",\\n },\\n \\\"max_output_tokens\\\": {\\n \\\"display_name\\\": \\\"Max Output Tokens\\\",\\n \\\"info\\\": \\\"The maximum number of tokens to generate.\\\",\\n },\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"info\\\": \\\"Run inference with this temperature. Must by in the closed interval [0.0, 1.0].\\\",\\n },\\n \\\"top_k\\\": {\\n \\\"display_name\\\": \\\"Top K\\\",\\n \\\"info\\\": \\\"Decode using top-k sampling: consider the set of top_k most probable tokens. Must be positive.\\\",\\n \\\"range_spec\\\": RangeSpec(min=0, max=2, step=0.1),\\n \\\"advanced\\\": True,\\n },\\n \\\"top_p\\\": {\\n \\\"display_name\\\": \\\"Top P\\\",\\n \\\"info\\\": \\\"The maximum cumulative probability of tokens to consider when sampling.\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"n\\\": {\\n \\\"display_name\\\": \\\"N\\\",\\n \\\"info\\\": \\\"Number of chat completions to generate for each prompt. Note that the API may not return the full n completions if duplicates are generated.\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"model\\\": {\\n \\\"display_name\\\": \\\"Model\\\",\\n \\\"info\\\": \\\"The name of the model to use. Supported examples: gemini-pro\\\",\\n \\\"options\\\": [\\\"gemini-pro\\\", \\\"gemini-pro-vision\\\"],\\n },\\n \\\"code\\\": {\\n \\\"advanced\\\": True,\\n },\\n \\\"inputs\\\": {\\\"display_name\\\": \\\"Input\\\"},\\n }\\n\\n def build(\\n self,\\n google_api_key: str,\\n model: str,\\n inputs: str,\\n max_output_tokens: Optional[int] = None,\\n temperature: float = 0.1,\\n top_k: Optional[int] = None,\\n top_p: Optional[float] = None,\\n n: Optional[int] = 1,\\n ) -> Text:\\n output = ChatGoogleGenerativeAI(\\n model=model,\\n max_output_tokens=max_output_tokens or None, # type: ignore\\n temperature=temperature,\\n top_k=top_k or None,\\n top_p=top_p or None, # type: ignore\\n n=n or 1,\\n google_api_key=SecretStr(google_api_key),\\n )\\n message = output.invoke(inputs)\\n result = message.content if hasattr(message, \\\"content\\\") else message\\n self.status = result\\n return result\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"google_api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"google_api_key\",\"display_name\":\"Google API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The Google API Key to use for the Google Generative AI.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"inputs\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"inputs\",\"display_name\":\"Input\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"max_output_tokens\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_output_tokens\",\"display_name\":\"Max Output Tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"The maximum number of tokens to generate.\",\"title_case\":false},\"model\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"gemini-pro\",\"gemini-pro-vision\"],\"name\":\"model\",\"display_name\":\"Model\",\"advanced\":false,\"dynamic\":false,\"info\":\"The name of the model to use. Supported examples: gemini-pro\",\"title_case\":false,\"input_types\":[\"Text\"]},\"n\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"n\",\"display_name\":\"N\",\"advanced\":true,\"dynamic\":false,\"info\":\"Number of chat completions to generate for each prompt. Note that the API may not return the full n completions if duplicates are generated.\",\"title_case\":false},\"temperature\":{\"type\":\"float\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.1,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"Run inference with this temperature. Must by in the closed interval [0.0, 1.0].\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"top_k\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_k\",\"display_name\":\"Top K\",\"advanced\":true,\"dynamic\":false,\"info\":\"Decode using top-k sampling: consider the set of top_k most probable tokens. Must be positive.\",\"rangeSpec\":{\"min\":0.0,\"max\":2.0,\"step\":0.1},\"title_case\":false},\"top_p\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_p\",\"display_name\":\"Top P\",\"advanced\":true,\"dynamic\":false,\"info\":\"The maximum cumulative probability of tokens to consider when sampling.\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Generate text using Google Generative AI to generate text.\",\"base_classes\":[\"Text\",\"object\"],\"display_name\":\"Google Generative AIModel\",\"documentation\":\"http://docs.langflow.org/components/custom\",\"custom_fields\":{\"google_api_key\":null,\"model\":null,\"inputs\":null,\"max_output_tokens\":null,\"temperature\":null,\"top_k\":null,\"top_p\":null,\"n\":null},\"output_types\":[\"Text\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"CTransformersModel\":{\"template\":{\"model_file\":{\"type\":\"file\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[\".bin\"],\"file_path\":\"\",\"password\":false,\"name\":\"model_file\",\"display_name\":\"Model File\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Dict, Optional\\n\\nfrom langchain_community.llms.ctransformers import CTransformers\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Text\\n\\n\\nclass CTransformersComponent(CustomComponent):\\n display_name = \\\"CTransformersModel\\\"\\n description = \\\"Generate text using CTransformers LLM models\\\"\\n documentation = \\\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/ctransformers\\\"\\n\\n def build_config(self):\\n return {\\n \\\"model\\\": {\\\"display_name\\\": \\\"Model\\\", \\\"required\\\": True},\\n \\\"model_file\\\": {\\n \\\"display_name\\\": \\\"Model File\\\",\\n \\\"required\\\": False,\\n \\\"field_type\\\": \\\"file\\\",\\n \\\"file_types\\\": [\\\".bin\\\"],\\n },\\n \\\"model_type\\\": {\\\"display_name\\\": \\\"Model Type\\\", \\\"required\\\": True},\\n \\\"config\\\": {\\n \\\"display_name\\\": \\\"Config\\\",\\n \\\"advanced\\\": True,\\n \\\"required\\\": False,\\n \\\"field_type\\\": \\\"dict\\\",\\n \\\"value\\\": '{\\\"top_k\\\":40,\\\"top_p\\\":0.95,\\\"temperature\\\":0.8,\\\"repetition_penalty\\\":1.1,\\\"last_n_tokens\\\":64,\\\"seed\\\":-1,\\\"max_new_tokens\\\":256,\\\"stop\\\":\\\"\\\",\\\"stream\\\":\\\"False\\\",\\\"reset\\\":\\\"True\\\",\\\"batch_size\\\":8,\\\"threads\\\":-1,\\\"context_length\\\":-1,\\\"gpu_layers\\\":0}',\\n },\\n \\\"inputs\\\": {\\\"display_name\\\": \\\"Input\\\"},\\n }\\n\\n def build(\\n self,\\n model: str,\\n model_file: str,\\n inputs: str,\\n model_type: str,\\n config: Optional[Dict] = None,\\n ) -> Text:\\n output = CTransformers(model=model, model_file=model_file, model_type=model_type, config=config)\\n message = output.invoke(inputs)\\n result = message.content if hasattr(message, \\\"content\\\") else message\\n self.status = result\\n return result\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"config\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"{\\\"top_k\\\":40,\\\"top_p\\\":0.95,\\\"temperature\\\":0.8,\\\"repetition_penalty\\\":1.1,\\\"last_n_tokens\\\":64,\\\"seed\\\":-1,\\\"max_new_tokens\\\":256,\\\"stop\\\":\\\"\\\",\\\"stream\\\":\\\"False\\\",\\\"reset\\\":\\\"True\\\",\\\"batch_size\\\":8,\\\"threads\\\":-1,\\\"context_length\\\":-1,\\\"gpu_layers\\\":0}\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"config\",\"display_name\":\"Config\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"inputs\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"inputs\",\"display_name\":\"Input\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"model\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model\",\"display_name\":\"Model\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"model_type\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model_type\",\"display_name\":\"Model Type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Generate text using CTransformers LLM models\",\"base_classes\":[\"Text\",\"object\"],\"display_name\":\"CTransformersModel\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/ctransformers\",\"custom_fields\":{\"model\":null,\"model_file\":null,\"inputs\":null,\"model_type\":null,\"config\":null},\"output_types\":[\"Text\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"VertexAiModel\":{\"template\":{\"credentials\":{\"type\":\"file\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[\".json\"],\"password\":false,\"name\":\"credentials\",\"display_name\":\"Credentials\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"examples\":{\"type\":\"BaseMessage\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":true,\"value\":[],\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"examples\",\"display_name\":\"Examples\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import List, Optional\\n\\nfrom langchain_core.messages.base import BaseMessage\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Text\\n\\n\\nclass ChatVertexAIComponent(CustomComponent):\\n display_name = \\\"ChatVertexAIModel\\\"\\n description = \\\"Generate text using Vertex AI Chat large language models API.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"credentials\\\": {\\n \\\"display_name\\\": \\\"Credentials\\\",\\n \\\"field_type\\\": \\\"file\\\",\\n \\\"file_types\\\": [\\\".json\\\"],\\n \\\"file_path\\\": None,\\n },\\n \\\"examples\\\": {\\n \\\"display_name\\\": \\\"Examples\\\",\\n \\\"multiline\\\": True,\\n },\\n \\\"location\\\": {\\n \\\"display_name\\\": \\\"Location\\\",\\n \\\"value\\\": \\\"us-central1\\\",\\n },\\n \\\"max_output_tokens\\\": {\\n \\\"display_name\\\": \\\"Max Output Tokens\\\",\\n \\\"value\\\": 128,\\n \\\"advanced\\\": True,\\n },\\n \\\"model_name\\\": {\\n \\\"display_name\\\": \\\"Model Name\\\",\\n \\\"value\\\": \\\"chat-bison\\\",\\n },\\n \\\"project\\\": {\\n \\\"display_name\\\": \\\"Project\\\",\\n },\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"value\\\": 0.0,\\n },\\n \\\"top_k\\\": {\\n \\\"display_name\\\": \\\"Top K\\\",\\n \\\"value\\\": 40,\\n \\\"advanced\\\": True,\\n },\\n \\\"top_p\\\": {\\n \\\"display_name\\\": \\\"Top P\\\",\\n \\\"value\\\": 0.95,\\n \\\"advanced\\\": True,\\n },\\n \\\"verbose\\\": {\\n \\\"display_name\\\": \\\"Verbose\\\",\\n \\\"value\\\": False,\\n \\\"advanced\\\": True,\\n },\\n \\\"inputs\\\": {\\\"display_name\\\": \\\"Input\\\"},\\n }\\n\\n def build(\\n self,\\n inputs: str,\\n credentials: Optional[str],\\n project: str,\\n examples: Optional[List[BaseMessage]] = [],\\n location: str = \\\"us-central1\\\",\\n max_output_tokens: int = 128,\\n model_name: str = \\\"chat-bison\\\",\\n temperature: float = 0.0,\\n top_k: int = 40,\\n top_p: float = 0.95,\\n verbose: bool = False,\\n ) -> Text:\\n try:\\n from langchain_google_vertexai import ChatVertexAI\\n except ImportError:\\n raise ImportError(\\n \\\"To use the ChatVertexAI model, you need to install the langchain-google-vertexai package.\\\"\\n )\\n output = ChatVertexAI(\\n credentials=credentials,\\n examples=examples,\\n location=location,\\n max_output_tokens=max_output_tokens,\\n model_name=model_name,\\n project=project,\\n temperature=temperature,\\n top_k=top_k,\\n top_p=top_p,\\n verbose=verbose,\\n )\\n message = output.invoke(inputs)\\n result = message.content if hasattr(message, \\\"content\\\") else message\\n self.status = result\\n return result\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"inputs\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"inputs\",\"display_name\":\"Input\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"location\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"us-central1\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"location\",\"display_name\":\"Location\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"max_output_tokens\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":128,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_output_tokens\",\"display_name\":\"Max Output Tokens\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"model_name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"chat-bison\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model_name\",\"display_name\":\"Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"project\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"project\",\"display_name\":\"Project\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"temperature\":{\"type\":\"float\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.0,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"top_k\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":40,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_k\",\"display_name\":\"Top K\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"top_p\":{\"type\":\"float\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.95,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_p\",\"display_name\":\"Top P\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"verbose\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"verbose\",\"display_name\":\"Verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Generate text using Vertex AI Chat large language models API.\",\"base_classes\":[\"Text\",\"object\"],\"display_name\":\"ChatVertexAIModel\",\"documentation\":\"\",\"custom_fields\":{\"inputs\":null,\"credentials\":null,\"project\":null,\"examples\":null,\"location\":null,\"max_output_tokens\":null,\"model_name\":null,\"temperature\":null,\"top_k\":null,\"top_p\":null,\"verbose\":null},\"output_types\":[\"Text\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"OllamaModel\":{\"template\":{\"metadata\":{\"type\":\"Dict[str, Any]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":true,\"dynamic\":false,\"info\":\"Metadata to add to the run trace.\",\"title_case\":false},\"stop\":{\"type\":\"list\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"stop\",\"display_name\":\"Stop Tokens\",\"advanced\":true,\"dynamic\":false,\"info\":\"List of tokens to signal the model to stop generating text.\",\"title_case\":false},\"tags\":{\"type\":\"list\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"display_name\":\"Tags\",\"advanced\":true,\"dynamic\":false,\"info\":\"Tags to add to the run trace.\",\"title_case\":false},\"base_url\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"base_url\",\"display_name\":\"Base URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"Endpoint of the Ollama API. Defaults to 'http://localhost:11434' if not specified.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"cache\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"cache\",\"display_name\":\"Cache\",\"advanced\":true,\"dynamic\":false,\"info\":\"Enable or disable caching.\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Any, Dict, List, Optional\\n\\n# from langchain_community.chat_models import ChatOllama\\nfrom langchain_community.chat_models import ChatOllama\\n\\n# from langchain.chat_models import ChatOllama\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Text\\n\\n# whe When a callback component is added to Langflow, the comment must be uncommented.\\n# from langchain.callbacks.manager import CallbackManager\\n\\n\\nclass ChatOllamaComponent(CustomComponent):\\n display_name = \\\"ChatOllamaModel\\\"\\n description = \\\"Generate text using Local LLM for chat with Ollama.\\\"\\n\\n def build_config(self) -> dict:\\n return {\\n \\\"base_url\\\": {\\n \\\"display_name\\\": \\\"Base URL\\\",\\n \\\"info\\\": \\\"Endpoint of the Ollama API. Defaults to 'http://localhost:11434' if not specified.\\\",\\n },\\n \\\"model\\\": {\\n \\\"display_name\\\": \\\"Model Name\\\",\\n \\\"value\\\": \\\"llama2\\\",\\n \\\"info\\\": \\\"Refer to https://ollama.ai/library for more models.\\\",\\n },\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"value\\\": 0.8,\\n \\\"info\\\": \\\"Controls the creativity of model responses.\\\",\\n },\\n \\\"cache\\\": {\\n \\\"display_name\\\": \\\"Cache\\\",\\n \\\"field_type\\\": \\\"bool\\\",\\n \\\"info\\\": \\\"Enable or disable caching.\\\",\\n \\\"advanced\\\": True,\\n \\\"value\\\": False,\\n },\\n ### When a callback component is added to Langflow, the comment must be uncommented. ###\\n # \\\"callback_manager\\\": {\\n # \\\"display_name\\\": \\\"Callback Manager\\\",\\n # \\\"info\\\": \\\"Optional callback manager for additional functionality.\\\",\\n # \\\"advanced\\\": True,\\n # },\\n # \\\"callbacks\\\": {\\n # \\\"display_name\\\": \\\"Callbacks\\\",\\n # \\\"info\\\": \\\"Callbacks to execute during model runtime.\\\",\\n # \\\"advanced\\\": True,\\n # },\\n ########################################################################################\\n \\\"format\\\": {\\n \\\"display_name\\\": \\\"Format\\\",\\n \\\"field_type\\\": \\\"str\\\",\\n \\\"info\\\": \\\"Specify the format of the output (e.g., json).\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"metadata\\\": {\\n \\\"display_name\\\": \\\"Metadata\\\",\\n \\\"info\\\": \\\"Metadata to add to the run trace.\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"mirostat\\\": {\\n \\\"display_name\\\": \\\"Mirostat\\\",\\n \\\"options\\\": [\\\"Disabled\\\", \\\"Mirostat\\\", \\\"Mirostat 2.0\\\"],\\n \\\"info\\\": \\\"Enable/disable Mirostat sampling for controlling perplexity.\\\",\\n \\\"value\\\": \\\"Disabled\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"mirostat_eta\\\": {\\n \\\"display_name\\\": \\\"Mirostat Eta\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Learning rate for Mirostat algorithm. (Default: 0.1)\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"mirostat_tau\\\": {\\n \\\"display_name\\\": \\\"Mirostat Tau\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Controls the balance between coherence and diversity of the output. (Default: 5.0)\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"num_ctx\\\": {\\n \\\"display_name\\\": \\\"Context Window Size\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"info\\\": \\\"Size of the context window for generating tokens. (Default: 2048)\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"num_gpu\\\": {\\n \\\"display_name\\\": \\\"Number of GPUs\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"info\\\": \\\"Number of GPUs to use for computation. (Default: 1 on macOS, 0 to disable)\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"num_thread\\\": {\\n \\\"display_name\\\": \\\"Number of Threads\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"info\\\": \\\"Number of threads to use during computation. (Default: detected for optimal performance)\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"repeat_last_n\\\": {\\n \\\"display_name\\\": \\\"Repeat Last N\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"info\\\": \\\"How far back the model looks to prevent repetition. (Default: 64, 0 = disabled, -1 = num_ctx)\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"repeat_penalty\\\": {\\n \\\"display_name\\\": \\\"Repeat Penalty\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Penalty for repetitions in generated text. (Default: 1.1)\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"tfs_z\\\": {\\n \\\"display_name\\\": \\\"TFS Z\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Tail free sampling value. (Default: 1)\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"timeout\\\": {\\n \\\"display_name\\\": \\\"Timeout\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"info\\\": \\\"Timeout for the request stream.\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"top_k\\\": {\\n \\\"display_name\\\": \\\"Top K\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"info\\\": \\\"Limits token selection to top K. (Default: 40)\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"top_p\\\": {\\n \\\"display_name\\\": \\\"Top P\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Works together with top-k. (Default: 0.9)\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"verbose\\\": {\\n \\\"display_name\\\": \\\"Verbose\\\",\\n \\\"field_type\\\": \\\"bool\\\",\\n \\\"info\\\": \\\"Whether to print out response text.\\\",\\n },\\n \\\"tags\\\": {\\n \\\"display_name\\\": \\\"Tags\\\",\\n \\\"field_type\\\": \\\"list\\\",\\n \\\"info\\\": \\\"Tags to add to the run trace.\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"stop\\\": {\\n \\\"display_name\\\": \\\"Stop Tokens\\\",\\n \\\"field_type\\\": \\\"list\\\",\\n \\\"info\\\": \\\"List of tokens to signal the model to stop generating text.\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"system\\\": {\\n \\\"display_name\\\": \\\"System\\\",\\n \\\"field_type\\\": \\\"str\\\",\\n \\\"info\\\": \\\"System to use for generating text.\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"template\\\": {\\n \\\"display_name\\\": \\\"Template\\\",\\n \\\"field_type\\\": \\\"str\\\",\\n \\\"info\\\": \\\"Template to use for generating text.\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"inputs\\\": {\\\"display_name\\\": \\\"Input\\\"},\\n }\\n\\n def build(\\n self,\\n base_url: Optional[str],\\n model: str,\\n inputs: str,\\n mirostat: Optional[str],\\n mirostat_eta: Optional[float] = None,\\n mirostat_tau: Optional[float] = None,\\n ### When a callback component is added to Langflow, the comment must be uncommented.###\\n # callback_manager: Optional[CallbackManager] = None,\\n # callbacks: Optional[List[Callbacks]] = None,\\n #######################################################################################\\n repeat_last_n: Optional[int] = None,\\n verbose: Optional[bool] = None,\\n cache: Optional[bool] = None,\\n num_ctx: Optional[int] = None,\\n num_gpu: Optional[int] = None,\\n format: Optional[str] = None,\\n metadata: Optional[Dict[str, Any]] = None,\\n num_thread: Optional[int] = None,\\n repeat_penalty: Optional[float] = None,\\n stop: Optional[List[str]] = None,\\n system: Optional[str] = None,\\n tags: Optional[List[str]] = None,\\n temperature: Optional[float] = None,\\n template: Optional[str] = None,\\n tfs_z: Optional[float] = None,\\n timeout: Optional[int] = None,\\n top_k: Optional[int] = None,\\n top_p: Optional[int] = None,\\n ) -> Text:\\n if not base_url:\\n base_url = \\\"http://localhost:11434\\\"\\n\\n # Mapping mirostat settings to their corresponding values\\n mirostat_options = {\\\"Mirostat\\\": 1, \\\"Mirostat 2.0\\\": 2}\\n\\n # Default to 0 for 'Disabled'\\n mirostat_value = mirostat_options.get(mirostat, 0) # type: ignore\\n\\n # Set mirostat_eta and mirostat_tau to None if mirostat is disabled\\n if mirostat_value == 0:\\n mirostat_eta = None\\n mirostat_tau = None\\n\\n # Mapping system settings to their corresponding values\\n llm_params = {\\n \\\"base_url\\\": base_url,\\n \\\"cache\\\": cache,\\n \\\"model\\\": model,\\n \\\"mirostat\\\": mirostat_value,\\n \\\"format\\\": format,\\n \\\"metadata\\\": metadata,\\n \\\"tags\\\": tags,\\n ## When a callback component is added to Langflow, the comment must be uncommented.##\\n # \\\"callback_manager\\\": callback_manager,\\n # \\\"callbacks\\\": callbacks,\\n #####################################################################################\\n \\\"mirostat_eta\\\": mirostat_eta,\\n \\\"mirostat_tau\\\": mirostat_tau,\\n \\\"num_ctx\\\": num_ctx,\\n \\\"num_gpu\\\": num_gpu,\\n \\\"num_thread\\\": num_thread,\\n \\\"repeat_last_n\\\": repeat_last_n,\\n \\\"repeat_penalty\\\": repeat_penalty,\\n \\\"temperature\\\": temperature,\\n \\\"stop\\\": stop,\\n \\\"system\\\": system,\\n \\\"template\\\": template,\\n \\\"tfs_z\\\": tfs_z,\\n \\\"timeout\\\": timeout,\\n \\\"top_k\\\": top_k,\\n \\\"top_p\\\": top_p,\\n \\\"verbose\\\": verbose,\\n }\\n\\n # None Value remove\\n llm_params = {k: v for k, v in llm_params.items() if v is not None}\\n\\n try:\\n output = ChatOllama(**llm_params) # type: ignore\\n except Exception as e:\\n raise ValueError(\\\"Could not initialize Ollama LLM.\\\") from e\\n message = output.invoke(inputs)\\n result = message.content if hasattr(message, \\\"content\\\") else message\\n self.status = result\\n return result\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"format\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"format\",\"display_name\":\"Format\",\"advanced\":true,\"dynamic\":false,\"info\":\"Specify the format of the output (e.g., json).\",\"title_case\":false,\"input_types\":[\"Text\"]},\"inputs\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"inputs\",\"display_name\":\"Input\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"mirostat\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"Disabled\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"Disabled\",\"Mirostat\",\"Mirostat 2.0\"],\"name\":\"mirostat\",\"display_name\":\"Mirostat\",\"advanced\":true,\"dynamic\":false,\"info\":\"Enable/disable Mirostat sampling for controlling perplexity.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"mirostat_eta\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"mirostat_eta\",\"display_name\":\"Mirostat Eta\",\"advanced\":true,\"dynamic\":false,\"info\":\"Learning rate for Mirostat algorithm. (Default: 0.1)\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"mirostat_tau\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"mirostat_tau\",\"display_name\":\"Mirostat Tau\",\"advanced\":true,\"dynamic\":false,\"info\":\"Controls the balance between coherence and diversity of the output. (Default: 5.0)\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"model\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"llama2\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model\",\"display_name\":\"Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"Refer to https://ollama.ai/library for more models.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"num_ctx\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"num_ctx\",\"display_name\":\"Context Window Size\",\"advanced\":true,\"dynamic\":false,\"info\":\"Size of the context window for generating tokens. (Default: 2048)\",\"title_case\":false},\"num_gpu\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"num_gpu\",\"display_name\":\"Number of GPUs\",\"advanced\":true,\"dynamic\":false,\"info\":\"Number of GPUs to use for computation. (Default: 1 on macOS, 0 to disable)\",\"title_case\":false},\"num_thread\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"num_thread\",\"display_name\":\"Number of Threads\",\"advanced\":true,\"dynamic\":false,\"info\":\"Number of threads to use during computation. (Default: detected for optimal performance)\",\"title_case\":false},\"repeat_last_n\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"repeat_last_n\",\"display_name\":\"Repeat Last N\",\"advanced\":true,\"dynamic\":false,\"info\":\"How far back the model looks to prevent repetition. (Default: 64, 0 = disabled, -1 = num_ctx)\",\"title_case\":false},\"repeat_penalty\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"repeat_penalty\",\"display_name\":\"Repeat Penalty\",\"advanced\":true,\"dynamic\":false,\"info\":\"Penalty for repetitions in generated text. (Default: 1.1)\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"system\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"system\",\"display_name\":\"System\",\"advanced\":true,\"dynamic\":false,\"info\":\"System to use for generating text.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.8,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"Controls the creativity of model responses.\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"template\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"template\",\"display_name\":\"Template\",\"advanced\":true,\"dynamic\":false,\"info\":\"Template to use for generating text.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"tfs_z\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tfs_z\",\"display_name\":\"TFS Z\",\"advanced\":true,\"dynamic\":false,\"info\":\"Tail free sampling value. (Default: 1)\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"timeout\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"timeout\",\"display_name\":\"Timeout\",\"advanced\":true,\"dynamic\":false,\"info\":\"Timeout for the request stream.\",\"title_case\":false},\"top_k\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_k\",\"display_name\":\"Top K\",\"advanced\":true,\"dynamic\":false,\"info\":\"Limits token selection to top K. (Default: 40)\",\"title_case\":false},\"top_p\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_p\",\"display_name\":\"Top P\",\"advanced\":true,\"dynamic\":false,\"info\":\"Works together with top-k. (Default: 0.9)\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"verbose\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"verbose\",\"display_name\":\"Verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"Whether to print out response text.\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Generate text using Local LLM for chat with Ollama.\",\"base_classes\":[\"Text\",\"object\"],\"display_name\":\"ChatOllamaModel\",\"documentation\":\"\",\"custom_fields\":{\"base_url\":null,\"model\":null,\"inputs\":null,\"mirostat\":null,\"mirostat_eta\":null,\"mirostat_tau\":null,\"repeat_last_n\":null,\"verbose\":null,\"cache\":null,\"num_ctx\":null,\"num_gpu\":null,\"format\":null,\"metadata\":null,\"num_thread\":null,\"repeat_penalty\":null,\"stop\":null,\"system\":null,\"tags\":null,\"temperature\":null,\"template\":null,\"tfs_z\":null,\"timeout\":null,\"top_k\":null,\"top_p\":null},\"output_types\":[\"Text\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"AnthropicModel\":{\"template\":{\"anthropic_api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"anthropic_api_key\",\"display_name\":\"Anthropic API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"Your Anthropic API key.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"api_endpoint\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"api_endpoint\",\"display_name\":\"API Endpoint\",\"advanced\":false,\"dynamic\":false,\"info\":\"Endpoint of the Anthropic API. Defaults to 'https://api.anthropic.com' if not specified.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain_community.chat_models.anthropic import ChatAnthropic\\nfrom pydantic.v1 import SecretStr\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Text\\n\\n\\nclass AnthropicLLM(CustomComponent):\\n display_name: str = \\\"AnthropicModel\\\"\\n description: str = \\\"Generate text using Anthropic Chat&Completion large language models.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"model\\\": {\\n \\\"display_name\\\": \\\"Model Name\\\",\\n \\\"options\\\": [\\n \\\"claude-2.1\\\",\\n \\\"claude-2.0\\\",\\n \\\"claude-instant-1.2\\\",\\n \\\"claude-instant-1\\\",\\n # Add more models as needed\\n ],\\n \\\"info\\\": \\\"https://python.langchain.com/docs/integrations/chat/anthropic\\\",\\n \\\"required\\\": True,\\n \\\"value\\\": \\\"claude-2.1\\\",\\n },\\n \\\"anthropic_api_key\\\": {\\n \\\"display_name\\\": \\\"Anthropic API Key\\\",\\n \\\"required\\\": True,\\n \\\"password\\\": True,\\n \\\"info\\\": \\\"Your Anthropic API key.\\\",\\n },\\n \\\"max_tokens\\\": {\\n \\\"display_name\\\": \\\"Max Tokens\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"value\\\": 256,\\n },\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"value\\\": 0.7,\\n },\\n \\\"api_endpoint\\\": {\\n \\\"display_name\\\": \\\"API Endpoint\\\",\\n \\\"info\\\": \\\"Endpoint of the Anthropic API. Defaults to 'https://api.anthropic.com' if not specified.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n \\\"inputs\\\": {\\\"display_name\\\": \\\"Input\\\"},\\n }\\n\\n def build(\\n self,\\n model: str,\\n inputs: str,\\n anthropic_api_key: Optional[str] = None,\\n max_tokens: Optional[int] = None,\\n temperature: Optional[float] = None,\\n api_endpoint: Optional[str] = None,\\n ) -> Text:\\n # Set default API endpoint if not provided\\n if not api_endpoint:\\n api_endpoint = \\\"https://api.anthropic.com\\\"\\n\\n try:\\n output = ChatAnthropic(\\n model_name=model,\\n anthropic_api_key=(SecretStr(anthropic_api_key) if anthropic_api_key else None),\\n max_tokens_to_sample=max_tokens, # type: ignore\\n temperature=temperature,\\n anthropic_api_url=api_endpoint,\\n )\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to Anthropic API.\\\") from e\\n message = output.invoke(inputs)\\n result = message.content if hasattr(message, \\\"content\\\") else message\\n self.status = result\\n return result\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"inputs\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"inputs\",\"display_name\":\"Input\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"max_tokens\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":256,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_tokens\",\"display_name\":\"Max Tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"model\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"claude-2.1\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"claude-2.1\",\"claude-2.0\",\"claude-instant-1.2\",\"claude-instant-1\"],\"name\":\"model\",\"display_name\":\"Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"https://python.langchain.com/docs/integrations/chat/anthropic\",\"title_case\":false,\"input_types\":[\"Text\"]},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.7,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Generate text using Anthropic Chat&Completion large language models.\",\"base_classes\":[\"Text\",\"object\"],\"display_name\":\"AnthropicModel\",\"documentation\":\"\",\"custom_fields\":{\"model\":null,\"inputs\":null,\"anthropic_api_key\":null,\"max_tokens\":null,\"temperature\":null,\"api_endpoint\":null},\"output_types\":[\"Text\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"OpenAIModel\":{\"template\":{\"inputs\":{\"type\":\"Text\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"inputs\",\"display_name\":\"Input\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain_openai import ChatOpenAI\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import NestedDict, Text\\n\\n\\nclass OpenAIModelComponent(CustomComponent):\\n display_name = \\\"OpenAI Model\\\"\\n description = \\\"Generates text using OpenAI's models.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"inputs\\\": {\\\"display_name\\\": \\\"Input\\\"},\\n \\\"max_tokens\\\": {\\n \\\"display_name\\\": \\\"Max Tokens\\\",\\n \\\"advanced\\\": False,\\n \\\"required\\\": False,\\n },\\n \\\"model_kwargs\\\": {\\n \\\"display_name\\\": \\\"Model Kwargs\\\",\\n \\\"advanced\\\": True,\\n \\\"required\\\": False,\\n },\\n \\\"model_name\\\": {\\n \\\"display_name\\\": \\\"Model Name\\\",\\n \\\"advanced\\\": False,\\n \\\"required\\\": False,\\n \\\"options\\\": [\\n \\\"gpt-4-turbo-preview\\\",\\n \\\"gpt-4-0125-preview\\\",\\n \\\"gpt-4-1106-preview\\\",\\n \\\"gpt-4-vision-preview\\\",\\n \\\"gpt-3.5-turbo-0125\\\",\\n \\\"gpt-3.5-turbo-1106\\\",\\n ],\\n },\\n \\\"openai_api_base\\\": {\\n \\\"display_name\\\": \\\"OpenAI API Base\\\",\\n \\\"advanced\\\": False,\\n \\\"required\\\": False,\\n \\\"info\\\": (\\n \\\"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\\\n\\\\n\\\"\\n \\\"You can change this to use other APIs like JinaChat, LocalAI and Prem.\\\"\\n ),\\n },\\n \\\"openai_api_key\\\": {\\n \\\"display_name\\\": \\\"OpenAI API Key\\\",\\n \\\"advanced\\\": False,\\n \\\"required\\\": False,\\n \\\"password\\\": True,\\n },\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"advanced\\\": False,\\n \\\"required\\\": False,\\n \\\"value\\\": 0.7,\\n },\\n }\\n\\n def build(\\n self,\\n inputs: Text,\\n max_tokens: Optional[int] = 256,\\n model_kwargs: NestedDict = {},\\n model_name: str = \\\"gpt-4-1106-preview\\\",\\n openai_api_base: Optional[str] = None,\\n openai_api_key: Optional[str] = None,\\n temperature: float = 0.7,\\n ) -> Text:\\n if not openai_api_base:\\n openai_api_base = \\\"https://api.openai.com/v1\\\"\\n model = ChatOpenAI(\\n max_tokens=max_tokens,\\n model_kwargs=model_kwargs,\\n model=model_name,\\n base_url=openai_api_base,\\n api_key=openai_api_key,\\n temperature=temperature,\\n )\\n\\n message = model.invoke(inputs)\\n result = message.content if hasattr(message, \\\"content\\\") else message\\n self.status = result\\n return result\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"max_tokens\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":256,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_tokens\",\"display_name\":\"Max Tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"model_kwargs\":{\"type\":\"NestedDict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model_kwargs\",\"display_name\":\"Model Kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"model_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"gpt-4-1106-preview\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"gpt-4-turbo-preview\",\"gpt-4-0125-preview\",\"gpt-4-1106-preview\",\"gpt-4-vision-preview\",\"gpt-3.5-turbo-0125\",\"gpt-3.5-turbo-1106\"],\"name\":\"model_name\",\"display_name\":\"Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"openai_api_base\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":false,\"dynamic\":false,\"info\":\"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"openai_api_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.7,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Generates text using OpenAI's models.\",\"base_classes\":[\"Text\",\"object\"],\"display_name\":\"OpenAI Model\",\"documentation\":\"\",\"custom_fields\":{\"inputs\":null,\"max_tokens\":null,\"model_kwargs\":null,\"model_name\":null,\"openai_api_base\":null,\"openai_api_key\":null,\"temperature\":null},\"output_types\":[\"Text\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"HuggingFaceModel\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain_community.chat_models.huggingface import ChatHuggingFace\\nfrom langchain_community.llms.huggingface_endpoint import HuggingFaceEndpoint\\n\\nfrom langflow import CustomComponent\\n\\nfrom langflow.field_typing import Text\\n\\n\\nclass HuggingFaceEndpointsComponent(CustomComponent):\\n display_name: str = \\\"Hugging Face Inference API models\\\"\\n description: str = \\\"Generate text using LLM model from Hugging Face Inference API.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"endpoint_url\\\": {\\\"display_name\\\": \\\"Endpoint URL\\\", \\\"password\\\": True},\\n \\\"task\\\": {\\n \\\"display_name\\\": \\\"Task\\\",\\n \\\"options\\\": [\\\"text2text-generation\\\", \\\"text-generation\\\", \\\"summarization\\\"],\\n },\\n \\\"huggingfacehub_api_token\\\": {\\\"display_name\\\": \\\"API token\\\", \\\"password\\\": True},\\n \\\"model_kwargs\\\": {\\n \\\"display_name\\\": \\\"Model Keyword Arguments\\\",\\n \\\"field_type\\\": \\\"code\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n \\\"inputs\\\": {\\\"display_name\\\": \\\"Input\\\"},\\n }\\n\\n def build(\\n self,\\n inputs: str,\\n endpoint_url: str,\\n task: str = \\\"text2text-generation\\\",\\n huggingfacehub_api_token: Optional[str] = None,\\n model_kwargs: Optional[dict] = None,\\n ) -> Text:\\n try:\\n llm = HuggingFaceEndpoint(\\n endpoint_url=endpoint_url,\\n task=task,\\n huggingfacehub_api_token=huggingfacehub_api_token,\\n model_kwargs=model_kwargs,\\n )\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to HuggingFace Endpoints API.\\\") from e\\n output = ChatHuggingFace(llm=llm)\\n message = output.invoke(inputs)\\n result = message.content if hasattr(message, \\\"content\\\") else message\\n self.status = result\\n return result\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"endpoint_url\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"endpoint_url\",\"display_name\":\"Endpoint URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"huggingfacehub_api_token\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"huggingfacehub_api_token\",\"display_name\":\"API token\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"inputs\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"inputs\",\"display_name\":\"Input\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"model_kwargs\":{\"type\":\"code\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model_kwargs\",\"display_name\":\"Model Keyword Arguments\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"task\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"text2text-generation\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"text2text-generation\",\"text-generation\",\"summarization\"],\"name\":\"task\",\"display_name\":\"Task\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Generate text using LLM model from Hugging Face Inference API.\",\"base_classes\":[\"Text\",\"object\"],\"display_name\":\"Hugging Face Inference API models\",\"documentation\":\"\",\"custom_fields\":{\"inputs\":null,\"endpoint_url\":null,\"task\":null,\"huggingfacehub_api_token\":null,\"model_kwargs\":null},\"output_types\":[\"Text\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"AzureOpenAIModel\":{\"template\":{\"api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"api_key\",\"display_name\":\"API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"api_version\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"2023-12-01-preview\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"2023-03-15-preview\",\"2023-05-15\",\"2023-06-01-preview\",\"2023-07-01-preview\",\"2023-08-01-preview\",\"2023-09-01-preview\",\"2023-12-01-preview\"],\"name\":\"api_version\",\"display_name\":\"API Version\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"azure_deployment\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"azure_deployment\",\"display_name\":\"Deployment Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"azure_endpoint\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"azure_endpoint\",\"display_name\":\"Azure Endpoint\",\"advanced\":false,\"dynamic\":false,\"info\":\"Your Azure endpoint, including the resource.. Example: `https://example-resource.azure.openai.com/`\",\"title_case\":false,\"input_types\":[\"Text\"]},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain.llms.base import BaseLanguageModel\\nfrom langchain_openai import AzureChatOpenAI\\n\\nfrom langflow import CustomComponent\\n\\n\\nclass AzureChatOpenAIComponent(CustomComponent):\\n display_name: str = \\\"AzureOpenAI Model\\\"\\n description: str = \\\"Generate text using LLM model from Azure OpenAI.\\\"\\n documentation: str = \\\"https://python.langchain.com/docs/integrations/llms/azure_openai\\\"\\n beta = False\\n\\n AZURE_OPENAI_MODELS = [\\n \\\"gpt-35-turbo\\\",\\n \\\"gpt-35-turbo-16k\\\",\\n \\\"gpt-35-turbo-instruct\\\",\\n \\\"gpt-4\\\",\\n \\\"gpt-4-32k\\\",\\n \\\"gpt-4-vision\\\",\\n ]\\n\\n AZURE_OPENAI_API_VERSIONS = [\\n \\\"2023-03-15-preview\\\",\\n \\\"2023-05-15\\\",\\n \\\"2023-06-01-preview\\\",\\n \\\"2023-07-01-preview\\\",\\n \\\"2023-08-01-preview\\\",\\n \\\"2023-09-01-preview\\\",\\n \\\"2023-12-01-preview\\\",\\n ]\\n\\n def build_config(self):\\n return {\\n \\\"model\\\": {\\n \\\"display_name\\\": \\\"Model Name\\\",\\n \\\"value\\\": self.AZURE_OPENAI_MODELS[0],\\n \\\"options\\\": self.AZURE_OPENAI_MODELS,\\n \\\"required\\\": True,\\n },\\n \\\"azure_endpoint\\\": {\\n \\\"display_name\\\": \\\"Azure Endpoint\\\",\\n \\\"required\\\": True,\\n \\\"info\\\": \\\"Your Azure endpoint, including the resource.. Example: `https://example-resource.azure.openai.com/`\\\",\\n },\\n \\\"azure_deployment\\\": {\\n \\\"display_name\\\": \\\"Deployment Name\\\",\\n \\\"required\\\": True,\\n },\\n \\\"api_version\\\": {\\n \\\"display_name\\\": \\\"API Version\\\",\\n \\\"options\\\": self.AZURE_OPENAI_API_VERSIONS,\\n \\\"value\\\": self.AZURE_OPENAI_API_VERSIONS[-1],\\n \\\"required\\\": True,\\n \\\"advanced\\\": True,\\n },\\n \\\"api_key\\\": {\\\"display_name\\\": \\\"API Key\\\", \\\"required\\\": True, \\\"password\\\": True},\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"value\\\": 0.7,\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"required\\\": False,\\n },\\n \\\"max_tokens\\\": {\\n \\\"display_name\\\": \\\"Max Tokens\\\",\\n \\\"value\\\": 1000,\\n \\\"required\\\": False,\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"advanced\\\": True,\\n \\\"info\\\": \\\"Maximum number of tokens to generate.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n \\\"inputs\\\": {\\\"display_name\\\": \\\"Input\\\"},\\n }\\n\\n def build(\\n self,\\n model: str,\\n azure_endpoint: str,\\n inputs: str,\\n azure_deployment: str,\\n api_key: str,\\n api_version: str,\\n temperature: float = 0.7,\\n max_tokens: Optional[int] = 1000,\\n ) -> BaseLanguageModel:\\n try:\\n output = AzureChatOpenAI(\\n model=model,\\n azure_endpoint=azure_endpoint,\\n azure_deployment=azure_deployment,\\n api_version=api_version,\\n api_key=api_key,\\n temperature=temperature,\\n max_tokens=max_tokens,\\n )\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to AzureOpenAI API.\\\") from e\\n message = output.invoke(inputs)\\n result = message.content if hasattr(message, \\\"content\\\") else message\\n self.status = result\\n return result\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"inputs\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"inputs\",\"display_name\":\"Input\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"max_tokens\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1000,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_tokens\",\"display_name\":\"Max Tokens\",\"advanced\":true,\"dynamic\":false,\"info\":\"Maximum number of tokens to generate.\",\"title_case\":false},\"model\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"gpt-35-turbo\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"gpt-35-turbo\",\"gpt-35-turbo-16k\",\"gpt-35-turbo-instruct\",\"gpt-4\",\"gpt-4-32k\",\"gpt-4-vision\"],\"name\":\"model\",\"display_name\":\"Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.7,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Generate text using LLM model from Azure OpenAI.\",\"base_classes\":[\"BaseLanguageModel\",\"Runnable\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"object\"],\"display_name\":\"AzureOpenAI Model\",\"documentation\":\"https://python.langchain.com/docs/integrations/llms/azure_openai\",\"custom_fields\":{\"model\":null,\"azure_endpoint\":null,\"inputs\":null,\"azure_deployment\":null,\"api_key\":null,\"api_version\":null,\"temperature\":null,\"max_tokens\":null},\"output_types\":[\"BaseLanguageModel\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"AmazonBedrockModel\":{\"template\":{\"cache\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"cache\",\"display_name\":\"Cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain_community.chat_models.bedrock import BedrockChat\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Text\\n\\n\\nclass AmazonBedrockComponent(CustomComponent):\\n display_name: str = \\\"Amazon Bedrock Model\\\"\\n description: str = \\\"Generate text using LLM model from Amazon Bedrock.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"model_id\\\": {\\n \\\"display_name\\\": \\\"Model Id\\\",\\n \\\"options\\\": [\\n \\\"ai21.j2-grande-instruct\\\",\\n \\\"ai21.j2-jumbo-instruct\\\",\\n \\\"ai21.j2-mid\\\",\\n \\\"ai21.j2-mid-v1\\\",\\n \\\"ai21.j2-ultra\\\",\\n \\\"ai21.j2-ultra-v1\\\",\\n \\\"anthropic.claude-instant-v1\\\",\\n \\\"anthropic.claude-v1\\\",\\n \\\"anthropic.claude-v2\\\",\\n \\\"cohere.command-text-v14\\\",\\n ],\\n },\\n \\\"credentials_profile_name\\\": {\\\"display_name\\\": \\\"Credentials Profile Name\\\"},\\n \\\"streaming\\\": {\\\"display_name\\\": \\\"Streaming\\\", \\\"field_type\\\": \\\"bool\\\"},\\n \\\"endpoint_url\\\": {\\\"display_name\\\": \\\"Endpoint URL\\\"},\\n \\\"region_name\\\": {\\\"display_name\\\": \\\"Region Name\\\"},\\n \\\"model_kwargs\\\": {\\\"display_name\\\": \\\"Model Kwargs\\\"},\\n \\\"cache\\\": {\\\"display_name\\\": \\\"Cache\\\"},\\n \\\"code\\\": {\\\"advanced\\\": True},\\n \\\"inputs\\\": {\\\"display_name\\\": \\\"Input\\\"},\\n }\\n\\n def build(\\n self,\\n inputs: str,\\n model_id: str = \\\"anthropic.claude-instant-v1\\\",\\n credentials_profile_name: Optional[str] = None,\\n region_name: Optional[str] = None,\\n model_kwargs: Optional[dict] = None,\\n endpoint_url: Optional[str] = None,\\n streaming: bool = False,\\n cache: Optional[bool] = None,\\n ) -> Text:\\n try:\\n output = BedrockChat(\\n credentials_profile_name=credentials_profile_name,\\n model_id=model_id,\\n region_name=region_name,\\n model_kwargs=model_kwargs,\\n endpoint_url=endpoint_url,\\n streaming=streaming,\\n cache=cache,\\n ) # type: ignore\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to AmazonBedrock API.\\\") from e\\n message = output.invoke(inputs)\\n result = message.content if hasattr(message, \\\"content\\\") else message\\n self.status = result\\n return result\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"credentials_profile_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"credentials_profile_name\",\"display_name\":\"Credentials Profile Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"endpoint_url\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"endpoint_url\",\"display_name\":\"Endpoint URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"inputs\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"inputs\",\"display_name\":\"Input\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"model_id\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"anthropic.claude-instant-v1\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"ai21.j2-grande-instruct\",\"ai21.j2-jumbo-instruct\",\"ai21.j2-mid\",\"ai21.j2-mid-v1\",\"ai21.j2-ultra\",\"ai21.j2-ultra-v1\",\"anthropic.claude-instant-v1\",\"anthropic.claude-v1\",\"anthropic.claude-v2\",\"cohere.command-text-v14\"],\"name\":\"model_id\",\"display_name\":\"Model Id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"model_kwargs\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model_kwargs\",\"display_name\":\"Model Kwargs\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"region_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"region_name\",\"display_name\":\"Region Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"streaming\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"streaming\",\"display_name\":\"Streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Generate text using LLM model from Amazon Bedrock.\",\"base_classes\":[\"Text\",\"object\"],\"display_name\":\"Amazon Bedrock Model\",\"documentation\":\"\",\"custom_fields\":{\"inputs\":null,\"model_id\":null,\"credentials_profile_name\":null,\"region_name\":null,\"model_kwargs\":null,\"endpoint_url\":null,\"streaming\":null,\"cache\":null},\"output_types\":[\"Text\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"CohereModel\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langchain_community.chat_models.cohere import ChatCohere\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Text\\n\\n\\nclass CohereComponent(CustomComponent):\\n display_name = \\\"CohereModel\\\"\\n description = \\\"Generate text using Cohere large language models.\\\"\\n documentation = \\\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/cohere\\\"\\n\\n def build_config(self):\\n return {\\n \\\"cohere_api_key\\\": {\\n \\\"display_name\\\": \\\"Cohere API Key\\\",\\n \\\"type\\\": \\\"password\\\",\\n \\\"password\\\": True,\\n },\\n \\\"max_tokens\\\": {\\n \\\"display_name\\\": \\\"Max Tokens\\\",\\n \\\"default\\\": 256,\\n \\\"type\\\": \\\"int\\\",\\n \\\"show\\\": True,\\n },\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"default\\\": 0.75,\\n \\\"type\\\": \\\"float\\\",\\n \\\"show\\\": True,\\n },\\n \\\"inputs\\\": {\\\"display_name\\\": \\\"Input\\\"},\\n }\\n\\n def build(\\n self,\\n cohere_api_key: str,\\n inputs: str,\\n max_tokens: int = 256,\\n temperature: float = 0.75,\\n ) -> Text:\\n output = ChatCohere(\\n cohere_api_key=cohere_api_key,\\n max_tokens=max_tokens,\\n temperature=temperature,\\n )\\n message = output.invoke(inputs)\\n result = message.content if hasattr(message, \\\"content\\\") else message\\n self.status = result\\n return result\\n return result\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"cohere_api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"cohere_api_key\",\"display_name\":\"Cohere API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"inputs\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"inputs\",\"display_name\":\"Input\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"max_tokens\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":256,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_tokens\",\"display_name\":\"Max Tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"temperature\":{\"type\":\"float\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.75,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Generate text using Cohere large language models.\",\"base_classes\":[\"Text\",\"object\"],\"display_name\":\"CohereModel\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/cohere\",\"custom_fields\":{\"cohere_api_key\":null,\"inputs\":null,\"max_tokens\":null,\"temperature\":null},\"output_types\":[\"Text\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true}},\"model_specs\":{\"AmazonBedrockSpecs\":{\"template\":{\"cache\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"cache\",\"display_name\":\"Cache\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain.llms.base import BaseLLM\\nfrom langchain_community.llms.bedrock import Bedrock\\n\\n\\nfrom langflow import CustomComponent\\n\\n\\nclass AmazonBedrockComponent(CustomComponent):\\n display_name: str = \\\"Amazon Bedrock\\\"\\n description: str = \\\"LLM model from Amazon Bedrock.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"model_id\\\": {\\n \\\"display_name\\\": \\\"Model Id\\\",\\n \\\"options\\\": [\\n \\\"ai21.j2-grande-instruct\\\",\\n \\\"ai21.j2-jumbo-instruct\\\",\\n \\\"ai21.j2-mid\\\",\\n \\\"ai21.j2-mid-v1\\\",\\n \\\"ai21.j2-ultra\\\",\\n \\\"ai21.j2-ultra-v1\\\",\\n \\\"anthropic.claude-instant-v1\\\",\\n \\\"anthropic.claude-v1\\\",\\n \\\"anthropic.claude-v2\\\",\\n \\\"cohere.command-text-v14\\\",\\n ],\\n },\\n \\\"credentials_profile_name\\\": {\\\"display_name\\\": \\\"Credentials Profile Name\\\"},\\n \\\"streaming\\\": {\\\"display_name\\\": \\\"Streaming\\\", \\\"field_type\\\": \\\"bool\\\"},\\n \\\"endpoint_url\\\": {\\\"display_name\\\": \\\"Endpoint URL\\\"},\\n \\\"region_name\\\": {\\\"display_name\\\": \\\"Region Name\\\"},\\n \\\"model_kwargs\\\": {\\\"display_name\\\": \\\"Model Kwargs\\\"},\\n \\\"cache\\\": {\\\"display_name\\\": \\\"Cache\\\"},\\n \\\"code\\\": {\\\"advanced\\\": True},\\n }\\n\\n def build(\\n self,\\n model_id: str = \\\"anthropic.claude-instant-v1\\\",\\n credentials_profile_name: Optional[str] = None,\\n region_name: Optional[str] = None,\\n model_kwargs: Optional[dict] = None,\\n endpoint_url: Optional[str] = None,\\n streaming: bool = False,\\n cache: Optional[bool] = None,\\n ) -> BaseLLM:\\n try:\\n output = Bedrock(\\n credentials_profile_name=credentials_profile_name,\\n model_id=model_id,\\n region_name=region_name,\\n model_kwargs=model_kwargs,\\n endpoint_url=endpoint_url,\\n streaming=streaming,\\n cache=cache,\\n ) # type: ignore\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to AmazonBedrock API.\\\") from e\\n return output\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"credentials_profile_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"credentials_profile_name\",\"display_name\":\"Credentials Profile Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"endpoint_url\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"endpoint_url\",\"display_name\":\"Endpoint URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"model_id\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"anthropic.claude-instant-v1\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"ai21.j2-grande-instruct\",\"ai21.j2-jumbo-instruct\",\"ai21.j2-mid\",\"ai21.j2-mid-v1\",\"ai21.j2-ultra\",\"ai21.j2-ultra-v1\",\"anthropic.claude-instant-v1\",\"anthropic.claude-v1\",\"anthropic.claude-v2\",\"cohere.command-text-v14\"],\"name\":\"model_id\",\"display_name\":\"Model Id\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"model_kwargs\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model_kwargs\",\"display_name\":\"Model Kwargs\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"region_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"region_name\",\"display_name\":\"Region Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"streaming\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"streaming\",\"display_name\":\"Streaming\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"LLM model from Amazon Bedrock.\",\"base_classes\":[\"BaseLanguageModel\",\"Runnable\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"object\",\"BaseLLM\"],\"display_name\":\"Amazon Bedrock\",\"documentation\":\"\",\"custom_fields\":{\"model_id\":null,\"credentials_profile_name\":null,\"region_name\":null,\"model_kwargs\":null,\"endpoint_url\":null,\"streaming\":null,\"cache\":null},\"output_types\":[\"BaseLLM\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"ChatVertexAISpecs\":{\"template\":{\"credentials\":{\"type\":\"file\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[\".json\"],\"password\":false,\"name\":\"credentials\",\"display_name\":\"Credentials\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"examples\":{\"type\":\"BaseMessage\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":true,\"value\":[],\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"examples\",\"display_name\":\"Examples\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import List, Optional, Union\\n\\nfrom langchain.llms import BaseLLM\\nfrom langchain_community.chat_models.vertexai import ChatVertexAI\\nfrom langchain_core.messages.base import BaseMessage\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import BaseLanguageModel\\n\\n\\nclass ChatVertexAIComponent(CustomComponent):\\n display_name = \\\"ChatVertexAI\\\"\\n description = \\\"`Vertex AI` Chat large language models API.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"credentials\\\": {\\n \\\"display_name\\\": \\\"Credentials\\\",\\n \\\"field_type\\\": \\\"file\\\",\\n \\\"file_types\\\": [\\\".json\\\"],\\n \\\"file_path\\\": None,\\n },\\n \\\"examples\\\": {\\n \\\"display_name\\\": \\\"Examples\\\",\\n \\\"multiline\\\": True,\\n },\\n \\\"location\\\": {\\n \\\"display_name\\\": \\\"Location\\\",\\n \\\"value\\\": \\\"us-central1\\\",\\n },\\n \\\"max_output_tokens\\\": {\\n \\\"display_name\\\": \\\"Max Output Tokens\\\",\\n \\\"value\\\": 128,\\n \\\"advanced\\\": True,\\n },\\n \\\"model_name\\\": {\\n \\\"display_name\\\": \\\"Model Name\\\",\\n \\\"value\\\": \\\"chat-bison\\\",\\n },\\n \\\"project\\\": {\\n \\\"display_name\\\": \\\"Project\\\",\\n },\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"value\\\": 0.0,\\n },\\n \\\"top_k\\\": {\\n \\\"display_name\\\": \\\"Top K\\\",\\n \\\"value\\\": 40,\\n \\\"advanced\\\": True,\\n },\\n \\\"top_p\\\": {\\n \\\"display_name\\\": \\\"Top P\\\",\\n \\\"value\\\": 0.95,\\n \\\"advanced\\\": True,\\n },\\n \\\"verbose\\\": {\\n \\\"display_name\\\": \\\"Verbose\\\",\\n \\\"value\\\": False,\\n \\\"advanced\\\": True,\\n },\\n }\\n\\n def build(\\n self,\\n credentials: Optional[str],\\n project: str,\\n examples: Optional[List[BaseMessage]] = [],\\n location: str = \\\"us-central1\\\",\\n max_output_tokens: int = 128,\\n model_name: str = \\\"chat-bison\\\",\\n temperature: float = 0.0,\\n top_k: int = 40,\\n top_p: float = 0.95,\\n verbose: bool = False,\\n ) -> Union[BaseLanguageModel, BaseLLM]:\\n return ChatVertexAI(\\n credentials=credentials,\\n examples=examples,\\n location=location,\\n max_output_tokens=max_output_tokens,\\n model_name=model_name,\\n project=project,\\n temperature=temperature,\\n top_k=top_k,\\n top_p=top_p,\\n verbose=verbose,\\n )\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"location\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"us-central1\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"location\",\"display_name\":\"Location\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"max_output_tokens\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":128,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_output_tokens\",\"display_name\":\"Max Output Tokens\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"model_name\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"chat-bison\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model_name\",\"display_name\":\"Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"project\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"project\",\"display_name\":\"Project\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"temperature\":{\"type\":\"float\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.0,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"top_k\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":40,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_k\",\"display_name\":\"Top K\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"top_p\":{\"type\":\"float\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.95,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_p\",\"display_name\":\"Top P\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"verbose\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"verbose\",\"display_name\":\"Verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"`Vertex AI` Chat large language models API.\",\"base_classes\":[\"BaseLanguageModel\",\"Runnable\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"object\",\"BaseLLM\"],\"display_name\":\"ChatVertexAI\",\"documentation\":\"\",\"custom_fields\":{\"credentials\":null,\"project\":null,\"examples\":null,\"location\":null,\"max_output_tokens\":null,\"model_name\":null,\"temperature\":null,\"top_k\":null,\"top_p\":null,\"verbose\":null},\"output_types\":[\"BaseLanguageModel\",\"BaseLLM\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"VertexAISpecs\":{\"template\":{\"credentials\":{\"type\":\"file\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[\".json\"],\"file_path\":\"\",\"password\":false,\"name\":\"credentials\",\"display_name\":\"Credentials\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langflow import CustomComponent\\nfrom langchain.llms import BaseLLM\\nfrom typing import Optional, Union, Callable, Dict\\nfrom langchain_community.llms.vertexai import VertexAI\\n\\n\\nclass VertexAIComponent(CustomComponent):\\n display_name = \\\"VertexAI\\\"\\n description = \\\"Google Vertex AI large language models\\\"\\n\\n def build_config(self):\\n return {\\n \\\"credentials\\\": {\\n \\\"display_name\\\": \\\"Credentials\\\",\\n \\\"field_type\\\": \\\"file\\\",\\n \\\"file_types\\\": [\\\".json\\\"],\\n \\\"required\\\": False,\\n \\\"value\\\": None,\\n },\\n \\\"location\\\": {\\n \\\"display_name\\\": \\\"Location\\\",\\n \\\"type\\\": \\\"str\\\",\\n \\\"advanced\\\": True,\\n \\\"value\\\": \\\"us-central1\\\",\\n \\\"required\\\": False,\\n },\\n \\\"max_output_tokens\\\": {\\n \\\"display_name\\\": \\\"Max Output Tokens\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"value\\\": 128,\\n \\\"required\\\": False,\\n \\\"advanced\\\": True,\\n },\\n \\\"max_retries\\\": {\\n \\\"display_name\\\": \\\"Max Retries\\\",\\n \\\"type\\\": \\\"int\\\",\\n \\\"value\\\": 6,\\n \\\"required\\\": False,\\n \\\"advanced\\\": True,\\n },\\n \\\"metadata\\\": {\\n \\\"display_name\\\": \\\"Metadata\\\",\\n \\\"field_type\\\": \\\"dict\\\",\\n \\\"required\\\": False,\\n \\\"default\\\": {},\\n },\\n \\\"model_name\\\": {\\n \\\"display_name\\\": \\\"Model Name\\\",\\n \\\"type\\\": \\\"str\\\",\\n \\\"value\\\": \\\"text-bison\\\",\\n \\\"required\\\": False,\\n },\\n \\\"n\\\": {\\n \\\"advanced\\\": True,\\n \\\"display_name\\\": \\\"N\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"value\\\": 1,\\n \\\"required\\\": False,\\n },\\n \\\"project\\\": {\\n \\\"display_name\\\": \\\"Project\\\",\\n \\\"type\\\": \\\"str\\\",\\n \\\"required\\\": False,\\n \\\"default\\\": None,\\n },\\n \\\"request_parallelism\\\": {\\n \\\"display_name\\\": \\\"Request Parallelism\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"value\\\": 5,\\n \\\"required\\\": False,\\n \\\"advanced\\\": True,\\n },\\n \\\"streaming\\\": {\\n \\\"display_name\\\": \\\"Streaming\\\",\\n \\\"field_type\\\": \\\"bool\\\",\\n \\\"value\\\": False,\\n \\\"required\\\": False,\\n \\\"advanced\\\": True,\\n },\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"value\\\": 0.0,\\n \\\"required\\\": False,\\n \\\"advanced\\\": True,\\n },\\n \\\"top_k\\\": {\\\"display_name\\\": \\\"Top K\\\", \\\"type\\\": \\\"int\\\", \\\"default\\\": 40, \\\"required\\\": False, \\\"advanced\\\": True},\\n \\\"top_p\\\": {\\n \\\"display_name\\\": \\\"Top P\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"value\\\": 0.95,\\n \\\"required\\\": False,\\n \\\"advanced\\\": True,\\n },\\n \\\"tuned_model_name\\\": {\\n \\\"display_name\\\": \\\"Tuned Model Name\\\",\\n \\\"type\\\": \\\"str\\\",\\n \\\"required\\\": False,\\n \\\"value\\\": None,\\n \\\"advanced\\\": True,\\n },\\n \\\"verbose\\\": {\\n \\\"display_name\\\": \\\"Verbose\\\",\\n \\\"field_type\\\": \\\"bool\\\",\\n \\\"value\\\": False,\\n \\\"required\\\": False,\\n },\\n \\\"name\\\": {\\\"display_name\\\": \\\"Name\\\", \\\"field_type\\\": \\\"str\\\"},\\n }\\n\\n def build(\\n self,\\n credentials: Optional[str] = None,\\n location: str = \\\"us-central1\\\",\\n max_output_tokens: int = 128,\\n max_retries: int = 6,\\n metadata: Dict = {},\\n model_name: str = \\\"text-bison\\\",\\n n: int = 1,\\n name: Optional[str] = None,\\n project: Optional[str] = None,\\n request_parallelism: int = 5,\\n streaming: bool = False,\\n temperature: float = 0.0,\\n top_k: int = 40,\\n top_p: float = 0.95,\\n tuned_model_name: Optional[str] = None,\\n verbose: bool = False,\\n ) -> Union[BaseLLM, Callable]:\\n return VertexAI(\\n credentials=credentials,\\n location=location,\\n max_output_tokens=max_output_tokens,\\n max_retries=max_retries,\\n metadata=metadata,\\n model_name=model_name,\\n n=n,\\n name=name,\\n project=project,\\n request_parallelism=request_parallelism,\\n streaming=streaming,\\n temperature=temperature,\\n top_k=top_k,\\n top_p=top_p,\\n tuned_model_name=tuned_model_name,\\n verbose=verbose,\\n )\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"location\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"us-central1\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"location\",\"display_name\":\"Location\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"max_output_tokens\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":128,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_output_tokens\",\"display_name\":\"Max Output Tokens\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"max_retries\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":6,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_retries\",\"display_name\":\"Max Retries\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"metadata\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"model_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"text-bison\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model_name\",\"display_name\":\"Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"n\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"n\",\"display_name\":\"N\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"name\",\"display_name\":\"Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"project\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"project\",\"display_name\":\"Project\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"request_parallelism\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":5,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"request_parallelism\",\"display_name\":\"Request Parallelism\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"streaming\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"streaming\",\"display_name\":\"Streaming\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.0,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"top_k\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":40,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_k\",\"display_name\":\"Top K\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"top_p\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.95,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_p\",\"display_name\":\"Top P\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"tuned_model_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tuned_model_name\",\"display_name\":\"Tuned Model Name\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"verbose\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"verbose\",\"display_name\":\"Verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Google Vertex AI large language models\",\"base_classes\":[\"BaseLanguageModel\",\"Runnable\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"object\",\"BaseLLM\",\"Callable\"],\"display_name\":\"VertexAI\",\"documentation\":\"\",\"custom_fields\":{\"credentials\":null,\"location\":null,\"max_output_tokens\":null,\"max_retries\":null,\"metadata\":null,\"model_name\":null,\"n\":null,\"name\":null,\"project\":null,\"request_parallelism\":null,\"streaming\":null,\"temperature\":null,\"top_k\":null,\"top_p\":null,\"tuned_model_name\":null,\"verbose\":null},\"output_types\":[\"BaseLLM\",\"Callable\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"ChatAnthropicSpecs\":{\"template\":{\"anthropic_api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"anthropic_api_key\",\"display_name\":\"Anthropic API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"anthropic_api_url\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"anthropic_api_url\",\"display_name\":\"Anthropic API URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from pydantic.v1.types import SecretStr\\nfrom langflow import CustomComponent\\nfrom typing import Optional, Union, Callable\\nfrom langflow.field_typing import BaseLanguageModel\\nfrom langchain_community.chat_models.anthropic import ChatAnthropic\\n\\n\\nclass ChatAnthropicComponent(CustomComponent):\\n display_name = \\\"ChatAnthropic\\\"\\n description = \\\"`Anthropic` chat large language models.\\\"\\n documentation = \\\"https://python.langchain.com/docs/modules/model_io/models/chat/integrations/anthropic\\\"\\n\\n def build_config(self):\\n return {\\n \\\"anthropic_api_key\\\": {\\n \\\"display_name\\\": \\\"Anthropic API Key\\\",\\n \\\"field_type\\\": \\\"str\\\",\\n \\\"password\\\": True,\\n },\\n \\\"anthropic_api_url\\\": {\\n \\\"display_name\\\": \\\"Anthropic API URL\\\",\\n \\\"field_type\\\": \\\"str\\\",\\n },\\n \\\"model_kwargs\\\": {\\n \\\"display_name\\\": \\\"Model Kwargs\\\",\\n \\\"field_type\\\": \\\"dict\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n },\\n }\\n\\n def build(\\n self,\\n anthropic_api_key: str,\\n anthropic_api_url: Optional[str] = None,\\n model_kwargs: dict = {},\\n temperature: Optional[float] = None,\\n ) -> Union[BaseLanguageModel, Callable]:\\n return ChatAnthropic(\\n anthropic_api_key=SecretStr(anthropic_api_key),\\n anthropic_api_url=anthropic_api_url,\\n model_kwargs=model_kwargs,\\n temperature=temperature,\\n )\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"model_kwargs\":{\"type\":\"dict\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model_kwargs\",\"display_name\":\"Model Kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"`Anthropic` chat large language models.\",\"base_classes\":[\"BaseLanguageModel\",\"Runnable\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"object\",\"Callable\"],\"display_name\":\"ChatAnthropic\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/chat/integrations/anthropic\",\"custom_fields\":{\"anthropic_api_key\":null,\"anthropic_api_url\":null,\"model_kwargs\":null,\"temperature\":null},\"output_types\":[\"BaseLanguageModel\",\"Callable\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"AzureChatOpenAISpecs\":{\"template\":{\"api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"api_key\",\"display_name\":\"API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"api_version\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"2023-12-01-preview\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"2023-03-15-preview\",\"2023-05-15\",\"2023-06-01-preview\",\"2023-07-01-preview\",\"2023-08-01-preview\",\"2023-09-01-preview\",\"2023-12-01-preview\"],\"name\":\"api_version\",\"display_name\":\"API Version\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"azure_deployment\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"azure_deployment\",\"display_name\":\"Deployment Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"azure_endpoint\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"azure_endpoint\",\"display_name\":\"Azure Endpoint\",\"advanced\":false,\"dynamic\":false,\"info\":\"Your Azure endpoint, including the resource.. Example: `https://example-resource.azure.openai.com/`\",\"title_case\":false,\"input_types\":[\"Text\"]},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain.llms.base import BaseLanguageModel\\nfrom langchain_community.chat_models.azure_openai import AzureChatOpenAI\\n\\nfrom langflow import CustomComponent\\n\\n\\nclass AzureChatOpenAISpecsComponent(CustomComponent):\\n display_name: str = \\\"AzureChatOpenAI\\\"\\n description: str = \\\"LLM model from Azure OpenAI.\\\"\\n documentation: str = \\\"https://python.langchain.com/docs/integrations/llms/azure_openai\\\"\\n beta = False\\n\\n AZURE_OPENAI_MODELS = [\\n \\\"gpt-35-turbo\\\",\\n \\\"gpt-35-turbo-16k\\\",\\n \\\"gpt-35-turbo-instruct\\\",\\n \\\"gpt-4\\\",\\n \\\"gpt-4-32k\\\",\\n \\\"gpt-4-vision\\\",\\n ]\\n\\n AZURE_OPENAI_API_VERSIONS = [\\n \\\"2023-03-15-preview\\\",\\n \\\"2023-05-15\\\",\\n \\\"2023-06-01-preview\\\",\\n \\\"2023-07-01-preview\\\",\\n \\\"2023-08-01-preview\\\",\\n \\\"2023-09-01-preview\\\",\\n \\\"2023-12-01-preview\\\",\\n ]\\n\\n def build_config(self):\\n return {\\n \\\"model\\\": {\\n \\\"display_name\\\": \\\"Model Name\\\",\\n \\\"value\\\": self.AZURE_OPENAI_MODELS[0],\\n \\\"options\\\": self.AZURE_OPENAI_MODELS,\\n \\\"required\\\": True,\\n },\\n \\\"azure_endpoint\\\": {\\n \\\"display_name\\\": \\\"Azure Endpoint\\\",\\n \\\"required\\\": True,\\n \\\"info\\\": \\\"Your Azure endpoint, including the resource.. Example: `https://example-resource.azure.openai.com/`\\\",\\n },\\n \\\"azure_deployment\\\": {\\n \\\"display_name\\\": \\\"Deployment Name\\\",\\n \\\"required\\\": True,\\n },\\n \\\"api_version\\\": {\\n \\\"display_name\\\": \\\"API Version\\\",\\n \\\"options\\\": self.AZURE_OPENAI_API_VERSIONS,\\n \\\"value\\\": self.AZURE_OPENAI_API_VERSIONS[-1],\\n \\\"required\\\": True,\\n \\\"advanced\\\": True,\\n },\\n \\\"api_key\\\": {\\\"display_name\\\": \\\"API Key\\\", \\\"required\\\": True, \\\"password\\\": True},\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"value\\\": 0.7,\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"required\\\": False,\\n },\\n \\\"max_tokens\\\": {\\n \\\"display_name\\\": \\\"Max Tokens\\\",\\n \\\"value\\\": 1000,\\n \\\"required\\\": False,\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"advanced\\\": True,\\n \\\"info\\\": \\\"Maximum number of tokens to generate.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n model: str,\\n azure_endpoint: str,\\n azure_deployment: str,\\n api_key: str,\\n api_version: str,\\n temperature: float = 0.7,\\n max_tokens: Optional[int] = 1000,\\n ) -> BaseLanguageModel:\\n try:\\n llm = AzureChatOpenAI(\\n model=model,\\n azure_endpoint=azure_endpoint,\\n azure_deployment=azure_deployment,\\n api_version=api_version,\\n api_key=api_key,\\n temperature=temperature,\\n max_tokens=max_tokens,\\n )\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to AzureOpenAI API.\\\") from e\\n return llm\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"max_tokens\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1000,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_tokens\",\"display_name\":\"Max Tokens\",\"advanced\":true,\"dynamic\":false,\"info\":\"Maximum number of tokens to generate.\",\"title_case\":false},\"model\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"gpt-35-turbo\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"gpt-35-turbo\",\"gpt-35-turbo-16k\",\"gpt-35-turbo-instruct\",\"gpt-4\",\"gpt-4-32k\",\"gpt-4-vision\"],\"name\":\"model\",\"display_name\":\"Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.7,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"LLM model from Azure OpenAI.\",\"base_classes\":[\"BaseLanguageModel\",\"Runnable\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"object\"],\"display_name\":\"AzureChatOpenAI\",\"documentation\":\"https://python.langchain.com/docs/integrations/llms/azure_openai\",\"custom_fields\":{\"model\":null,\"azure_endpoint\":null,\"azure_deployment\":null,\"api_key\":null,\"api_version\":null,\"temperature\":null,\"max_tokens\":null},\"output_types\":[\"BaseLanguageModel\"],\"field_formatters\":{},\"pinned\":false,\"beta\":false},\"ChatOllamaEndpointSpecs\":{\"template\":{\"metadata\":{\"type\":\"Dict[str, Any]\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":true,\"dynamic\":false,\"info\":\"Metadata to add to the run trace.\",\"title_case\":false},\"stop\":{\"type\":\"list\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"stop\",\"display_name\":\"Stop Tokens\",\"advanced\":true,\"dynamic\":false,\"info\":\"List of tokens to signal the model to stop generating text.\",\"title_case\":false},\"tags\":{\"type\":\"list\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"display_name\":\"Tags\",\"advanced\":true,\"dynamic\":false,\"info\":\"Tags to add to the run trace.\",\"title_case\":false},\"base_url\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"base_url\",\"display_name\":\"Base URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"Endpoint of the Ollama API. Defaults to 'http://localhost:11434' if not specified.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"cache\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"cache\",\"display_name\":\"Cache\",\"advanced\":true,\"dynamic\":false,\"info\":\"Enable or disable caching.\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Any, Dict, List, Optional\\n\\n# from langchain_community.chat_models import ChatOllama\\nfrom langchain_community.chat_models import ChatOllama\\nfrom langchain_core.language_models.chat_models import BaseChatModel\\n\\n# from langchain.chat_models import ChatOllama\\nfrom langflow import CustomComponent\\n\\n# whe When a callback component is added to Langflow, the comment must be uncommented.\\n# from langchain.callbacks.manager import CallbackManager\\n\\n\\nclass ChatOllamaComponent(CustomComponent):\\n display_name = \\\"ChatOllama\\\"\\n description = \\\"Local LLM for chat with Ollama.\\\"\\n\\n def build_config(self) -> dict:\\n return {\\n \\\"base_url\\\": {\\n \\\"display_name\\\": \\\"Base URL\\\",\\n \\\"info\\\": \\\"Endpoint of the Ollama API. Defaults to 'http://localhost:11434' if not specified.\\\",\\n },\\n \\\"model\\\": {\\n \\\"display_name\\\": \\\"Model Name\\\",\\n \\\"value\\\": \\\"llama2\\\",\\n \\\"info\\\": \\\"Refer to https://ollama.ai/library for more models.\\\",\\n },\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"value\\\": 0.8,\\n \\\"info\\\": \\\"Controls the creativity of model responses.\\\",\\n },\\n \\\"cache\\\": {\\n \\\"display_name\\\": \\\"Cache\\\",\\n \\\"field_type\\\": \\\"bool\\\",\\n \\\"info\\\": \\\"Enable or disable caching.\\\",\\n \\\"advanced\\\": True,\\n \\\"value\\\": False,\\n },\\n ### When a callback component is added to Langflow, the comment must be uncommented. ###\\n # \\\"callback_manager\\\": {\\n # \\\"display_name\\\": \\\"Callback Manager\\\",\\n # \\\"info\\\": \\\"Optional callback manager for additional functionality.\\\",\\n # \\\"advanced\\\": True,\\n # },\\n # \\\"callbacks\\\": {\\n # \\\"display_name\\\": \\\"Callbacks\\\",\\n # \\\"info\\\": \\\"Callbacks to execute during model runtime.\\\",\\n # \\\"advanced\\\": True,\\n # },\\n ########################################################################################\\n \\\"format\\\": {\\n \\\"display_name\\\": \\\"Format\\\",\\n \\\"field_type\\\": \\\"str\\\",\\n \\\"info\\\": \\\"Specify the format of the output (e.g., json).\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"metadata\\\": {\\n \\\"display_name\\\": \\\"Metadata\\\",\\n \\\"info\\\": \\\"Metadata to add to the run trace.\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"mirostat\\\": {\\n \\\"display_name\\\": \\\"Mirostat\\\",\\n \\\"options\\\": [\\\"Disabled\\\", \\\"Mirostat\\\", \\\"Mirostat 2.0\\\"],\\n \\\"info\\\": \\\"Enable/disable Mirostat sampling for controlling perplexity.\\\",\\n \\\"value\\\": \\\"Disabled\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"mirostat_eta\\\": {\\n \\\"display_name\\\": \\\"Mirostat Eta\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Learning rate for Mirostat algorithm. (Default: 0.1)\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"mirostat_tau\\\": {\\n \\\"display_name\\\": \\\"Mirostat Tau\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Controls the balance between coherence and diversity of the output. (Default: 5.0)\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"num_ctx\\\": {\\n \\\"display_name\\\": \\\"Context Window Size\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"info\\\": \\\"Size of the context window for generating tokens. (Default: 2048)\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"num_gpu\\\": {\\n \\\"display_name\\\": \\\"Number of GPUs\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"info\\\": \\\"Number of GPUs to use for computation. (Default: 1 on macOS, 0 to disable)\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"num_thread\\\": {\\n \\\"display_name\\\": \\\"Number of Threads\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"info\\\": \\\"Number of threads to use during computation. (Default: detected for optimal performance)\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"repeat_last_n\\\": {\\n \\\"display_name\\\": \\\"Repeat Last N\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"info\\\": \\\"How far back the model looks to prevent repetition. (Default: 64, 0 = disabled, -1 = num_ctx)\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"repeat_penalty\\\": {\\n \\\"display_name\\\": \\\"Repeat Penalty\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Penalty for repetitions in generated text. (Default: 1.1)\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"tfs_z\\\": {\\n \\\"display_name\\\": \\\"TFS Z\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Tail free sampling value. (Default: 1)\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"timeout\\\": {\\n \\\"display_name\\\": \\\"Timeout\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"info\\\": \\\"Timeout for the request stream.\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"top_k\\\": {\\n \\\"display_name\\\": \\\"Top K\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"info\\\": \\\"Limits token selection to top K. (Default: 40)\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"top_p\\\": {\\n \\\"display_name\\\": \\\"Top P\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Works together with top-k. (Default: 0.9)\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"verbose\\\": {\\n \\\"display_name\\\": \\\"Verbose\\\",\\n \\\"field_type\\\": \\\"bool\\\",\\n \\\"info\\\": \\\"Whether to print out response text.\\\",\\n },\\n \\\"tags\\\": {\\n \\\"display_name\\\": \\\"Tags\\\",\\n \\\"field_type\\\": \\\"list\\\",\\n \\\"info\\\": \\\"Tags to add to the run trace.\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"stop\\\": {\\n \\\"display_name\\\": \\\"Stop Tokens\\\",\\n \\\"field_type\\\": \\\"list\\\",\\n \\\"info\\\": \\\"List of tokens to signal the model to stop generating text.\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"system\\\": {\\n \\\"display_name\\\": \\\"System\\\",\\n \\\"field_type\\\": \\\"str\\\",\\n \\\"info\\\": \\\"System to use for generating text.\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"template\\\": {\\n \\\"display_name\\\": \\\"Template\\\",\\n \\\"field_type\\\": \\\"str\\\",\\n \\\"info\\\": \\\"Template to use for generating text.\\\",\\n \\\"advanced\\\": True,\\n },\\n }\\n\\n def build(\\n self,\\n base_url: Optional[str],\\n model: str,\\n mirostat: Optional[str],\\n mirostat_eta: Optional[float] = None,\\n mirostat_tau: Optional[float] = None,\\n ### When a callback component is added to Langflow, the comment must be uncommented.###\\n # callback_manager: Optional[CallbackManager] = None,\\n # callbacks: Optional[List[Callbacks]] = None,\\n #######################################################################################\\n repeat_last_n: Optional[int] = None,\\n verbose: Optional[bool] = None,\\n cache: Optional[bool] = None,\\n num_ctx: Optional[int] = None,\\n num_gpu: Optional[int] = None,\\n format: Optional[str] = None,\\n metadata: Optional[Dict[str, Any]] = None,\\n num_thread: Optional[int] = None,\\n repeat_penalty: Optional[float] = None,\\n stop: Optional[List[str]] = None,\\n system: Optional[str] = None,\\n tags: Optional[List[str]] = None,\\n temperature: Optional[float] = None,\\n template: Optional[str] = None,\\n tfs_z: Optional[float] = None,\\n timeout: Optional[int] = None,\\n top_k: Optional[int] = None,\\n top_p: Optional[int] = None,\\n ) -> BaseChatModel:\\n if not base_url:\\n base_url = \\\"http://localhost:11434\\\"\\n\\n # Mapping mirostat settings to their corresponding values\\n mirostat_options = {\\\"Mirostat\\\": 1, \\\"Mirostat 2.0\\\": 2}\\n\\n # Default to 0 for 'Disabled'\\n mirostat_value = mirostat_options.get(mirostat, 0) # type: ignore\\n\\n # Set mirostat_eta and mirostat_tau to None if mirostat is disabled\\n if mirostat_value == 0:\\n mirostat_eta = None\\n mirostat_tau = None\\n\\n # Mapping system settings to their corresponding values\\n llm_params = {\\n \\\"base_url\\\": base_url,\\n \\\"cache\\\": cache,\\n \\\"model\\\": model,\\n \\\"mirostat\\\": mirostat_value,\\n \\\"format\\\": format,\\n \\\"metadata\\\": metadata,\\n \\\"tags\\\": tags,\\n ## When a callback component is added to Langflow, the comment must be uncommented.##\\n # \\\"callback_manager\\\": callback_manager,\\n # \\\"callbacks\\\": callbacks,\\n #####################################################################################\\n \\\"mirostat_eta\\\": mirostat_eta,\\n \\\"mirostat_tau\\\": mirostat_tau,\\n \\\"num_ctx\\\": num_ctx,\\n \\\"num_gpu\\\": num_gpu,\\n \\\"num_thread\\\": num_thread,\\n \\\"repeat_last_n\\\": repeat_last_n,\\n \\\"repeat_penalty\\\": repeat_penalty,\\n \\\"temperature\\\": temperature,\\n \\\"stop\\\": stop,\\n \\\"system\\\": system,\\n \\\"template\\\": template,\\n \\\"tfs_z\\\": tfs_z,\\n \\\"timeout\\\": timeout,\\n \\\"top_k\\\": top_k,\\n \\\"top_p\\\": top_p,\\n \\\"verbose\\\": verbose,\\n }\\n\\n # None Value remove\\n llm_params = {k: v for k, v in llm_params.items() if v is not None}\\n\\n try:\\n output = ChatOllama(**llm_params) # type: ignore\\n except Exception as e:\\n raise ValueError(\\\"Could not initialize Ollama LLM.\\\") from e\\n\\n return output # type: ignore\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"format\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"format\",\"display_name\":\"Format\",\"advanced\":true,\"dynamic\":false,\"info\":\"Specify the format of the output (e.g., json).\",\"title_case\":false,\"input_types\":[\"Text\"]},\"mirostat\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"Disabled\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"Disabled\",\"Mirostat\",\"Mirostat 2.0\"],\"name\":\"mirostat\",\"display_name\":\"Mirostat\",\"advanced\":true,\"dynamic\":false,\"info\":\"Enable/disable Mirostat sampling for controlling perplexity.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"mirostat_eta\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"mirostat_eta\",\"display_name\":\"Mirostat Eta\",\"advanced\":true,\"dynamic\":false,\"info\":\"Learning rate for Mirostat algorithm. (Default: 0.1)\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"mirostat_tau\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"mirostat_tau\",\"display_name\":\"Mirostat Tau\",\"advanced\":true,\"dynamic\":false,\"info\":\"Controls the balance between coherence and diversity of the output. (Default: 5.0)\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"model\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"llama2\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model\",\"display_name\":\"Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"Refer to https://ollama.ai/library for more models.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"num_ctx\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"num_ctx\",\"display_name\":\"Context Window Size\",\"advanced\":true,\"dynamic\":false,\"info\":\"Size of the context window for generating tokens. (Default: 2048)\",\"title_case\":false},\"num_gpu\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"num_gpu\",\"display_name\":\"Number of GPUs\",\"advanced\":true,\"dynamic\":false,\"info\":\"Number of GPUs to use for computation. (Default: 1 on macOS, 0 to disable)\",\"title_case\":false},\"num_thread\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"num_thread\",\"display_name\":\"Number of Threads\",\"advanced\":true,\"dynamic\":false,\"info\":\"Number of threads to use during computation. (Default: detected for optimal performance)\",\"title_case\":false},\"repeat_last_n\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"repeat_last_n\",\"display_name\":\"Repeat Last N\",\"advanced\":true,\"dynamic\":false,\"info\":\"How far back the model looks to prevent repetition. (Default: 64, 0 = disabled, -1 = num_ctx)\",\"title_case\":false},\"repeat_penalty\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"repeat_penalty\",\"display_name\":\"Repeat Penalty\",\"advanced\":true,\"dynamic\":false,\"info\":\"Penalty for repetitions in generated text. (Default: 1.1)\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"system\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"system\",\"display_name\":\"System\",\"advanced\":true,\"dynamic\":false,\"info\":\"System to use for generating text.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.8,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"Controls the creativity of model responses.\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"template\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"template\",\"display_name\":\"Template\",\"advanced\":true,\"dynamic\":false,\"info\":\"Template to use for generating text.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"tfs_z\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tfs_z\",\"display_name\":\"TFS Z\",\"advanced\":true,\"dynamic\":false,\"info\":\"Tail free sampling value. (Default: 1)\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"timeout\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"timeout\",\"display_name\":\"Timeout\",\"advanced\":true,\"dynamic\":false,\"info\":\"Timeout for the request stream.\",\"title_case\":false},\"top_k\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_k\",\"display_name\":\"Top K\",\"advanced\":true,\"dynamic\":false,\"info\":\"Limits token selection to top K. (Default: 40)\",\"title_case\":false},\"top_p\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_p\",\"display_name\":\"Top P\",\"advanced\":true,\"dynamic\":false,\"info\":\"Works together with top-k. (Default: 0.9)\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"verbose\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"verbose\",\"display_name\":\"Verbose\",\"advanced\":false,\"dynamic\":false,\"info\":\"Whether to print out response text.\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Local LLM for chat with Ollama.\",\"base_classes\":[\"BaseLanguageModel\",\"Runnable\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"object\",\"BaseChatModel\"],\"display_name\":\"ChatOllama\",\"documentation\":\"\",\"custom_fields\":{\"base_url\":null,\"model\":null,\"mirostat\":null,\"mirostat_eta\":null,\"mirostat_tau\":null,\"repeat_last_n\":null,\"verbose\":null,\"cache\":null,\"num_ctx\":null,\"num_gpu\":null,\"format\":null,\"metadata\":null,\"num_thread\":null,\"repeat_penalty\":null,\"stop\":null,\"system\":null,\"tags\":null,\"temperature\":null,\"template\":null,\"tfs_z\":null,\"timeout\":null,\"top_k\":null,\"top_p\":null},\"output_types\":[\"BaseChatModel\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"BaiduQianfanChatEndpointsSpecs\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain_community.chat_models.baidu_qianfan_endpoint import QianfanChatEndpoint\\nfrom langchain.llms.base import BaseLLM\\nfrom pydantic.v1 import SecretStr\\n\\nfrom langflow import CustomComponent\\n\\n\\nclass QianfanChatEndpointComponent(CustomComponent):\\n display_name: str = \\\"QianfanChatEndpoint\\\"\\n description: str = (\\n \\\"Baidu Qianfan chat models. Get more detail from \\\"\\n \\\"https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint.\\\"\\n )\\n\\n def build_config(self):\\n return {\\n \\\"model\\\": {\\n \\\"display_name\\\": \\\"Model Name\\\",\\n \\\"options\\\": [\\n \\\"ERNIE-Bot\\\",\\n \\\"ERNIE-Bot-turbo\\\",\\n \\\"BLOOMZ-7B\\\",\\n \\\"Llama-2-7b-chat\\\",\\n \\\"Llama-2-13b-chat\\\",\\n \\\"Llama-2-70b-chat\\\",\\n \\\"Qianfan-BLOOMZ-7B-compressed\\\",\\n \\\"Qianfan-Chinese-Llama-2-7B\\\",\\n \\\"ChatGLM2-6B-32K\\\",\\n \\\"AquilaChat-7B\\\",\\n ],\\n \\\"info\\\": \\\"https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint\\\",\\n \\\"required\\\": True,\\n },\\n \\\"qianfan_ak\\\": {\\n \\\"display_name\\\": \\\"Qianfan Ak\\\",\\n \\\"required\\\": True,\\n \\\"password\\\": True,\\n \\\"info\\\": \\\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\\\",\\n },\\n \\\"qianfan_sk\\\": {\\n \\\"display_name\\\": \\\"Qianfan Sk\\\",\\n \\\"required\\\": True,\\n \\\"password\\\": True,\\n \\\"info\\\": \\\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\\\",\\n },\\n \\\"top_p\\\": {\\n \\\"display_name\\\": \\\"Top p\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\\\",\\n \\\"value\\\": 0.8,\\n },\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\\\",\\n \\\"value\\\": 0.95,\\n },\\n \\\"penalty_score\\\": {\\n \\\"display_name\\\": \\\"Penalty Score\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\\\",\\n \\\"value\\\": 1.0,\\n },\\n \\\"endpoint\\\": {\\n \\\"display_name\\\": \\\"Endpoint\\\",\\n \\\"info\\\": \\\"Endpoint of the Qianfan LLM, required if custom model used.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n model: str = \\\"ERNIE-Bot-turbo\\\",\\n qianfan_ak: Optional[str] = None,\\n qianfan_sk: Optional[str] = None,\\n top_p: Optional[float] = None,\\n temperature: Optional[float] = None,\\n penalty_score: Optional[float] = None,\\n endpoint: Optional[str] = None,\\n ) -> BaseLLM:\\n try:\\n output = QianfanChatEndpoint( # type: ignore\\n model=model,\\n qianfan_ak=SecretStr(qianfan_ak) if qianfan_ak else None,\\n qianfan_sk=SecretStr(qianfan_sk) if qianfan_sk else None,\\n top_p=top_p,\\n temperature=temperature,\\n penalty_score=penalty_score,\\n endpoint=endpoint,\\n )\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to Baidu Qianfan API.\\\") from e\\n return output # type: ignore\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"endpoint\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"endpoint\",\"display_name\":\"Endpoint\",\"advanced\":false,\"dynamic\":false,\"info\":\"Endpoint of the Qianfan LLM, required if custom model used.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"model\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"ERNIE-Bot-turbo\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"ERNIE-Bot\",\"ERNIE-Bot-turbo\",\"BLOOMZ-7B\",\"Llama-2-7b-chat\",\"Llama-2-13b-chat\",\"Llama-2-70b-chat\",\"Qianfan-BLOOMZ-7B-compressed\",\"Qianfan-Chinese-Llama-2-7B\",\"ChatGLM2-6B-32K\",\"AquilaChat-7B\"],\"name\":\"model\",\"display_name\":\"Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint\",\"title_case\":false,\"input_types\":[\"Text\"]},\"penalty_score\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1.0,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"penalty_score\",\"display_name\":\"Penalty Score\",\"advanced\":false,\"dynamic\":false,\"info\":\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"qianfan_ak\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"qianfan_ak\",\"display_name\":\"Qianfan Ak\",\"advanced\":false,\"dynamic\":false,\"info\":\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\",\"title_case\":false,\"input_types\":[\"Text\"]},\"qianfan_sk\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"qianfan_sk\",\"display_name\":\"Qianfan Sk\",\"advanced\":false,\"dynamic\":false,\"info\":\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\",\"title_case\":false,\"input_types\":[\"Text\"]},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.95,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"top_p\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.8,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_p\",\"display_name\":\"Top p\",\"advanced\":false,\"dynamic\":false,\"info\":\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Baidu Qianfan chat models. Get more detail from https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint.\",\"base_classes\":[\"BaseLanguageModel\",\"Runnable\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"object\",\"BaseLLM\"],\"display_name\":\"QianfanChatEndpoint\",\"documentation\":\"\",\"custom_fields\":{\"model\":null,\"qianfan_ak\":null,\"qianfan_sk\":null,\"top_p\":null,\"temperature\":null,\"penalty_score\":null,\"endpoint\":null},\"output_types\":[\"BaseLLM\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"LlamaCppSpecs\":{\"template\":{\"metadata\":{\"type\":\"Dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"metadata\",\"display_name\":\"Metadata\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"model_kwargs\":{\"type\":\"Dict\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model_kwargs\",\"display_name\":\"Model Kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"model_path\":{\"type\":\"file\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[\".bin\"],\"file_path\":\"\",\"password\":false,\"name\":\"model_path\",\"display_name\":\"Model Path\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"cache\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"cache\",\"display_name\":\"Cache\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"client\":{\"type\":\"Any\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"client\",\"display_name\":\"Client\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional, List, Dict, Any\\nfrom langflow import CustomComponent\\nfrom langchain_community.llms.llamacpp import LlamaCpp\\n\\n\\nclass LlamaCppComponent(CustomComponent):\\n display_name = \\\"LlamaCpp\\\"\\n description = \\\"llama.cpp model.\\\"\\n documentation = \\\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/llamacpp\\\"\\n\\n def build_config(self):\\n return {\\n \\\"grammar\\\": {\\\"display_name\\\": \\\"Grammar\\\", \\\"advanced\\\": True},\\n \\\"cache\\\": {\\\"display_name\\\": \\\"Cache\\\", \\\"advanced\\\": True},\\n \\\"client\\\": {\\\"display_name\\\": \\\"Client\\\", \\\"advanced\\\": True},\\n \\\"echo\\\": {\\\"display_name\\\": \\\"Echo\\\", \\\"advanced\\\": True},\\n \\\"f16_kv\\\": {\\\"display_name\\\": \\\"F16 KV\\\", \\\"advanced\\\": True},\\n \\\"grammar_path\\\": {\\\"display_name\\\": \\\"Grammar Path\\\", \\\"advanced\\\": True},\\n \\\"last_n_tokens_size\\\": {\\\"display_name\\\": \\\"Last N Tokens Size\\\", \\\"advanced\\\": True},\\n \\\"logits_all\\\": {\\\"display_name\\\": \\\"Logits All\\\", \\\"advanced\\\": True},\\n \\\"logprobs\\\": {\\\"display_name\\\": \\\"Logprobs\\\", \\\"advanced\\\": True},\\n \\\"lora_base\\\": {\\\"display_name\\\": \\\"Lora Base\\\", \\\"advanced\\\": True},\\n \\\"lora_path\\\": {\\\"display_name\\\": \\\"Lora Path\\\", \\\"advanced\\\": True},\\n \\\"max_tokens\\\": {\\\"display_name\\\": \\\"Max Tokens\\\", \\\"advanced\\\": True},\\n \\\"metadata\\\": {\\\"display_name\\\": \\\"Metadata\\\", \\\"advanced\\\": True},\\n \\\"model_kwargs\\\": {\\\"display_name\\\": \\\"Model Kwargs\\\", \\\"advanced\\\": True},\\n \\\"model_path\\\": {\\n \\\"display_name\\\": \\\"Model Path\\\",\\n \\\"field_type\\\": \\\"file\\\",\\n \\\"file_types\\\": [\\\".bin\\\"],\\n \\\"required\\\": True,\\n },\\n \\\"n_batch\\\": {\\\"display_name\\\": \\\"N Batch\\\", \\\"advanced\\\": True},\\n \\\"n_ctx\\\": {\\\"display_name\\\": \\\"N Ctx\\\", \\\"advanced\\\": True},\\n \\\"n_gpu_layers\\\": {\\\"display_name\\\": \\\"N GPU Layers\\\", \\\"advanced\\\": True},\\n \\\"n_parts\\\": {\\\"display_name\\\": \\\"N Parts\\\", \\\"advanced\\\": True},\\n \\\"n_threads\\\": {\\\"display_name\\\": \\\"N Threads\\\", \\\"advanced\\\": True},\\n \\\"repeat_penalty\\\": {\\\"display_name\\\": \\\"Repeat Penalty\\\", \\\"advanced\\\": True},\\n \\\"rope_freq_base\\\": {\\\"display_name\\\": \\\"Rope Freq Base\\\", \\\"advanced\\\": True},\\n \\\"rope_freq_scale\\\": {\\\"display_name\\\": \\\"Rope Freq Scale\\\", \\\"advanced\\\": True},\\n \\\"seed\\\": {\\\"display_name\\\": \\\"Seed\\\", \\\"advanced\\\": True},\\n \\\"stop\\\": {\\\"display_name\\\": \\\"Stop\\\", \\\"advanced\\\": True},\\n \\\"streaming\\\": {\\\"display_name\\\": \\\"Streaming\\\", \\\"advanced\\\": True},\\n \\\"suffix\\\": {\\\"display_name\\\": \\\"Suffix\\\", \\\"advanced\\\": True},\\n \\\"tags\\\": {\\\"display_name\\\": \\\"Tags\\\", \\\"advanced\\\": True},\\n \\\"temperature\\\": {\\\"display_name\\\": \\\"Temperature\\\"},\\n \\\"top_k\\\": {\\\"display_name\\\": \\\"Top K\\\", \\\"advanced\\\": True},\\n \\\"top_p\\\": {\\\"display_name\\\": \\\"Top P\\\", \\\"advanced\\\": True},\\n \\\"use_mlock\\\": {\\\"display_name\\\": \\\"Use Mlock\\\", \\\"advanced\\\": True},\\n \\\"use_mmap\\\": {\\\"display_name\\\": \\\"Use Mmap\\\", \\\"advanced\\\": True},\\n \\\"verbose\\\": {\\\"display_name\\\": \\\"Verbose\\\", \\\"advanced\\\": True},\\n \\\"vocab_only\\\": {\\\"display_name\\\": \\\"Vocab Only\\\", \\\"advanced\\\": True},\\n }\\n\\n def build(\\n self,\\n model_path: str,\\n grammar: Optional[str] = None,\\n cache: Optional[bool] = None,\\n client: Optional[Any] = None,\\n echo: Optional[bool] = False,\\n f16_kv: bool = True,\\n grammar_path: Optional[str] = None,\\n last_n_tokens_size: Optional[int] = 64,\\n logits_all: bool = False,\\n logprobs: Optional[int] = None,\\n lora_base: Optional[str] = None,\\n lora_path: Optional[str] = None,\\n max_tokens: Optional[int] = 256,\\n metadata: Optional[Dict] = None,\\n model_kwargs: Dict = {},\\n n_batch: Optional[int] = 8,\\n n_ctx: int = 512,\\n n_gpu_layers: Optional[int] = 1,\\n n_parts: int = -1,\\n n_threads: Optional[int] = 1,\\n repeat_penalty: Optional[float] = 1.1,\\n rope_freq_base: float = 10000.0,\\n rope_freq_scale: float = 1.0,\\n seed: int = -1,\\n stop: Optional[List[str]] = [],\\n streaming: bool = True,\\n suffix: Optional[str] = \\\"\\\",\\n tags: Optional[List[str]] = [],\\n temperature: Optional[float] = 0.8,\\n top_k: Optional[int] = 40,\\n top_p: Optional[float] = 0.95,\\n use_mlock: bool = False,\\n use_mmap: Optional[bool] = True,\\n verbose: bool = True,\\n vocab_only: bool = False,\\n ) -> LlamaCpp:\\n return LlamaCpp(\\n model_path=model_path,\\n grammar=grammar,\\n cache=cache,\\n client=client,\\n echo=echo,\\n f16_kv=f16_kv,\\n grammar_path=grammar_path,\\n last_n_tokens_size=last_n_tokens_size,\\n logits_all=logits_all,\\n logprobs=logprobs,\\n lora_base=lora_base,\\n lora_path=lora_path,\\n max_tokens=max_tokens,\\n metadata=metadata,\\n model_kwargs=model_kwargs,\\n n_batch=n_batch,\\n n_ctx=n_ctx,\\n n_gpu_layers=n_gpu_layers,\\n n_parts=n_parts,\\n n_threads=n_threads,\\n repeat_penalty=repeat_penalty,\\n rope_freq_base=rope_freq_base,\\n rope_freq_scale=rope_freq_scale,\\n seed=seed,\\n stop=stop,\\n streaming=streaming,\\n suffix=suffix,\\n tags=tags,\\n temperature=temperature,\\n top_k=top_k,\\n top_p=top_p,\\n use_mlock=use_mlock,\\n use_mmap=use_mmap,\\n verbose=verbose,\\n vocab_only=vocab_only,\\n )\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"echo\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"echo\",\"display_name\":\"Echo\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"f16_kv\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":true,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"f16_kv\",\"display_name\":\"F16 KV\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"grammar\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"grammar\",\"display_name\":\"Grammar\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"grammar_path\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"grammar_path\",\"display_name\":\"Grammar Path\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"last_n_tokens_size\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":64,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"last_n_tokens_size\",\"display_name\":\"Last N Tokens Size\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"logits_all\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"logits_all\",\"display_name\":\"Logits All\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"logprobs\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"logprobs\",\"display_name\":\"Logprobs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"lora_base\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"lora_base\",\"display_name\":\"Lora Base\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"lora_path\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"lora_path\",\"display_name\":\"Lora Path\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"max_tokens\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":256,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_tokens\",\"display_name\":\"Max Tokens\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"n_batch\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":8,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"n_batch\",\"display_name\":\"N Batch\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"n_ctx\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":512,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"n_ctx\",\"display_name\":\"N Ctx\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"n_gpu_layers\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"n_gpu_layers\",\"display_name\":\"N GPU Layers\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"n_parts\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":-1,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"n_parts\",\"display_name\":\"N Parts\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"n_threads\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"n_threads\",\"display_name\":\"N Threads\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"repeat_penalty\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1.1,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"repeat_penalty\",\"display_name\":\"Repeat Penalty\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"rope_freq_base\":{\"type\":\"float\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":10000.0,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"rope_freq_base\",\"display_name\":\"Rope Freq Base\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"rope_freq_scale\":{\"type\":\"float\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1.0,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"rope_freq_scale\",\"display_name\":\"Rope Freq Scale\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"seed\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":-1,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"seed\",\"display_name\":\"Seed\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"stop\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":[],\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"stop\",\"display_name\":\"Stop\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"streaming\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":true,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"streaming\",\"display_name\":\"Streaming\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"suffix\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"suffix\",\"display_name\":\"Suffix\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"tags\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":[],\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tags\",\"display_name\":\"Tags\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.8,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"top_k\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":40,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_k\",\"display_name\":\"Top K\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"top_p\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.95,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_p\",\"display_name\":\"Top P\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"use_mlock\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"use_mlock\",\"display_name\":\"Use Mlock\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"use_mmap\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":true,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"use_mmap\",\"display_name\":\"Use Mmap\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"verbose\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":true,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"verbose\",\"display_name\":\"Verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"vocab_only\":{\"type\":\"bool\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"vocab_only\",\"display_name\":\"Vocab Only\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"llama.cpp model.\",\"base_classes\":[\"BaseLanguageModel\",\"Runnable\",\"Generic\",\"LlamaCpp\",\"RunnableSerializable\",\"Serializable\",\"object\",\"BaseLLM\",\"LLM\"],\"display_name\":\"LlamaCpp\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/llamacpp\",\"custom_fields\":{\"model_path\":null,\"grammar\":null,\"cache\":null,\"client\":null,\"echo\":null,\"f16_kv\":null,\"grammar_path\":null,\"last_n_tokens_size\":null,\"logits_all\":null,\"logprobs\":null,\"lora_base\":null,\"lora_path\":null,\"max_tokens\":null,\"metadata\":null,\"model_kwargs\":null,\"n_batch\":null,\"n_ctx\":null,\"n_gpu_layers\":null,\"n_parts\":null,\"n_threads\":null,\"repeat_penalty\":null,\"rope_freq_base\":null,\"rope_freq_scale\":null,\"seed\":null,\"stop\":null,\"streaming\":null,\"suffix\":null,\"tags\":null,\"temperature\":null,\"top_k\":null,\"top_p\":null,\"use_mlock\":null,\"use_mmap\":null,\"verbose\":null,\"vocab_only\":null},\"output_types\":[\"LlamaCpp\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"AnthropicSpecs\":{\"template\":{\"anthropic_api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"anthropic_api_key\",\"display_name\":\"Anthropic API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"anthropic_api_url\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"anthropic_api_url\",\"display_name\":\"Anthropic API URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain_community.llms.anthropic import Anthropic\\nfrom pydantic.v1 import SecretStr\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import BaseLanguageModel, NestedDict\\n\\n\\nclass AnthropicComponent(CustomComponent):\\n display_name = \\\"Anthropic\\\"\\n description = \\\"Anthropic large language models.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"anthropic_api_key\\\": {\\n \\\"display_name\\\": \\\"Anthropic API Key\\\",\\n \\\"type\\\": str,\\n \\\"password\\\": True,\\n },\\n \\\"anthropic_api_url\\\": {\\n \\\"display_name\\\": \\\"Anthropic API URL\\\",\\n \\\"type\\\": str,\\n },\\n \\\"model_kwargs\\\": {\\n \\\"display_name\\\": \\\"Model Kwargs\\\",\\n \\\"field_type\\\": \\\"NestedDict\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n },\\n }\\n\\n def build(\\n self,\\n anthropic_api_key: str,\\n anthropic_api_url: str,\\n model_kwargs: NestedDict = {},\\n temperature: Optional[float] = None,\\n ) -> BaseLanguageModel:\\n return Anthropic(\\n anthropic_api_key=SecretStr(anthropic_api_key),\\n anthropic_api_url=anthropic_api_url,\\n model_kwargs=model_kwargs,\\n temperature=temperature,\\n )\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"model_kwargs\":{\"type\":\"NestedDict\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model_kwargs\",\"display_name\":\"Model Kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Anthropic large language models.\",\"base_classes\":[\"BaseLanguageModel\",\"Runnable\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"object\"],\"display_name\":\"Anthropic\",\"documentation\":\"\",\"custom_fields\":{\"anthropic_api_key\":null,\"anthropic_api_url\":null,\"model_kwargs\":null,\"temperature\":null},\"output_types\":[\"BaseLanguageModel\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"AnthropicLLMSpecs\":{\"template\":{\"anthropic_api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"anthropic_api_key\",\"display_name\":\"Anthropic API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"Your Anthropic API key.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"api_endpoint\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"api_endpoint\",\"display_name\":\"API Endpoint\",\"advanced\":false,\"dynamic\":false,\"info\":\"Endpoint of the Anthropic API. Defaults to 'https://api.anthropic.com' if not specified.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain_community.chat_models.anthropic import ChatAnthropic\\nfrom langchain.llms.base import BaseLanguageModel\\nfrom pydantic.v1 import SecretStr\\n\\nfrom langflow import CustomComponent\\n\\n\\nclass AnthropicLLM(CustomComponent):\\n display_name: str = \\\"AnthropicLLM\\\"\\n description: str = \\\"Anthropic Chat&Completion large language models.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"model\\\": {\\n \\\"display_name\\\": \\\"Model Name\\\",\\n \\\"options\\\": [\\n \\\"claude-2.1\\\",\\n \\\"claude-2.0\\\",\\n \\\"claude-instant-1.2\\\",\\n \\\"claude-instant-1\\\",\\n # Add more models as needed\\n ],\\n \\\"info\\\": \\\"https://python.langchain.com/docs/integrations/chat/anthropic\\\",\\n \\\"required\\\": True,\\n \\\"value\\\": \\\"claude-2.1\\\",\\n },\\n \\\"anthropic_api_key\\\": {\\n \\\"display_name\\\": \\\"Anthropic API Key\\\",\\n \\\"required\\\": True,\\n \\\"password\\\": True,\\n \\\"info\\\": \\\"Your Anthropic API key.\\\",\\n },\\n \\\"max_tokens\\\": {\\n \\\"display_name\\\": \\\"Max Tokens\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"value\\\": 256,\\n },\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"value\\\": 0.7,\\n },\\n \\\"api_endpoint\\\": {\\n \\\"display_name\\\": \\\"API Endpoint\\\",\\n \\\"info\\\": \\\"Endpoint of the Anthropic API. Defaults to 'https://api.anthropic.com' if not specified.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n model: str,\\n anthropic_api_key: Optional[str] = None,\\n max_tokens: Optional[int] = None,\\n temperature: Optional[float] = None,\\n api_endpoint: Optional[str] = None,\\n ) -> BaseLanguageModel:\\n # Set default API endpoint if not provided\\n if not api_endpoint:\\n api_endpoint = \\\"https://api.anthropic.com\\\"\\n\\n try:\\n output = ChatAnthropic(\\n model_name=model,\\n anthropic_api_key=SecretStr(anthropic_api_key) if anthropic_api_key else None,\\n max_tokens_to_sample=max_tokens, # type: ignore\\n temperature=temperature,\\n anthropic_api_url=api_endpoint,\\n )\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to Anthropic API.\\\") from e\\n return output\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"max_tokens\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":256,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_tokens\",\"display_name\":\"Max Tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"model\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"claude-2.1\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"claude-2.1\",\"claude-2.0\",\"claude-instant-1.2\",\"claude-instant-1\"],\"name\":\"model\",\"display_name\":\"Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"https://python.langchain.com/docs/integrations/chat/anthropic\",\"title_case\":false,\"input_types\":[\"Text\"]},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.7,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Anthropic Chat&Completion large language models.\",\"base_classes\":[\"BaseLanguageModel\",\"Runnable\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"object\"],\"display_name\":\"AnthropicLLM\",\"documentation\":\"\",\"custom_fields\":{\"model\":null,\"anthropic_api_key\":null,\"max_tokens\":null,\"temperature\":null,\"api_endpoint\":null},\"output_types\":[\"BaseLanguageModel\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"CohereSpecs\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langchain_community.llms.cohere import Cohere\\nfrom langchain_core.language_models.base import BaseLanguageModel\\nfrom langflow import CustomComponent\\n\\n\\nclass CohereComponent(CustomComponent):\\n display_name = \\\"Cohere\\\"\\n description = \\\"Cohere large language models.\\\"\\n documentation = \\\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/cohere\\\"\\n\\n def build_config(self):\\n return {\\n \\\"cohere_api_key\\\": {\\\"display_name\\\": \\\"Cohere API Key\\\", \\\"type\\\": \\\"password\\\", \\\"password\\\": True},\\n \\\"max_tokens\\\": {\\\"display_name\\\": \\\"Max Tokens\\\", \\\"default\\\": 256, \\\"type\\\": \\\"int\\\", \\\"show\\\": True},\\n \\\"temperature\\\": {\\\"display_name\\\": \\\"Temperature\\\", \\\"default\\\": 0.75, \\\"type\\\": \\\"float\\\", \\\"show\\\": True},\\n }\\n\\n def build(\\n self,\\n cohere_api_key: str,\\n max_tokens: int = 256,\\n temperature: float = 0.75,\\n ) -> BaseLanguageModel:\\n return Cohere(cohere_api_key=cohere_api_key, max_tokens=max_tokens, temperature=temperature) # type: ignore\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"cohere_api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"cohere_api_key\",\"display_name\":\"Cohere API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"max_tokens\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":256,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_tokens\",\"display_name\":\"Max Tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"temperature\":{\"type\":\"float\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.75,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Cohere large language models.\",\"base_classes\":[\"BaseLanguageModel\",\"Runnable\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"object\"],\"display_name\":\"Cohere\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/cohere\",\"custom_fields\":{\"cohere_api_key\":null,\"max_tokens\":null,\"temperature\":null},\"output_types\":[\"BaseLanguageModel\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"GoogleGenerativeAISpecs\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain_google_genai import ChatGoogleGenerativeAI # type: ignore\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import BaseLanguageModel, RangeSpec\\nfrom pydantic.v1.types import SecretStr\\n\\n\\nclass GoogleGenerativeAIComponent(CustomComponent):\\n display_name: str = \\\"Google Generative AI\\\"\\n description: str = \\\"A component that uses Google Generative AI to generate text.\\\"\\n documentation: str = \\\"http://docs.langflow.org/components/custom\\\"\\n\\n def build_config(self):\\n return {\\n \\\"google_api_key\\\": {\\n \\\"display_name\\\": \\\"Google API Key\\\",\\n \\\"info\\\": \\\"The Google API Key to use for the Google Generative AI.\\\",\\n },\\n \\\"max_output_tokens\\\": {\\n \\\"display_name\\\": \\\"Max Output Tokens\\\",\\n \\\"info\\\": \\\"The maximum number of tokens to generate.\\\",\\n },\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"info\\\": \\\"Run inference with this temperature. Must by in the closed interval [0.0, 1.0].\\\",\\n },\\n \\\"top_k\\\": {\\n \\\"display_name\\\": \\\"Top K\\\",\\n \\\"info\\\": \\\"Decode using top-k sampling: consider the set of top_k most probable tokens. Must be positive.\\\",\\n \\\"range_spec\\\": RangeSpec(min=0, max=2, step=0.1),\\n \\\"advanced\\\": True,\\n },\\n \\\"top_p\\\": {\\n \\\"display_name\\\": \\\"Top P\\\",\\n \\\"info\\\": \\\"The maximum cumulative probability of tokens to consider when sampling.\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"n\\\": {\\n \\\"display_name\\\": \\\"N\\\",\\n \\\"info\\\": \\\"Number of chat completions to generate for each prompt. Note that the API may not return the full n completions if duplicates are generated.\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"model\\\": {\\n \\\"display_name\\\": \\\"Model\\\",\\n \\\"info\\\": \\\"The name of the model to use. Supported examples: gemini-pro\\\",\\n \\\"options\\\": [\\\"gemini-pro\\\", \\\"gemini-pro-vision\\\"],\\n },\\n \\\"code\\\": {\\n \\\"advanced\\\": True,\\n },\\n }\\n\\n def build(\\n self,\\n google_api_key: str,\\n model: str,\\n max_output_tokens: Optional[int] = None,\\n temperature: float = 0.1,\\n top_k: Optional[int] = None,\\n top_p: Optional[float] = None,\\n n: Optional[int] = 1,\\n ) -> BaseLanguageModel:\\n return ChatGoogleGenerativeAI(\\n model=model,\\n max_output_tokens=max_output_tokens or None, # type: ignore\\n temperature=temperature,\\n top_k=top_k or None,\\n top_p=top_p or None, # type: ignore\\n n=n or 1,\\n google_api_key=SecretStr(google_api_key),\\n )\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"google_api_key\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"google_api_key\",\"display_name\":\"Google API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"The Google API Key to use for the Google Generative AI.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"max_output_tokens\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_output_tokens\",\"display_name\":\"Max Output Tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"The maximum number of tokens to generate.\",\"title_case\":false},\"model\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"gemini-pro\",\"gemini-pro-vision\"],\"name\":\"model\",\"display_name\":\"Model\",\"advanced\":false,\"dynamic\":false,\"info\":\"The name of the model to use. Supported examples: gemini-pro\",\"title_case\":false,\"input_types\":[\"Text\"]},\"n\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"n\",\"display_name\":\"N\",\"advanced\":true,\"dynamic\":false,\"info\":\"Number of chat completions to generate for each prompt. Note that the API may not return the full n completions if duplicates are generated.\",\"title_case\":false},\"temperature\":{\"type\":\"float\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.1,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"Run inference with this temperature. Must by in the closed interval [0.0, 1.0].\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"top_k\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_k\",\"display_name\":\"Top K\",\"advanced\":true,\"dynamic\":false,\"info\":\"Decode using top-k sampling: consider the set of top_k most probable tokens. Must be positive.\",\"rangeSpec\":{\"min\":0.0,\"max\":2.0,\"step\":0.1},\"title_case\":false},\"top_p\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_p\",\"display_name\":\"Top P\",\"advanced\":true,\"dynamic\":false,\"info\":\"The maximum cumulative probability of tokens to consider when sampling.\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"A component that uses Google Generative AI to generate text.\",\"base_classes\":[\"BaseLanguageModel\",\"Runnable\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"object\"],\"display_name\":\"Google Generative AI\",\"documentation\":\"http://docs.langflow.org/components/custom\",\"custom_fields\":{\"google_api_key\":null,\"model\":null,\"max_output_tokens\":null,\"temperature\":null,\"top_k\":null,\"top_p\":null,\"n\":null},\"output_types\":[\"BaseLanguageModel\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"BaiduQianfanLLMEndpointsSpecs\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\nfrom langflow import CustomComponent\\nfrom langchain.llms.baidu_qianfan_endpoint import QianfanLLMEndpoint\\nfrom langchain.llms.base import BaseLLM\\n\\n\\nclass QianfanLLMEndpointComponent(CustomComponent):\\n display_name: str = \\\"QianfanLLMEndpoint\\\"\\n description: str = (\\n \\\"Baidu Qianfan hosted open source or customized models. \\\"\\n \\\"Get more detail from https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint\\\"\\n )\\n\\n def build_config(self):\\n return {\\n \\\"model\\\": {\\n \\\"display_name\\\": \\\"Model Name\\\",\\n \\\"options\\\": [\\n \\\"ERNIE-Bot\\\",\\n \\\"ERNIE-Bot-turbo\\\",\\n \\\"BLOOMZ-7B\\\",\\n \\\"Llama-2-7b-chat\\\",\\n \\\"Llama-2-13b-chat\\\",\\n \\\"Llama-2-70b-chat\\\",\\n \\\"Qianfan-BLOOMZ-7B-compressed\\\",\\n \\\"Qianfan-Chinese-Llama-2-7B\\\",\\n \\\"ChatGLM2-6B-32K\\\",\\n \\\"AquilaChat-7B\\\",\\n ],\\n \\\"info\\\": \\\"https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint\\\",\\n \\\"required\\\": True,\\n },\\n \\\"qianfan_ak\\\": {\\n \\\"display_name\\\": \\\"Qianfan Ak\\\",\\n \\\"required\\\": True,\\n \\\"password\\\": True,\\n \\\"info\\\": \\\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\\\",\\n },\\n \\\"qianfan_sk\\\": {\\n \\\"display_name\\\": \\\"Qianfan Sk\\\",\\n \\\"required\\\": True,\\n \\\"password\\\": True,\\n \\\"info\\\": \\\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\\\",\\n },\\n \\\"top_p\\\": {\\n \\\"display_name\\\": \\\"Top p\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\\\",\\n \\\"value\\\": 0.8,\\n },\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\\\",\\n \\\"value\\\": 0.95,\\n },\\n \\\"penalty_score\\\": {\\n \\\"display_name\\\": \\\"Penalty Score\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\\\",\\n \\\"value\\\": 1.0,\\n },\\n \\\"endpoint\\\": {\\n \\\"display_name\\\": \\\"Endpoint\\\",\\n \\\"info\\\": \\\"Endpoint of the Qianfan LLM, required if custom model used.\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n model: str = \\\"ERNIE-Bot-turbo\\\",\\n qianfan_ak: Optional[str] = None,\\n qianfan_sk: Optional[str] = None,\\n top_p: Optional[float] = None,\\n temperature: Optional[float] = None,\\n penalty_score: Optional[float] = None,\\n endpoint: Optional[str] = None,\\n ) -> BaseLLM:\\n try:\\n output = QianfanLLMEndpoint( # type: ignore\\n model=model,\\n qianfan_ak=qianfan_ak,\\n qianfan_sk=qianfan_sk,\\n top_p=top_p,\\n temperature=temperature,\\n penalty_score=penalty_score,\\n endpoint=endpoint,\\n )\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to Baidu Qianfan API.\\\") from e\\n return output # type: ignore\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"endpoint\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"endpoint\",\"display_name\":\"Endpoint\",\"advanced\":false,\"dynamic\":false,\"info\":\"Endpoint of the Qianfan LLM, required if custom model used.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"model\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"ERNIE-Bot-turbo\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"ERNIE-Bot\",\"ERNIE-Bot-turbo\",\"BLOOMZ-7B\",\"Llama-2-7b-chat\",\"Llama-2-13b-chat\",\"Llama-2-70b-chat\",\"Qianfan-BLOOMZ-7B-compressed\",\"Qianfan-Chinese-Llama-2-7B\",\"ChatGLM2-6B-32K\",\"AquilaChat-7B\"],\"name\":\"model\",\"display_name\":\"Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint\",\"title_case\":false,\"input_types\":[\"Text\"]},\"penalty_score\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1.0,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"penalty_score\",\"display_name\":\"Penalty Score\",\"advanced\":false,\"dynamic\":false,\"info\":\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"qianfan_ak\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"qianfan_ak\",\"display_name\":\"Qianfan Ak\",\"advanced\":false,\"dynamic\":false,\"info\":\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\",\"title_case\":false,\"input_types\":[\"Text\"]},\"qianfan_sk\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"qianfan_sk\",\"display_name\":\"Qianfan Sk\",\"advanced\":false,\"dynamic\":false,\"info\":\"which you could get from https://cloud.baidu.com/product/wenxinworkshop\",\"title_case\":false,\"input_types\":[\"Text\"]},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.95,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"top_p\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.8,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_p\",\"display_name\":\"Top p\",\"advanced\":false,\"dynamic\":false,\"info\":\"Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Baidu Qianfan hosted open source or customized models. Get more detail from https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint\",\"base_classes\":[\"BaseLanguageModel\",\"Runnable\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"object\",\"BaseLLM\"],\"display_name\":\"QianfanLLMEndpoint\",\"documentation\":\"\",\"custom_fields\":{\"model\":null,\"qianfan_ak\":null,\"qianfan_sk\":null,\"top_p\":null,\"temperature\":null,\"penalty_score\":null,\"endpoint\":null},\"output_types\":[\"BaseLLM\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"ChatLiteLLMSpecs\":{\"template\":{\"api_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"api_key\",\"display_name\":\"API key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Any, Callable, Dict, Optional, Union\\n\\nfrom langchain_community.chat_models.litellm import ChatLiteLLM, ChatLiteLLMException\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import BaseLanguageModel\\n\\n\\nclass ChatLiteLLMComponent(CustomComponent):\\n display_name = \\\"ChatLiteLLM\\\"\\n description = \\\"`LiteLLM` collection of large language models.\\\"\\n documentation = \\\"https://python.langchain.com/docs/integrations/chat/litellm\\\"\\n\\n def build_config(self):\\n return {\\n \\\"model\\\": {\\n \\\"display_name\\\": \\\"Model name\\\",\\n \\\"field_type\\\": \\\"str\\\",\\n \\\"advanced\\\": False,\\n \\\"required\\\": True,\\n \\\"info\\\": \\\"The name of the model to use. For example, `gpt-3.5-turbo`.\\\",\\n },\\n \\\"api_key\\\": {\\n \\\"display_name\\\": \\\"API key\\\",\\n \\\"field_type\\\": \\\"str\\\",\\n \\\"advanced\\\": False,\\n \\\"required\\\": False,\\n \\\"password\\\": True,\\n },\\n \\\"provider\\\": {\\n \\\"display_name\\\": \\\"Provider\\\",\\n \\\"info\\\": \\\"The provider of the API key.\\\",\\n \\\"options\\\": [\\n \\\"OpenAI\\\",\\n \\\"Azure\\\",\\n \\\"Anthropic\\\",\\n \\\"Replicate\\\",\\n \\\"Cohere\\\",\\n \\\"OpenRouter\\\",\\n ],\\n },\\n \\\"streaming\\\": {\\n \\\"display_name\\\": \\\"Streaming\\\",\\n \\\"field_type\\\": \\\"bool\\\",\\n \\\"advanced\\\": True,\\n \\\"required\\\": False,\\n \\\"default\\\": True,\\n },\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"advanced\\\": False,\\n \\\"required\\\": False,\\n \\\"default\\\": 0.7,\\n },\\n \\\"model_kwargs\\\": {\\n \\\"display_name\\\": \\\"Model kwargs\\\",\\n \\\"field_type\\\": \\\"dict\\\",\\n \\\"advanced\\\": True,\\n \\\"required\\\": False,\\n \\\"default\\\": {},\\n },\\n \\\"top_p\\\": {\\n \\\"display_name\\\": \\\"Top p\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"advanced\\\": True,\\n \\\"required\\\": False,\\n },\\n \\\"top_k\\\": {\\n \\\"display_name\\\": \\\"Top k\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"advanced\\\": True,\\n \\\"required\\\": False,\\n },\\n \\\"n\\\": {\\n \\\"display_name\\\": \\\"N\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"advanced\\\": True,\\n \\\"required\\\": False,\\n \\\"info\\\": \\\"Number of chat completions to generate for each prompt. \\\"\\n \\\"Note that the API may not return the full n completions if duplicates are generated.\\\",\\n \\\"default\\\": 1,\\n },\\n \\\"max_tokens\\\": {\\n \\\"display_name\\\": \\\"Max tokens\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"advanced\\\": False,\\n \\\"required\\\": False,\\n \\\"default\\\": 256,\\n \\\"info\\\": \\\"The maximum number of tokens to generate for each chat completion.\\\",\\n },\\n \\\"max_retries\\\": {\\n \\\"display_name\\\": \\\"Max retries\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"advanced\\\": True,\\n \\\"required\\\": False,\\n \\\"default\\\": 6,\\n },\\n \\\"verbose\\\": {\\n \\\"display_name\\\": \\\"Verbose\\\",\\n \\\"field_type\\\": \\\"bool\\\",\\n \\\"advanced\\\": True,\\n \\\"required\\\": False,\\n \\\"default\\\": False,\\n },\\n }\\n\\n def build(\\n self,\\n model: str,\\n provider: str,\\n api_key: Optional[str] = None,\\n streaming: bool = True,\\n temperature: Optional[float] = 0.7,\\n model_kwargs: Optional[Dict[str, Any]] = {},\\n top_p: Optional[float] = None,\\n top_k: Optional[int] = None,\\n n: int = 1,\\n max_tokens: int = 256,\\n max_retries: int = 6,\\n verbose: bool = False,\\n ) -> Union[BaseLanguageModel, Callable]:\\n try:\\n import litellm # type: ignore\\n\\n litellm.drop_params = True\\n litellm.set_verbose = verbose\\n except ImportError:\\n raise ChatLiteLLMException(\\n \\\"Could not import litellm python package. \\\" \\\"Please install it with `pip install litellm`\\\"\\n )\\n provider_map = {\\n \\\"OpenAI\\\": \\\"openai_api_key\\\",\\n \\\"Azure\\\": \\\"azure_api_key\\\",\\n \\\"Anthropic\\\": \\\"anthropic_api_key\\\",\\n \\\"Replicate\\\": \\\"replicate_api_key\\\",\\n \\\"Cohere\\\": \\\"cohere_api_key\\\",\\n \\\"OpenRouter\\\": \\\"openrouter_api_key\\\",\\n }\\n # Set the API key based on the provider\\n kwarg = {provider_map[provider]: api_key}\\n\\n LLM = ChatLiteLLM(\\n model=model,\\n client=None,\\n streaming=streaming,\\n temperature=temperature,\\n model_kwargs=model_kwargs if model_kwargs is not None else {},\\n top_p=top_p,\\n top_k=top_k,\\n n=n,\\n max_tokens=max_tokens,\\n max_retries=max_retries,\\n **kwarg,\\n )\\n return LLM\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"max_retries\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":6,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_retries\",\"display_name\":\"Max retries\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"max_tokens\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":256,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_tokens\",\"display_name\":\"Max tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"The maximum number of tokens to generate for each chat completion.\",\"title_case\":false},\"model\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model\",\"display_name\":\"Model name\",\"advanced\":false,\"dynamic\":false,\"info\":\"The name of the model to use. For example, `gpt-3.5-turbo`.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"model_kwargs\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model_kwargs\",\"display_name\":\"Model kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"n\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":1,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"n\",\"display_name\":\"N\",\"advanced\":true,\"dynamic\":false,\"info\":\"Number of chat completions to generate for each prompt. Note that the API may not return the full n completions if duplicates are generated.\",\"title_case\":false},\"provider\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"OpenAI\",\"Azure\",\"Anthropic\",\"Replicate\",\"Cohere\",\"OpenRouter\"],\"name\":\"provider\",\"display_name\":\"Provider\",\"advanced\":false,\"dynamic\":false,\"info\":\"The provider of the API key.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"streaming\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":true,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"streaming\",\"display_name\":\"Streaming\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.7,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"top_k\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_k\",\"display_name\":\"Top k\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"top_p\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_p\",\"display_name\":\"Top p\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"verbose\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"verbose\",\"display_name\":\"Verbose\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"`LiteLLM` collection of large language models.\",\"base_classes\":[\"BaseLanguageModel\",\"Runnable\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"object\",\"Callable\"],\"display_name\":\"ChatLiteLLM\",\"documentation\":\"https://python.langchain.com/docs/integrations/chat/litellm\",\"custom_fields\":{\"model\":null,\"provider\":null,\"api_key\":null,\"streaming\":null,\"temperature\":null,\"model_kwargs\":null,\"top_p\":null,\"top_k\":null,\"n\":null,\"max_tokens\":null,\"max_retries\":null,\"verbose\":null},\"output_types\":[\"BaseLanguageModel\",\"Callable\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"CTransformersSpecs\":{\"template\":{\"model_file\":{\"type\":\"file\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[\".bin\"],\"file_path\":\"\",\"password\":false,\"name\":\"model_file\",\"display_name\":\"Model File\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Dict, Optional\\n\\nfrom langchain_community.llms.ctransformers import CTransformers\\n\\nfrom langflow import CustomComponent\\n\\n\\nclass CTransformersComponent(CustomComponent):\\n display_name = \\\"CTransformers\\\"\\n description = \\\"C Transformers LLM models\\\"\\n documentation = \\\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/ctransformers\\\"\\n\\n def build_config(self):\\n return {\\n \\\"model\\\": {\\\"display_name\\\": \\\"Model\\\", \\\"required\\\": True},\\n \\\"model_file\\\": {\\n \\\"display_name\\\": \\\"Model File\\\",\\n \\\"required\\\": False,\\n \\\"field_type\\\": \\\"file\\\",\\n \\\"file_types\\\": [\\\".bin\\\"],\\n },\\n \\\"model_type\\\": {\\\"display_name\\\": \\\"Model Type\\\", \\\"required\\\": True},\\n \\\"config\\\": {\\n \\\"display_name\\\": \\\"Config\\\",\\n \\\"advanced\\\": True,\\n \\\"required\\\": False,\\n \\\"field_type\\\": \\\"dict\\\",\\n \\\"value\\\": '{\\\"top_k\\\":40,\\\"top_p\\\":0.95,\\\"temperature\\\":0.8,\\\"repetition_penalty\\\":1.1,\\\"last_n_tokens\\\":64,\\\"seed\\\":-1,\\\"max_new_tokens\\\":256,\\\"stop\\\":\\\"\\\",\\\"stream\\\":\\\"False\\\",\\\"reset\\\":\\\"True\\\",\\\"batch_size\\\":8,\\\"threads\\\":-1,\\\"context_length\\\":-1,\\\"gpu_layers\\\":0}',\\n },\\n }\\n\\n def build(self, model: str, model_file: str, model_type: str, config: Optional[Dict] = None) -> CTransformers:\\n return CTransformers(model=model, model_file=model_file, model_type=model_type, config=config) # type: ignore\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"config\":{\"type\":\"dict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"{\\\"top_k\\\":40,\\\"top_p\\\":0.95,\\\"temperature\\\":0.8,\\\"repetition_penalty\\\":1.1,\\\"last_n_tokens\\\":64,\\\"seed\\\":-1,\\\"max_new_tokens\\\":256,\\\"stop\\\":\\\"\\\",\\\"stream\\\":\\\"False\\\",\\\"reset\\\":\\\"True\\\",\\\"batch_size\\\":8,\\\"threads\\\":-1,\\\"context_length\\\":-1,\\\"gpu_layers\\\":0}\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"config\",\"display_name\":\"Config\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"model\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model\",\"display_name\":\"Model\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"model_type\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model_type\",\"display_name\":\"Model Type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"C Transformers LLM models\",\"base_classes\":[\"BaseLanguageModel\",\"Runnable\",\"Generic\",\"CTransformers\",\"RunnableSerializable\",\"Serializable\",\"object\",\"BaseLLM\",\"LLM\"],\"display_name\":\"CTransformers\",\"documentation\":\"https://python.langchain.com/docs/modules/model_io/models/llms/integrations/ctransformers\",\"custom_fields\":{\"model\":null,\"model_file\":null,\"model_type\":null,\"config\":null},\"output_types\":[\"CTransformers\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"HuggingFaceEndpointsSpecs\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langchain.llms.base import BaseLLM\\nfrom langchain.llms.huggingface_endpoint import HuggingFaceEndpoint\\nfrom langflow import CustomComponent\\n\\n\\nclass HuggingFaceEndpointsComponent(CustomComponent):\\n display_name: str = \\\"Hugging Face Inference API\\\"\\n description: str = \\\"LLM model from Hugging Face Inference API.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"endpoint_url\\\": {\\\"display_name\\\": \\\"Endpoint URL\\\", \\\"password\\\": True},\\n \\\"task\\\": {\\n \\\"display_name\\\": \\\"Task\\\",\\n \\\"options\\\": [\\\"text2text-generation\\\", \\\"text-generation\\\", \\\"summarization\\\"],\\n },\\n \\\"huggingfacehub_api_token\\\": {\\\"display_name\\\": \\\"API token\\\", \\\"password\\\": True},\\n \\\"model_kwargs\\\": {\\n \\\"display_name\\\": \\\"Model Keyword Arguments\\\",\\n \\\"field_type\\\": \\\"code\\\",\\n },\\n \\\"code\\\": {\\\"show\\\": False},\\n }\\n\\n def build(\\n self,\\n endpoint_url: str,\\n task: str = \\\"text2text-generation\\\",\\n huggingfacehub_api_token: Optional[str] = None,\\n model_kwargs: Optional[dict] = None,\\n ) -> BaseLLM:\\n try:\\n output = HuggingFaceEndpoint( # type: ignore\\n endpoint_url=endpoint_url,\\n task=task,\\n huggingfacehub_api_token=huggingfacehub_api_token,\\n model_kwargs=model_kwargs or {},\\n )\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to HuggingFace Endpoints API.\\\") from e\\n return output\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"endpoint_url\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"endpoint_url\",\"display_name\":\"Endpoint URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"huggingfacehub_api_token\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"huggingfacehub_api_token\",\"display_name\":\"API token\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"model_kwargs\":{\"type\":\"code\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model_kwargs\",\"display_name\":\"Model Keyword Arguments\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"task\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"text2text-generation\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"text2text-generation\",\"text-generation\",\"summarization\"],\"name\":\"task\",\"display_name\":\"Task\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"LLM model from Hugging Face Inference API.\",\"base_classes\":[\"BaseLanguageModel\",\"Runnable\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"object\",\"BaseLLM\"],\"display_name\":\"Hugging Face Inference API\",\"documentation\":\"\",\"custom_fields\":{\"endpoint_url\":null,\"task\":null,\"huggingfacehub_api_token\":null,\"model_kwargs\":null},\"output_types\":[\"BaseLLM\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"ChatOpenAISpecs\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional, Union\\n\\nfrom langchain.llms import BaseLLM\\nfrom langchain_community.chat_models.openai import ChatOpenAI\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import BaseLanguageModel, NestedDict\\n\\n\\nclass ChatOpenAIComponent(CustomComponent):\\n display_name = \\\"ChatOpenAI\\\"\\n description = \\\"`OpenAI` Chat large language models API.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"max_tokens\\\": {\\n \\\"display_name\\\": \\\"Max Tokens\\\",\\n \\\"advanced\\\": False,\\n \\\"required\\\": False,\\n },\\n \\\"model_kwargs\\\": {\\n \\\"display_name\\\": \\\"Model Kwargs\\\",\\n \\\"advanced\\\": True,\\n \\\"required\\\": False,\\n },\\n \\\"model_name\\\": {\\n \\\"display_name\\\": \\\"Model Name\\\",\\n \\\"advanced\\\": False,\\n \\\"required\\\": False,\\n \\\"options\\\": [\\n \\\"gpt-4-turbo-preview\\\",\\n \\\"gpt-4-0125-preview\\\",\\n \\\"gpt-4-1106-preview\\\",\\n \\\"gpt-4-vision-preview\\\",\\n \\\"gpt-3.5-turbo-0125\\\",\\n \\\"gpt-3.5-turbo-1106\\\",\\n ],\\n },\\n \\\"openai_api_base\\\": {\\n \\\"display_name\\\": \\\"OpenAI API Base\\\",\\n \\\"advanced\\\": False,\\n \\\"required\\\": False,\\n \\\"info\\\": (\\n \\\"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\\\n\\\\n\\\"\\n \\\"You can change this to use other APIs like JinaChat, LocalAI and Prem.\\\"\\n ),\\n },\\n \\\"openai_api_key\\\": {\\n \\\"display_name\\\": \\\"OpenAI API Key\\\",\\n \\\"advanced\\\": False,\\n \\\"required\\\": False,\\n \\\"password\\\": True,\\n },\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"advanced\\\": False,\\n \\\"required\\\": False,\\n \\\"value\\\": 0.7,\\n },\\n }\\n\\n def build(\\n self,\\n max_tokens: Optional[int] = 256,\\n model_kwargs: NestedDict = {},\\n model_name: str = \\\"gpt-4-1106-preview\\\",\\n openai_api_base: Optional[str] = None,\\n openai_api_key: Optional[str] = None,\\n temperature: float = 0.7,\\n ) -> Union[BaseLanguageModel, BaseLLM]:\\n if not openai_api_base:\\n openai_api_base = \\\"https://api.openai.com/v1\\\"\\n return ChatOpenAI(\\n max_tokens=max_tokens,\\n model_kwargs=model_kwargs,\\n model=model_name,\\n base_url=openai_api_base,\\n api_key=openai_api_key,\\n temperature=temperature,\\n )\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"max_tokens\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":256,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"max_tokens\",\"display_name\":\"Max Tokens\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"model_kwargs\":{\"type\":\"NestedDict\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":{},\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model_kwargs\",\"display_name\":\"Model Kwargs\",\"advanced\":true,\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"model_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"gpt-4-1106-preview\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"gpt-4-turbo-preview\",\"gpt-4-0125-preview\",\"gpt-4-1106-preview\",\"gpt-4-vision-preview\",\"gpt-3.5-turbo-0125\",\"gpt-3.5-turbo-1106\"],\"name\":\"model_name\",\"display_name\":\"Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"openai_api_base\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"openai_api_base\",\"display_name\":\"OpenAI API Base\",\"advanced\":false,\"dynamic\":false,\"info\":\"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"openai_api_key\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":true,\"name\":\"openai_api_key\",\"display_name\":\"OpenAI API Key\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.7,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"`OpenAI` Chat large language models API.\",\"base_classes\":[\"BaseLanguageModel\",\"Runnable\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"object\",\"BaseLLM\"],\"display_name\":\"ChatOpenAI\",\"documentation\":\"\",\"custom_fields\":{\"max_tokens\":null,\"model_kwargs\":null,\"model_name\":null,\"openai_api_base\":null,\"openai_api_key\":null,\"temperature\":null},\"output_types\":[\"BaseLanguageModel\",\"BaseLLM\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"OllamaLLMSpecs\":{\"template\":{\"base_url\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"base_url\",\"display_name\":\"Base URL\",\"advanced\":false,\"dynamic\":false,\"info\":\"Endpoint of the Ollama API. Defaults to 'http://localhost:11434' if not specified.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import List, Optional\\n\\nfrom langchain.llms.base import BaseLLM\\nfrom langchain_community.llms.ollama import Ollama\\n\\nfrom langflow import CustomComponent\\n\\n\\nclass OllamaLLM(CustomComponent):\\n display_name = \\\"Ollama\\\"\\n description = \\\"Local LLM with Ollama.\\\"\\n\\n def build_config(self) -> dict:\\n return {\\n \\\"base_url\\\": {\\n \\\"display_name\\\": \\\"Base URL\\\",\\n \\\"info\\\": \\\"Endpoint of the Ollama API. Defaults to 'http://localhost:11434' if not specified.\\\",\\n },\\n \\\"model\\\": {\\n \\\"display_name\\\": \\\"Model Name\\\",\\n \\\"value\\\": \\\"llama2\\\",\\n \\\"info\\\": \\\"Refer to https://ollama.ai/library for more models.\\\",\\n },\\n \\\"temperature\\\": {\\n \\\"display_name\\\": \\\"Temperature\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"value\\\": 0.8,\\n \\\"info\\\": \\\"Controls the creativity of model responses.\\\",\\n },\\n \\\"mirostat\\\": {\\n \\\"display_name\\\": \\\"Mirostat\\\",\\n \\\"options\\\": [\\\"Disabled\\\", \\\"Mirostat\\\", \\\"Mirostat 2.0\\\"],\\n \\\"info\\\": \\\"Enable/disable Mirostat sampling for controlling perplexity.\\\",\\n \\\"value\\\": \\\"Disabled\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"mirostat_eta\\\": {\\n \\\"display_name\\\": \\\"Mirostat Eta\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Learning rate influencing the algorithm's response to feedback.\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"mirostat_tau\\\": {\\n \\\"display_name\\\": \\\"Mirostat Tau\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Controls balance between coherence and diversity.\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"num_ctx\\\": {\\n \\\"display_name\\\": \\\"Context Window Size\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"info\\\": \\\"Size of the context window for generating the next token.\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"num_gpu\\\": {\\n \\\"display_name\\\": \\\"Number of GPUs\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"info\\\": \\\"Number of GPUs to use for computation.\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"num_thread\\\": {\\n \\\"display_name\\\": \\\"Number of Threads\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"info\\\": \\\"Number of threads to use during computation.\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"repeat_last_n\\\": {\\n \\\"display_name\\\": \\\"Repeat Last N\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"info\\\": \\\"Sets how far back the model looks to prevent repetition.\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"repeat_penalty\\\": {\\n \\\"display_name\\\": \\\"Repeat Penalty\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Penalty for repetitions in generated text.\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"stop\\\": {\\n \\\"display_name\\\": \\\"Stop Tokens\\\",\\n \\\"info\\\": \\\"List of tokens to signal the model to stop generating text.\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"tfs_z\\\": {\\n \\\"display_name\\\": \\\"TFS Z\\\",\\n \\\"field_type\\\": \\\"float\\\",\\n \\\"info\\\": \\\"Tail free sampling to reduce impact of less probable tokens.\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"top_k\\\": {\\n \\\"display_name\\\": \\\"Top K\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"info\\\": \\\"Limits token selection to top K for reducing nonsense generation.\\\",\\n \\\"advanced\\\": True,\\n },\\n \\\"top_p\\\": {\\n \\\"display_name\\\": \\\"Top P\\\",\\n \\\"field_type\\\": \\\"int\\\",\\n \\\"info\\\": \\\"Works with top-k to control diversity of generated text.\\\",\\n \\\"advanced\\\": True,\\n },\\n }\\n\\n def build(\\n self,\\n base_url: Optional[str],\\n model: str,\\n temperature: Optional[float],\\n mirostat: Optional[str],\\n mirostat_eta: Optional[float] = None,\\n mirostat_tau: Optional[float] = None,\\n num_ctx: Optional[int] = None,\\n num_gpu: Optional[int] = None,\\n num_thread: Optional[int] = None,\\n repeat_last_n: Optional[int] = None,\\n repeat_penalty: Optional[float] = None,\\n stop: Optional[List[str]] = None,\\n tfs_z: Optional[float] = None,\\n top_k: Optional[int] = None,\\n top_p: Optional[int] = None,\\n ) -> BaseLLM:\\n if not base_url:\\n base_url = \\\"http://localhost:11434\\\"\\n\\n # Mapping mirostat settings to their corresponding values\\n mirostat_options = {\\\"Mirostat\\\": 1, \\\"Mirostat 2.0\\\": 2}\\n\\n # Default to 0 for 'Disabled'\\n mirostat_value = mirostat_options.get(mirostat, 0) # type: ignore\\n\\n # Set mirostat_eta and mirostat_tau to None if mirostat is disabled\\n if mirostat_value == 0:\\n mirostat_eta = None\\n mirostat_tau = None\\n\\n try:\\n llm = Ollama(\\n base_url=base_url,\\n model=model,\\n mirostat=mirostat_value,\\n mirostat_eta=mirostat_eta,\\n mirostat_tau=mirostat_tau,\\n num_ctx=num_ctx,\\n num_gpu=num_gpu,\\n num_thread=num_thread,\\n repeat_last_n=repeat_last_n,\\n repeat_penalty=repeat_penalty,\\n temperature=temperature,\\n stop=stop,\\n tfs_z=tfs_z,\\n top_k=top_k,\\n top_p=top_p,\\n )\\n\\n except Exception as e:\\n raise ValueError(\\\"Could not connect to Ollama.\\\") from e\\n\\n return llm\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"mirostat\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"Disabled\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"Disabled\",\"Mirostat\",\"Mirostat 2.0\"],\"name\":\"mirostat\",\"display_name\":\"Mirostat\",\"advanced\":true,\"dynamic\":false,\"info\":\"Enable/disable Mirostat sampling for controlling perplexity.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"mirostat_eta\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"mirostat_eta\",\"display_name\":\"Mirostat Eta\",\"advanced\":true,\"dynamic\":false,\"info\":\"Learning rate influencing the algorithm's response to feedback.\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"mirostat_tau\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"mirostat_tau\",\"display_name\":\"Mirostat Tau\",\"advanced\":true,\"dynamic\":false,\"info\":\"Controls balance between coherence and diversity.\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"model\":{\"type\":\"str\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"llama2\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"model\",\"display_name\":\"Model Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"Refer to https://ollama.ai/library for more models.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"num_ctx\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"num_ctx\",\"display_name\":\"Context Window Size\",\"advanced\":true,\"dynamic\":false,\"info\":\"Size of the context window for generating the next token.\",\"title_case\":false},\"num_gpu\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"num_gpu\",\"display_name\":\"Number of GPUs\",\"advanced\":true,\"dynamic\":false,\"info\":\"Number of GPUs to use for computation.\",\"title_case\":false},\"num_thread\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"num_thread\",\"display_name\":\"Number of Threads\",\"advanced\":true,\"dynamic\":false,\"info\":\"Number of threads to use during computation.\",\"title_case\":false},\"repeat_last_n\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"repeat_last_n\",\"display_name\":\"Repeat Last N\",\"advanced\":true,\"dynamic\":false,\"info\":\"Sets how far back the model looks to prevent repetition.\",\"title_case\":false},\"repeat_penalty\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"repeat_penalty\",\"display_name\":\"Repeat Penalty\",\"advanced\":true,\"dynamic\":false,\"info\":\"Penalty for repetitions in generated text.\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"stop\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"stop\",\"display_name\":\"Stop Tokens\",\"advanced\":true,\"dynamic\":false,\"info\":\"List of tokens to signal the model to stop generating text.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"temperature\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":0.8,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"temperature\",\"display_name\":\"Temperature\",\"advanced\":false,\"dynamic\":false,\"info\":\"Controls the creativity of model responses.\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"tfs_z\":{\"type\":\"float\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"tfs_z\",\"display_name\":\"TFS Z\",\"advanced\":true,\"dynamic\":false,\"info\":\"Tail free sampling to reduce impact of less probable tokens.\",\"rangeSpec\":{\"min\":-1.0,\"max\":1.0,\"step\":0.1},\"title_case\":false},\"top_k\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_k\",\"display_name\":\"Top K\",\"advanced\":true,\"dynamic\":false,\"info\":\"Limits token selection to top K for reducing nonsense generation.\",\"title_case\":false},\"top_p\":{\"type\":\"int\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"top_p\",\"display_name\":\"Top P\",\"advanced\":true,\"dynamic\":false,\"info\":\"Works with top-k to control diversity of generated text.\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Local LLM with Ollama.\",\"base_classes\":[\"BaseLanguageModel\",\"Runnable\",\"Generic\",\"RunnableSerializable\",\"Serializable\",\"object\",\"BaseLLM\"],\"display_name\":\"Ollama\",\"documentation\":\"\",\"custom_fields\":{\"base_url\":null,\"model\":null,\"temperature\":null,\"mirostat\":null,\"mirostat_eta\":null,\"mirostat_tau\":null,\"num_ctx\":null,\"num_gpu\":null,\"num_thread\":null,\"repeat_last_n\":null,\"repeat_penalty\":null,\"stop\":null,\"tfs_z\":null,\"top_k\":null,\"top_p\":null},\"output_types\":[\"BaseLLM\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true}},\"io\":{\"ChatOutput\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional, Union\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Text\\nfrom langflow.schema import Record\\n\\n\\nclass ChatOutput(CustomComponent):\\n display_name = \\\"Chat Output\\\"\\n description = \\\"Used to send a message to the chat.\\\"\\n\\n field_config = {\\n \\\"code\\\": {\\n \\\"show\\\": True,\\n }\\n }\\n\\n def build_config(self):\\n return {\\n \\\"message\\\": {\\\"input_types\\\": [\\\"Text\\\"], \\\"display_name\\\": \\\"Message\\\"},\\n \\\"sender\\\": {\\n \\\"options\\\": [\\\"Machine\\\", \\\"User\\\"],\\n \\\"display_name\\\": \\\"Sender Type\\\",\\n },\\n \\\"sender_name\\\": {\\\"display_name\\\": \\\"Sender Name\\\"},\\n \\\"session_id\\\": {\\n \\\"display_name\\\": \\\"Session ID\\\",\\n \\\"info\\\": \\\"Session ID of the chat history.\\\",\\n \\\"input_types\\\": [\\\"Text\\\"],\\n },\\n \\\"return_record\\\": {\\n \\\"display_name\\\": \\\"Return Record\\\",\\n \\\"info\\\": \\\"Return the message as a record containing the sender, sender_name, and session_id.\\\",\\n },\\n }\\n\\n def build(\\n self,\\n sender: Optional[str] = \\\"Machine\\\",\\n sender_name: Optional[str] = \\\"AI\\\",\\n session_id: Optional[str] = None,\\n message: Optional[str] = None,\\n return_record: Optional[bool] = False,\\n ) -> Union[Text, Record]:\\n if return_record:\\n if isinstance(message, Record):\\n # Update the data of the record\\n message.data[\\\"sender\\\"] = sender\\n message.data[\\\"sender_name\\\"] = sender_name\\n message.data[\\\"session_id\\\"] = session_id\\n else:\\n message = Record(\\n text=message,\\n data={\\n \\\"sender\\\": sender,\\n \\\"sender_name\\\": sender_name,\\n \\\"session_id\\\": session_id,\\n },\\n )\\n if not message:\\n message = \\\"\\\"\\n self.status = message\\n return message\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"message\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"message\",\"display_name\":\"Message\",\"advanced\":false,\"input_types\":[\"Text\",\"Text\"],\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"return_record\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"return_record\",\"display_name\":\"Return Record\",\"advanced\":false,\"dynamic\":false,\"info\":\"Return the message as a record containing the sender, sender_name, and session_id.\",\"title_case\":false},\"sender\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"Machine\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"Machine\",\"User\"],\"name\":\"sender\",\"display_name\":\"Sender Type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"sender_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"AI\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"sender_name\",\"display_name\":\"Sender Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"session_id\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"session_id\",\"display_name\":\"Session ID\",\"advanced\":false,\"input_types\":[\"Text\",\"Text\"],\"dynamic\":false,\"info\":\"Session ID of the chat history.\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Used to send a message to the chat.\",\"base_classes\":[\"Text\",\"object\",\"Record\"],\"display_name\":\"Chat Output\",\"documentation\":\"\",\"custom_fields\":{\"sender\":null,\"sender_name\":null,\"session_id\":null,\"message\":null,\"return_record\":null},\"output_types\":[\"Text\",\"Record\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"MessageHistory\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import List, Optional\\n\\nfrom langflow import CustomComponent\\nfrom langflow.memory import get_messages\\nfrom langflow.schema import Record\\n\\n\\nclass MessageHistoryComponent(CustomComponent):\\n display_name = \\\"Message History\\\"\\n description = \\\"Used to retrieve stored messages.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"sender\\\": {\\n \\\"options\\\": [\\\"Machine\\\", \\\"User\\\"],\\n \\\"display_name\\\": \\\"Sender Type\\\",\\n },\\n \\\"sender_name\\\": {\\\"display_name\\\": \\\"Sender Name\\\"},\\n \\\"file_path\\\": {\\n \\\"display_name\\\": \\\"File Path\\\",\\n \\\"info\\\": \\\"Path of the local JSON file to store the messages. It should be a unique path for each chat history.\\\",\\n },\\n \\\"n_messages\\\": {\\n \\\"display_name\\\": \\\"Number of Messages\\\",\\n \\\"info\\\": \\\"Number of messages to retrieve.\\\",\\n },\\n \\\"session_id\\\": {\\n \\\"display_name\\\": \\\"Session ID\\\",\\n \\\"info\\\": \\\"Session ID of the chat history.\\\",\\n \\\"input_types\\\": [\\\"Text\\\"],\\n },\\n }\\n\\n def build(\\n self,\\n sender: Optional[str] = None,\\n sender_name: Optional[str] = None,\\n session_id: Optional[str] = None,\\n n_messages: int = 5,\\n ) -> List[Record]:\\n messages = get_messages(\\n sender=sender,\\n sender_name=sender_name,\\n session_id=session_id,\\n limit=n_messages,\\n )\\n self.status = messages\\n return messages\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"n_messages\":{\"type\":\"int\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":5,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"n_messages\",\"display_name\":\"Number of Messages\",\"advanced\":false,\"dynamic\":false,\"info\":\"Number of messages to retrieve.\",\"title_case\":false},\"sender\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"Machine\",\"User\"],\"name\":\"sender\",\"display_name\":\"Sender Type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"sender_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"sender_name\",\"display_name\":\"Sender Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"session_id\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"session_id\",\"display_name\":\"Session ID\",\"advanced\":false,\"input_types\":[\"Text\",\"Text\"],\"dynamic\":false,\"info\":\"Session ID of the chat history.\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"Used to retrieve stored messages.\",\"base_classes\":[\"Record\"],\"display_name\":\"Message History\",\"documentation\":\"\",\"custom_fields\":{\"sender\":null,\"sender_name\":null,\"session_id\":null,\"n_messages\":null},\"output_types\":[\"Record\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"TextOutput\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Text\\n\\n\\nclass TextOutput(CustomComponent):\\n display_name = \\\"Text Output\\\"\\n description = \\\"Used to pass text output to the next component.\\\"\\n\\n field_config = {\\n \\\"value\\\": {\\\"display_name\\\": \\\"Value\\\"},\\n }\\n\\n def build(self, value: Optional[str] = \\\"\\\") -> Text:\\n self.status = value\\n if not value:\\n value = \\\"\\\"\\n return value\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"value\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"value\",\"display_name\":\"Value\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Used to pass text output to the next component.\",\"base_classes\":[\"Text\",\"object\"],\"display_name\":\"Text Output\",\"documentation\":\"\",\"custom_fields\":{\"value\":null},\"output_types\":[\"Text\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"StoreMessages\":{\"template\":{\"records\":{\"type\":\"Record\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"records\",\"display_name\":\"Records\",\"advanced\":false,\"dynamic\":false,\"info\":\"The list of records to store. Each record should contain the keys 'sender', 'sender_name', and 'session_id'.\",\"title_case\":false},\"texts\":{\"type\":\"Text\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"texts\",\"display_name\":\"Texts\",\"advanced\":false,\"dynamic\":false,\"info\":\"The list of texts to store. If records is not provided, texts must be provided.\",\"title_case\":false},\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import List, Optional\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Text\\nfrom langflow.memory import add_messages\\nfrom langflow.schema import Record\\n\\n\\nclass StoreMessages(CustomComponent):\\n display_name = \\\"Store Messages\\\"\\n description = \\\"Used to store messages.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"records\\\": {\\n \\\"display_name\\\": \\\"Records\\\",\\n \\\"info\\\": \\\"The list of records to store. Each record should contain the keys 'sender', 'sender_name', and 'session_id'.\\\",\\n },\\n \\\"texts\\\": {\\n \\\"display_name\\\": \\\"Texts\\\",\\n \\\"info\\\": \\\"The list of texts to store. If records is not provided, texts must be provided.\\\",\\n },\\n \\\"session_id\\\": {\\n \\\"display_name\\\": \\\"Session ID\\\",\\n \\\"info\\\": \\\"The session ID to store.\\\",\\n },\\n \\\"sender\\\": {\\n \\\"display_name\\\": \\\"Sender\\\",\\n \\\"info\\\": \\\"The sender to store.\\\",\\n },\\n \\\"sender_name\\\": {\\n \\\"display_name\\\": \\\"Sender Name\\\",\\n \\\"info\\\": \\\"The sender name to store.\\\",\\n },\\n }\\n\\n def build(\\n self,\\n records: Optional[List[Record]] = None,\\n texts: Optional[List[Text]] = None,\\n session_id: Optional[str] = None,\\n sender: Optional[str] = None,\\n sender_name: Optional[str] = None,\\n ) -> List[Record]:\\n # Records is the main way to store messages\\n # If records is not provided, we can use texts\\n # but we need to create the records from the texts\\n # and the other parameters\\n if not texts and not records:\\n raise ValueError(\\\"Either texts or records must be provided.\\\")\\n\\n if not records:\\n records = []\\n if not session_id or not sender or not sender_name:\\n raise ValueError(\\\"If passing texts, session_id, sender, and sender_name must be provided.\\\")\\n for text in texts:\\n record = Record(\\n text=text,\\n data={\\n \\\"session_id\\\": session_id,\\n \\\"sender\\\": sender,\\n \\\"sender_name\\\": sender_name,\\n },\\n )\\n records.append(record)\\n elif isinstance(records, Record):\\n records = [records]\\n\\n self.status = records\\n records = add_messages(records)\\n return records\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"sender\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"sender\",\"display_name\":\"Sender\",\"advanced\":false,\"dynamic\":false,\"info\":\"The sender to store.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"sender_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"sender_name\",\"display_name\":\"Sender Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"The sender name to store.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"session_id\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"session_id\",\"display_name\":\"Session ID\",\"advanced\":false,\"dynamic\":false,\"info\":\"The session ID to store.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Used to store messages.\",\"base_classes\":[\"Record\"],\"display_name\":\"Store Messages\",\"documentation\":\"\",\"custom_fields\":{\"records\":null,\"texts\":null,\"session_id\":null,\"sender\":null,\"sender_name\":null},\"output_types\":[\"Record\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"ChatInput\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langflow import CustomComponent\\nfrom langflow.schema import Record\\n\\n\\nclass ChatInput(CustomComponent):\\n display_name = \\\"Chat Input\\\"\\n description = \\\"Used to get user input from the chat.\\\"\\n\\n def build_config(self):\\n return {\\n \\\"message\\\": {\\n \\\"input_types\\\": [\\\"Text\\\"],\\n \\\"display_name\\\": \\\"Message\\\",\\n \\\"multiline\\\": True,\\n },\\n \\\"sender\\\": {\\n \\\"options\\\": [\\\"Machine\\\", \\\"User\\\"],\\n \\\"display_name\\\": \\\"Sender Type\\\",\\n },\\n \\\"sender_name\\\": {\\\"display_name\\\": \\\"Sender Name\\\"},\\n \\\"session_id\\\": {\\n \\\"display_name\\\": \\\"Session ID\\\",\\n \\\"info\\\": \\\"Session ID of the chat history.\\\",\\n },\\n \\\"return_record\\\": {\\n \\\"display_name\\\": \\\"Return Record\\\",\\n \\\"info\\\": \\\"Return the message as a record containing the sender, sender_name, and session_id.\\\",\\n },\\n }\\n\\n def build(\\n self,\\n sender: Optional[str] = \\\"User\\\",\\n sender_name: Optional[str] = \\\"User\\\",\\n message: Optional[str] = None,\\n session_id: Optional[str] = None,\\n return_record: Optional[bool] = False,\\n ) -> Record:\\n if return_record:\\n if isinstance(message, Record):\\n # Update the data of the record\\n message.data[\\\"sender\\\"] = sender\\n message.data[\\\"sender_name\\\"] = sender_name\\n message.data[\\\"session_id\\\"] = session_id\\n else:\\n message = Record(\\n text=message,\\n data={\\n \\\"sender\\\": sender,\\n \\\"sender_name\\\": sender_name,\\n \\\"session_id\\\": session_id,\\n },\\n )\\n if not message:\\n message = \\\"\\\"\\n self.status = message\\n return message\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"message\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"message\",\"display_name\":\"Message\",\"advanced\":false,\"input_types\":[\"Text\",\"Text\"],\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"return_record\":{\"type\":\"bool\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"return_record\",\"display_name\":\"Return Record\",\"advanced\":false,\"dynamic\":false,\"info\":\"Return the message as a record containing the sender, sender_name, and session_id.\",\"title_case\":false},\"sender\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":true,\"show\":true,\"multiline\":false,\"value\":\"User\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"options\":[\"Machine\",\"User\"],\"name\":\"sender\",\"display_name\":\"Sender Type\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"sender_name\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"User\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"sender_name\",\"display_name\":\"Sender Name\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"session_id\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"session_id\",\"display_name\":\"Session ID\",\"advanced\":false,\"dynamic\":false,\"info\":\"Session ID of the chat history.\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Used to get user input from the chat.\",\"base_classes\":[\"Record\"],\"display_name\":\"Chat Input\",\"documentation\":\"\",\"custom_fields\":{\"sender\":null,\"sender_name\":null,\"message\":null,\"session_id\":null,\"return_record\":null},\"output_types\":[\"Record\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true},\"TextInput\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from typing import Optional\\n\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Text\\n\\n\\nclass TextInput(CustomComponent):\\n display_name = \\\"Text Input\\\"\\n description = \\\"Used to pass text input to the next component.\\\"\\n\\n field_config = {\\n \\\"value\\\": {\\\"display_name\\\": \\\"Value\\\"},\\n }\\n\\n def build(self, value: Optional[str] = \\\"\\\") -> Text:\\n self.status = value\\n if not value:\\n value = \\\"\\\"\\n return value\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":false,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"value\":{\"type\":\"str\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"value\",\"display_name\":\"Value\",\"advanced\":false,\"dynamic\":false,\"info\":\"\",\"title_case\":false,\"input_types\":[\"Text\"]},\"_type\":\"CustomComponent\"},\"description\":\"Used to pass text input to the next component.\",\"base_classes\":[\"Text\",\"object\"],\"display_name\":\"Text Input\",\"documentation\":\"\",\"custom_fields\":{\"value\":null},\"output_types\":[\"Text\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true}},\"prompts\":{\"Prompt\":{\"template\":{\"code\":{\"type\":\"code\",\"required\":true,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":true,\"value\":\"from langchain_core.prompts import PromptTemplate\\nfrom langflow import CustomComponent\\nfrom langflow.field_typing import Prompt, TemplateField, Text\\n\\n\\nclass PromptComponent(CustomComponent):\\n display_name: str = \\\"Prompt\\\"\\n description: str = \\\"A component for creating prompts using templates\\\"\\n beta = True\\n\\n def build_config(self):\\n return {\\n \\\"template\\\": TemplateField(display_name=\\\"Template\\\"),\\n \\\"code\\\": TemplateField(advanced=True),\\n }\\n\\n def build(\\n self,\\n template: Prompt,\\n **kwargs,\\n ) -> Text:\\n prompt_template = PromptTemplate.from_template(template)\\n\\n attributes_to_check = [\\\"text\\\", \\\"page_content\\\"]\\n for key, value in kwargs.items():\\n for attribute in attributes_to_check:\\n if hasattr(value, attribute):\\n kwargs[key] = getattr(value, attribute)\\n\\n try:\\n formated_prompt = prompt_template.format(**kwargs)\\n except Exception as exc:\\n raise ValueError(f\\\"Error formatting prompt: {exc}\\\") from exc\\n self.status = f'Prompt: \\\"{formated_prompt}\\\"'\\n return formated_prompt\\n\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"code\",\"advanced\":true,\"dynamic\":true,\"info\":\"\",\"title_case\":false},\"template\":{\"type\":\"prompt\",\"required\":false,\"placeholder\":\"\",\"list\":false,\"show\":true,\"multiline\":false,\"value\":\"\",\"fileTypes\":[],\"file_path\":\"\",\"password\":false,\"name\":\"template\",\"display_name\":\"Template\",\"advanced\":false,\"input_types\":[\"Text\"],\"dynamic\":false,\"info\":\"\",\"title_case\":false},\"_type\":\"CustomComponent\"},\"description\":\"A component for creating prompts using templates\",\"base_classes\":[\"Text\",\"object\"],\"display_name\":\"Prompt\",\"documentation\":\"\",\"custom_fields\":{\"template\":null},\"output_types\":[\"Text\"],\"field_formatters\":{},\"pinned\":false,\"beta\":true}}}" }, - "cache": {}, - "timings": { "send": -1, "wait": -1, "receive": 0.743 } - } - ] - } - } \ No newline at end of file + "headersSize": -1, + "bodySize": -1, + "redirectURL": "" + }, + "cache": {}, + "timings": { "send": -1, "wait": -1, "receive": 2.771 } + }, + { + "startedDateTime": "2024-02-28T14:32:30.976Z", + "time": 0.753, + "request": { + "method": "GET", + "url": "http://localhost:3000/api/v1/store/check/", + "httpVersion": "HTTP/1.1", + "cookies": [], + "headers": [ + { "name": "Accept", "value": "application/json, text/plain, */*" }, + { "name": "Accept-Encoding", "value": "gzip, deflate, br, zstd" }, + { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, + { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMzg5ZmIyOS1kYWE2LTQwOGMtYjhjYi1iOGZmOGQxNzM0M2EiLCJleHAiOjE3NDA2NjY3NTB9.ef5W5jwNOeVzU3JZ7ylLYf2MLEJcVxC4-fF7EK9Ecdc" }, + { "name": "Connection", "value": "keep-alive" }, + { "name": "Cookie", "value": "access_token_lf=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMzg5ZmIyOS1kYWE2LTQwOGMtYjhjYi1iOGZmOGQxNzM0M2EiLCJleHAiOjE3NDA2NjY3NTB9.ef5W5jwNOeVzU3JZ7ylLYf2MLEJcVxC4-fF7EK9Ecdc" }, + { "name": "Host", "value": "localhost:3000" }, + { "name": "Referer", "value": "http://localhost:3000/" }, + { "name": "Sec-Fetch-Dest", "value": "empty" }, + { "name": "Sec-Fetch-Mode", "value": "cors" }, + { "name": "Sec-Fetch-Site", "value": "same-origin" }, + { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" }, + { "name": "sec-ch-ua", "value": "\"Chromium\";v=\"123\", \"Not:A-Brand\";v=\"8\"" }, + { "name": "sec-ch-ua-mobile", "value": "?0" }, + { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } + ], + "queryString": [], + "headersSize": -1, + "bodySize": -1 + }, + "response": { + "status": 200, + "statusText": "OK", + "httpVersion": "HTTP/1.1", + "cookies": [], + "headers": [ + { "name": "Access-Control-Allow-Origin", "value": "*" }, + { "name": "connection", "value": "close" }, + { "name": "content-length", "value": "16" }, + { "name": "content-type", "value": "application/json" }, + { "name": "date", "value": "Wed, 28 Feb 2024 14:32:30 GMT" }, + { "name": "server", "value": "uvicorn" } + ], + "content": { + "size": -1, + "mimeType": "application/json", + "text": "{\"enabled\":true}" + }, + "headersSize": -1, + "bodySize": -1, + "redirectURL": "" + }, + "cache": {}, + "timings": { "send": -1, "wait": -1, "receive": 0.753 } + }, + { + "startedDateTime": "2024-02-28T14:32:30.976Z", + "time": 0.525, + "request": { + "method": "GET", + "url": "http://localhost:3000/api/v1/store/check/api_key", + "httpVersion": "HTTP/1.1", + "cookies": [], + "headers": [ + { "name": "Accept", "value": "application/json, text/plain, */*" }, + { "name": "Accept-Encoding", "value": "gzip, deflate, br, zstd" }, + { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, + { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMzg5ZmIyOS1kYWE2LTQwOGMtYjhjYi1iOGZmOGQxNzM0M2EiLCJleHAiOjE3NDA2NjY3NTB9.ef5W5jwNOeVzU3JZ7ylLYf2MLEJcVxC4-fF7EK9Ecdc" }, + { "name": "Connection", "value": "keep-alive" }, + { "name": "Cookie", "value": "access_token_lf=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMzg5ZmIyOS1kYWE2LTQwOGMtYjhjYi1iOGZmOGQxNzM0M2EiLCJleHAiOjE3NDA2NjY3NTB9.ef5W5jwNOeVzU3JZ7ylLYf2MLEJcVxC4-fF7EK9Ecdc" }, + { "name": "Host", "value": "localhost:3000" }, + { "name": "Referer", "value": "http://localhost:3000/" }, + { "name": "Sec-Fetch-Dest", "value": "empty" }, + { "name": "Sec-Fetch-Mode", "value": "cors" }, + { "name": "Sec-Fetch-Site", "value": "same-origin" }, + { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" }, + { "name": "sec-ch-ua", "value": "\"Chromium\";v=\"123\", \"Not:A-Brand\";v=\"8\"" }, + { "name": "sec-ch-ua-mobile", "value": "?0" }, + { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } + ], + "queryString": [], + "headersSize": -1, + "bodySize": -1 + }, + "response": { + "status": 200, + "statusText": "OK", + "httpVersion": "HTTP/1.1", + "cookies": [], + "headers": [ + { "name": "Access-Control-Allow-Origin", "value": "*" }, + { "name": "connection", "value": "close" }, + { "name": "content-length", "value": "38" }, + { "name": "content-type", "value": "application/json" }, + { "name": "date", "value": "Wed, 28 Feb 2024 14:32:30 GMT" }, + { "name": "server", "value": "uvicorn" } + ], + "content": { + "size": -1, + "mimeType": "application/json", + "text": "{\"has_api_key\":false,\"is_valid\":false}" + }, + "headersSize": -1, + "bodySize": -1, + "redirectURL": "" + }, + "cache": {}, + "timings": { "send": -1, "wait": -1, "receive": 0.525 } + }, + { + "startedDateTime": "2024-02-28T14:32:30.976Z", + "time": 0.658, + "request": { + "method": "GET", + "url": "http://localhost:3000/api/v1/auto_login", + "httpVersion": "HTTP/1.1", + "cookies": [], + "headers": [ + { "name": "Accept", "value": "application/json, text/plain, */*" }, + { "name": "Accept-Encoding", "value": "gzip, deflate, br, zstd" }, + { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, + { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMzg5ZmIyOS1kYWE2LTQwOGMtYjhjYi1iOGZmOGQxNzM0M2EiLCJleHAiOjE3NDA2NjY3NTB9.ef5W5jwNOeVzU3JZ7ylLYf2MLEJcVxC4-fF7EK9Ecdc" }, + { "name": "Connection", "value": "keep-alive" }, + { "name": "Cookie", "value": "access_token_lf=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMzg5ZmIyOS1kYWE2LTQwOGMtYjhjYi1iOGZmOGQxNzM0M2EiLCJleHAiOjE3NDA2NjY3NTB9.ef5W5jwNOeVzU3JZ7ylLYf2MLEJcVxC4-fF7EK9Ecdc" }, + { "name": "Host", "value": "localhost:3000" }, + { "name": "Referer", "value": "http://localhost:3000/" }, + { "name": "Sec-Fetch-Dest", "value": "empty" }, + { "name": "Sec-Fetch-Mode", "value": "cors" }, + { "name": "Sec-Fetch-Site", "value": "same-origin" }, + { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" }, + { "name": "sec-ch-ua", "value": "\"Chromium\";v=\"123\", \"Not:A-Brand\";v=\"8\"" }, + { "name": "sec-ch-ua-mobile", "value": "?0" }, + { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } + ], + "queryString": [], + "headersSize": -1, + "bodySize": -1 + }, + "response": { + "status": 200, + "statusText": "OK", + "httpVersion": "HTTP/1.1", + "cookies": [], + "headers": [ + { "name": "Access-Control-Allow-Origin", "value": "*" }, + { "name": "connection", "value": "close" }, + { "name": "content-length", "value": "227" }, + { "name": "content-type", "value": "application/json" }, + { "name": "date", "value": "Wed, 28 Feb 2024 14:32:30 GMT" }, + { "name": "server", "value": "uvicorn" }, + { "name": "set-cookie", "value": "access_token_lf=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMzg5ZmIyOS1kYWE2LTQwOGMtYjhjYi1iOGZmOGQxNzM0M2EiLCJleHAiOjE3NDA2NjY3NTB9.ef5W5jwNOeVzU3JZ7ylLYf2MLEJcVxC4-fF7EK9Ecdc; Path=/; SameSite=none; Secure" } + ], + "content": { + "size": -1, + "mimeType": "application/json", + "text": "{\"access_token\":\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMzg5ZmIyOS1kYWE2LTQwOGMtYjhjYi1iOGZmOGQxNzM0M2EiLCJleHAiOjE3NDA2NjY3NTB9.ef5W5jwNOeVzU3JZ7ylLYf2MLEJcVxC4-fF7EK9Ecdc\",\"refresh_token\":null,\"token_type\":\"bearer\"}" + }, + "headersSize": -1, + "bodySize": -1, + "redirectURL": "" + }, + "cache": {}, + "timings": { "send": -1, "wait": -1, "receive": 0.658 } + }, + { + "startedDateTime": "2024-02-28T14:32:31.023Z", + "time": 0.787, + "request": { + "method": "GET", + "url": "http://localhost:3000/api/v1/users/whoami", + "httpVersion": "HTTP/1.1", + "cookies": [], + "headers": [ + { "name": "Accept", "value": "application/json, text/plain, */*" }, + { "name": "Accept-Encoding", "value": "gzip, deflate, br, zstd" }, + { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, + { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMzg5ZmIyOS1kYWE2LTQwOGMtYjhjYi1iOGZmOGQxNzM0M2EiLCJleHAiOjE3NDA2NjY3NTB9.ef5W5jwNOeVzU3JZ7ylLYf2MLEJcVxC4-fF7EK9Ecdc" }, + { "name": "Connection", "value": "keep-alive" }, + { "name": "Cookie", "value": "access_token_lf=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMzg5ZmIyOS1kYWE2LTQwOGMtYjhjYi1iOGZmOGQxNzM0M2EiLCJleHAiOjE3NDA2NjY3NTB9.ef5W5jwNOeVzU3JZ7ylLYf2MLEJcVxC4-fF7EK9Ecdc" }, + { "name": "Host", "value": "localhost:3000" }, + { "name": "Referer", "value": "http://localhost:3000/" }, + { "name": "Sec-Fetch-Dest", "value": "empty" }, + { "name": "Sec-Fetch-Mode", "value": "cors" }, + { "name": "Sec-Fetch-Site", "value": "same-origin" }, + { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" }, + { "name": "sec-ch-ua", "value": "\"Chromium\";v=\"123\", \"Not:A-Brand\";v=\"8\"" }, + { "name": "sec-ch-ua-mobile", "value": "?0" }, + { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } + ], + "queryString": [], + "headersSize": -1, + "bodySize": -1 + }, + "response": { + "status": 200, + "statusText": "OK", + "httpVersion": "HTTP/1.1", + "cookies": [], + "headers": [ + { "name": "Access-Control-Allow-Origin", "value": "*" }, + { "name": "connection", "value": "close" }, + { "name": "content-length", "value": "253" }, + { "name": "content-type", "value": "application/json" }, + { "name": "date", "value": "Wed, 28 Feb 2024 14:32:30 GMT" }, + { "name": "server", "value": "uvicorn" } + ], + "content": { + "size": -1, + "mimeType": "application/json", + "text": "{\"id\":\"0389fb29-daa6-408c-b8cb-b8ff8d17343a\",\"username\":\"langflow\",\"profile_image\":null,\"is_active\":true,\"is_superuser\":true,\"create_at\":\"2024-02-28T14:31:41.362911\",\"updated_at\":\"2024-02-28T14:32:30.982826\",\"last_login_at\":\"2024-02-28T14:32:30.982478\"}" + }, + "headersSize": -1, + "bodySize": -1, + "redirectURL": "" + }, + "cache": {}, + "timings": { "send": -1, "wait": -1, "receive": 0.787 } + }, + { + "startedDateTime": "2024-02-28T14:32:32.479Z", + "time": 0.836, + "request": { + "method": "GET", + "url": "http://localhost:3000/api/v1/flows/", + "httpVersion": "HTTP/1.1", + "cookies": [], + "headers": [ + { "name": "Accept", "value": "application/json, text/plain, */*" }, + { "name": "Accept-Encoding", "value": "gzip, deflate, br, zstd" }, + { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, + { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMzg5ZmIyOS1kYWE2LTQwOGMtYjhjYi1iOGZmOGQxNzM0M2EiLCJleHAiOjE3NDA2NjY3NTB9.ef5W5jwNOeVzU3JZ7ylLYf2MLEJcVxC4-fF7EK9Ecdc" }, + { "name": "Connection", "value": "keep-alive" }, + { "name": "Cookie", "value": "access_token_lf=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMzg5ZmIyOS1kYWE2LTQwOGMtYjhjYi1iOGZmOGQxNzM0M2EiLCJleHAiOjE3NDA2NjY3NTB9.ef5W5jwNOeVzU3JZ7ylLYf2MLEJcVxC4-fF7EK9Ecdc" }, + { "name": "Host", "value": "localhost:3000" }, + { "name": "Referer", "value": "http://localhost:3000/flows" }, + { "name": "Sec-Fetch-Dest", "value": "empty" }, + { "name": "Sec-Fetch-Mode", "value": "cors" }, + { "name": "Sec-Fetch-Site", "value": "same-origin" }, + { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" }, + { "name": "sec-ch-ua", "value": "\"Chromium\";v=\"123\", \"Not:A-Brand\";v=\"8\"" }, + { "name": "sec-ch-ua-mobile", "value": "?0" }, + { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } + ], + "queryString": [], + "headersSize": -1, + "bodySize": -1 + }, + "response": { + "status": 200, + "statusText": "OK", + "httpVersion": "HTTP/1.1", + "cookies": [], + "headers": [ + { "name": "Access-Control-Allow-Origin", "value": "*" }, + { "name": "connection", "value": "close" }, + { "name": "content-length", "value": "2" }, + { "name": "content-type", "value": "application/json" }, + { "name": "date", "value": "Wed, 28 Feb 2024 14:32:31 GMT" }, + { "name": "server", "value": "uvicorn" } + ], + "content": { + "size": -1, + "mimeType": "application/json", + "text": "[]" + }, + "headersSize": -1, + "bodySize": -1, + "redirectURL": "" + }, + "cache": {}, + "timings": { "send": -1, "wait": -1, "receive": 0.836 } + }, + { + "startedDateTime": "2024-02-28T14:32:36.617Z", + "time": 1.679, + "request": { + "method": "POST", + "url": "http://localhost:3000/api/v1/flows/", + "httpVersion": "HTTP/1.1", + "cookies": [], + "headers": [ + { "name": "Accept", "value": "application/json, text/plain, */*" }, + { "name": "Accept-Encoding", "value": "gzip, deflate, br, zstd" }, + { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, + { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMzg5ZmIyOS1kYWE2LTQwOGMtYjhjYi1iOGZmOGQxNzM0M2EiLCJleHAiOjE3NDA2NjY3NTB9.ef5W5jwNOeVzU3JZ7ylLYf2MLEJcVxC4-fF7EK9Ecdc" }, + { "name": "Connection", "value": "keep-alive" }, + { "name": "Content-Length", "value": "170" }, + { "name": "Content-Type", "value": "application/json" }, + { "name": "Cookie", "value": "access_token_lf=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMzg5ZmIyOS1kYWE2LTQwOGMtYjhjYi1iOGZmOGQxNzM0M2EiLCJleHAiOjE3NDA2NjY3NTB9.ef5W5jwNOeVzU3JZ7ylLYf2MLEJcVxC4-fF7EK9Ecdc" }, + { "name": "Host", "value": "localhost:3000" }, + { "name": "Origin", "value": "http://localhost:3000" }, + { "name": "Referer", "value": "http://localhost:3000/flows" }, + { "name": "Sec-Fetch-Dest", "value": "empty" }, + { "name": "Sec-Fetch-Mode", "value": "cors" }, + { "name": "Sec-Fetch-Site", "value": "same-origin" }, + { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" }, + { "name": "sec-ch-ua", "value": "\"Chromium\";v=\"123\", \"Not:A-Brand\";v=\"8\"" }, + { "name": "sec-ch-ua-mobile", "value": "?0" }, + { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } + ], + "queryString": [], + "headersSize": -1, + "bodySize": -1, + "postData": { + "mimeType": "application/json", + "text": "{\"name\":\"Untitled document\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"description\":\"Harness the Power of Conversational AI.\",\"is_component\":false}", + "params": [] + } + }, + "response": { + "status": 201, + "statusText": "Created", + "httpVersion": "HTTP/1.1", + "cookies": [], + "headers": [ + { "name": "access-control-allow-credentials", "value": "true" }, + { "name": "access-control-allow-origin", "value": "http://localhost:3000" }, + { "name": "connection", "value": "close" }, + { "name": "content-length", "value": "319" }, + { "name": "content-type", "value": "application/json" }, + { "name": "date", "value": "Wed, 28 Feb 2024 14:32:35 GMT" }, + { "name": "server", "value": "uvicorn" }, + { "name": "vary", "value": "Origin" } + ], + "content": { + "size": -1, + "mimeType": "application/json", + "text": "{\"name\":\"Untitled document\",\"description\":\"Harness the Power of Conversational AI.\",\"data\":{\"nodes\":[],\"edges\":[],\"viewport\":{\"zoom\":1,\"x\":0,\"y\":0}},\"is_component\":false,\"updated_at\":\"2024-02-28T14:32:36.621261\",\"folder\":null,\"id\":\"b3aad40d-cf3b-49d2-804f-bfa33b70beef\",\"user_id\":\"0389fb29-daa6-408c-b8cb-b8ff8d17343a\"}" + }, + "headersSize": -1, + "bodySize": -1, + "redirectURL": "" + }, + "cache": {}, + "timings": { "send": -1, "wait": -1, "receive": 1.679 } + }, + { + "startedDateTime": "2024-02-28T14:32:36.774Z", + "time": 1.023, + "request": { + "method": "GET", + "url": "http://localhost:3000/api/v1/monitor/builds?flow_id=b3aad40d-cf3b-49d2-804f-bfa33b70beef", + "httpVersion": "HTTP/1.1", + "cookies": [], + "headers": [ + { "name": "Accept", "value": "application/json, text/plain, */*" }, + { "name": "Accept-Encoding", "value": "gzip, deflate, br, zstd" }, + { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, + { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMzg5ZmIyOS1kYWE2LTQwOGMtYjhjYi1iOGZmOGQxNzM0M2EiLCJleHAiOjE3NDA2NjY3NTB9.ef5W5jwNOeVzU3JZ7ylLYf2MLEJcVxC4-fF7EK9Ecdc" }, + { "name": "Connection", "value": "keep-alive" }, + { "name": "Cookie", "value": "access_token_lf=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMzg5ZmIyOS1kYWE2LTQwOGMtYjhjYi1iOGZmOGQxNzM0M2EiLCJleHAiOjE3NDA2NjY3NTB9.ef5W5jwNOeVzU3JZ7ylLYf2MLEJcVxC4-fF7EK9Ecdc" }, + { "name": "Host", "value": "localhost:3000" }, + { "name": "Referer", "value": "http://localhost:3000/flow/b3aad40d-cf3b-49d2-804f-bfa33b70beef" }, + { "name": "Sec-Fetch-Dest", "value": "empty" }, + { "name": "Sec-Fetch-Mode", "value": "cors" }, + { "name": "Sec-Fetch-Site", "value": "same-origin" }, + { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" }, + { "name": "sec-ch-ua", "value": "\"Chromium\";v=\"123\", \"Not:A-Brand\";v=\"8\"" }, + { "name": "sec-ch-ua-mobile", "value": "?0" }, + { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } + ], + "queryString": [ + { + "name": "flow_id", + "value": "b3aad40d-cf3b-49d2-804f-bfa33b70beef" + } + ], + "headersSize": -1, + "bodySize": -1 + }, + "response": { + "status": 200, + "statusText": "OK", + "httpVersion": "HTTP/1.1", + "cookies": [], + "headers": [ + { "name": "Access-Control-Allow-Origin", "value": "*" }, + { "name": "connection", "value": "close" }, + { "name": "content-length", "value": "20" }, + { "name": "content-type", "value": "application/json" }, + { "name": "date", "value": "Wed, 28 Feb 2024 14:32:35 GMT" }, + { "name": "server", "value": "uvicorn" } + ], + "content": { + "size": -1, + "mimeType": "application/json", + "text": "{\"vertex_builds\":{}}" + }, + "headersSize": -1, + "bodySize": -1, + "redirectURL": "" + }, + "cache": {}, + "timings": { "send": -1, "wait": -1, "receive": 1.023 } + }, + { + "startedDateTime": "2024-02-28T14:32:49.526Z", + "time": 0.977, + "request": { + "method": "DELETE", + "url": "http://localhost:3000/api/v1/flows/b3aad40d-cf3b-49d2-804f-bfa33b70beef", + "httpVersion": "HTTP/1.1", + "cookies": [], + "headers": [ + { "name": "Accept", "value": "application/json, text/plain, */*" }, + { "name": "Accept-Encoding", "value": "gzip, deflate, br, zstd" }, + { "name": "Accept-Language", "value": "en-US,en;q=0.9" }, + { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMzg5ZmIyOS1kYWE2LTQwOGMtYjhjYi1iOGZmOGQxNzM0M2EiLCJleHAiOjE3NDA2NjY3NTB9.ef5W5jwNOeVzU3JZ7ylLYf2MLEJcVxC4-fF7EK9Ecdc" }, + { "name": "Connection", "value": "keep-alive" }, + { "name": "Cookie", "value": "access_token_lf=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIwMzg5ZmIyOS1kYWE2LTQwOGMtYjhjYi1iOGZmOGQxNzM0M2EiLCJleHAiOjE3NDA2NjY3NTB9.ef5W5jwNOeVzU3JZ7ylLYf2MLEJcVxC4-fF7EK9Ecdc" }, + { "name": "Host", "value": "localhost:3000" }, + { "name": "Origin", "value": "http://localhost:3000" }, + { "name": "Referer", "value": "http://localhost:3000/flow/b3aad40d-cf3b-49d2-804f-bfa33b70beef" }, + { "name": "Sec-Fetch-Dest", "value": "empty" }, + { "name": "Sec-Fetch-Mode", "value": "cors" }, + { "name": "Sec-Fetch-Site", "value": "same-origin" }, + { "name": "User-Agent", "value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" }, + { "name": "sec-ch-ua", "value": "\"Chromium\";v=\"123\", \"Not:A-Brand\";v=\"8\"" }, + { "name": "sec-ch-ua-mobile", "value": "?0" }, + { "name": "sec-ch-ua-platform", "value": "\"Linux\"" } + ], + "queryString": [], + "headersSize": -1, + "bodySize": -1 + }, + "response": { + "status": 200, + "statusText": "OK", + "httpVersion": "HTTP/1.1", + "cookies": [], + "headers": [ + { "name": "access-control-allow-credentials", "value": "true" }, + { "name": "access-control-allow-origin", "value": "http://localhost:3000" }, + { "name": "connection", "value": "close" }, + { "name": "content-length", "value": "39" }, + { "name": "content-type", "value": "application/json" }, + { "name": "date", "value": "Wed, 28 Feb 2024 14:32:48 GMT" }, + { "name": "server", "value": "uvicorn" }, + { "name": "vary", "value": "Origin" } + ], + "content": { + "size": -1, + "mimeType": "application/json", + "text": "{\"message\":\"Flow deleted successfully\"}" + }, + "headersSize": -1, + "bodySize": -1, + "redirectURL": "" + }, + "cache": {}, + "timings": { "send": -1, "wait": -1, "receive": 0.977 } + } + ] + } +} \ No newline at end of file diff --git a/src/frontend/index.html b/src/frontend/index.html index 8c21f0124..d4b03effb 100644 --- a/src/frontend/index.html +++ b/src/frontend/index.html @@ -1,16 +1,19 @@ - - - - + + + + - + Langflow - - + + -

+
- + diff --git a/src/frontend/package-lock.json b/src/frontend/package-lock.json index 2bfc05143..971c9eee1 100644 --- a/src/frontend/package-lock.json +++ b/src/frontend/package-lock.json @@ -8,12 +8,8 @@ "name": "langflow", "version": "0.1.2", "dependencies": { - "@emotion/react": "^11.11.1", - "@emotion/styled": "^11.11.0", "@headlessui/react": "^1.7.17", - "@heroicons/react": "^2.0.18", - "@mui/material": "^5.14.7", - "@preact/signals-react": "^2.0.0", + "@million/lint": "^0.0.73", "@radix-ui/react-accordion": "^1.1.2", "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-dialog": "^1.0.4", @@ -24,7 +20,7 @@ "@radix-ui/react-menubar": "^1.0.3", "@radix-ui/react-popover": "^1.0.6", "@radix-ui/react-progress": "^1.0.3", - "@radix-ui/react-select": "^1.2.2", + "@radix-ui/react-select": "^2.0.0", "@radix-ui/react-separator": "^1.0.3", "@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-switch": "^1.0.3", @@ -34,31 +30,31 @@ "@tailwindcss/forms": "^0.5.6", "@tailwindcss/line-clamp": "^0.4.4", "@types/axios": "^0.14.0", - "accordion": "^3.0.2", "ace-builds": "^1.24.1", - "add": "^2.0.6", "ansi-to-html": "^0.7.2", "axios": "^1.5.0", "base64-js": "^1.5.1", "class-variance-authority": "^0.6.1", "clsx": "^1.2.1", + "cmdk": "^1.0.0", "dompurify": "^3.0.5", "esbuild": "^0.17.19", + "framer-motion": "^11.0.6", "lodash": "^4.17.21", - "lucide-react": "^0.233.0", + "lucide-react": "^0.331.0", + "million": "^3.0.6", "moment": "^2.29.4", + "playwright": "^1.42.0", "react": "^18.2.0", "react-ace": "^10.1.0", "react-cookie": "^4.1.1", "react-dom": "^18.2.0", "react-error-boundary": "^4.0.11", - "react-icons": "^4.10.1", + "react-icons": "^5.0.1", "react-laag": "^2.0.5", "react-markdown": "^8.0.7", "react-router-dom": "^6.15.0", "react-syntax-highlighter": "^15.5.0", - "react-tabs": "^6.0.2", - "react-tooltip": "^5.21.1", "react18-json-view": "^0.2.3", "reactflow": "^11.9.2", "rehype-mathjax": "^4.0.3", @@ -66,8 +62,6 @@ "remark-math": "^5.1.1", "shadcn-ui": "^0.2.3", "short-unique-id": "^4.4.4", - "switch": "^0.0.0", - "table": "^6.8.1", "tailwind-merge": "^1.14.0", "tailwindcss-animate": "^1.0.7", "uuid": "^9.0.0", @@ -76,7 +70,7 @@ "zustand": "^4.4.7" }, "devDependencies": { - "@playwright/test": "^1.38.0", + "@playwright/test": "^1.42.0", "@swc/cli": "^0.1.62", "@swc/core": "^1.3.80", "@tailwindcss/typography": "^0.5.9", @@ -92,16 +86,29 @@ "@vitejs/plugin-react-swc": "^3.3.2", "autoprefixer": "^10.4.15", "daisyui": "^4.0.4", + "eslint": "^8.57.0", + "eslint-plugin-node": "^11.1.0", "postcss": "^8.4.29", "prettier": "^2.8.8", "prettier-plugin-organize-imports": "^3.2.3", "prettier-plugin-tailwindcss": "^0.3.0", "pretty-quick": "^3.1.3", "tailwindcss": "^3.3.3", + "tailwindcss-dotted-background": "^1.1.0", "typescript": "^5.2.2", + "ua-parser-js": "^1.0.37", "vite": "^4.5.2" } }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@adobe/css-tools": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.3.tgz", @@ -120,12 +127,12 @@ } }, "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -146,104 +153,40 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/code-frame/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/code-frame/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/code-frame/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/compat-data": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", - "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.1.tgz", + "integrity": "sha512-Pc65opHDliVpRHuKfzI+gSA4zcgr65O4cl64fFJIWEEh8JoHIHh0Oez1Eo8Arz8zq/JhgKodQaxEwUPRtZylVA==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", - "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.3.tgz", + "integrity": "sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ==", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.1", "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.9", - "@babel/parser": "^7.23.9", - "@babel/template": "^7.23.9", - "@babel/traverse": "^7.23.9", - "@babel/types": "^7.23.9", + "@babel/helpers": "^7.24.1", + "@babel/parser": "^7.24.1", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -258,27 +201,14 @@ "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/core/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@babel/generator": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", - "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.1.tgz", + "integrity": "sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A==", "dependencies": { - "@babel/types": "^7.23.6", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.24.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" }, "engines": { @@ -300,27 +230,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, "node_modules/@babel/helper-environment-visitor": { "version": "7.22.20", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", @@ -353,11 +262,11 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", "dependencies": { - "@babel/types": "^7.22.15" + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -404,9 +313,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", "engines": { "node": ">=6.9.0" } @@ -428,99 +337,36 @@ } }, "node_modules/@babel/helpers": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", - "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.1.tgz", + "integrity": "sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg==", "dependencies": { - "@babel/template": "^7.23.9", - "@babel/traverse": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", + "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/parser": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", - "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz", + "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==", "bin": { "parser": "bin/babel-parser.js" }, @@ -529,9 +375,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz", - "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.1.tgz", + "integrity": "sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -540,31 +386,31 @@ } }, "node_modules/@babel/template": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", - "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", "dependencies": { "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", - "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", + "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", + "@babel/code-frame": "^7.24.1", + "@babel/generator": "^7.24.1", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9", + "@babel/parser": "^7.24.1", + "@babel/types": "^7.24.0", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -573,9 +419,9 @@ } }, "node_modules/@babel/types": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", - "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", "dependencies": { "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", @@ -585,139 +431,21 @@ "node": ">=6.9.0" } }, - "node_modules/@emotion/babel-plugin": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", - "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", - "dependencies": { - "@babel/helper-module-imports": "^7.16.7", - "@babel/runtime": "^7.18.3", - "@emotion/hash": "^0.9.1", - "@emotion/memoize": "^0.8.1", - "@emotion/serialize": "^1.1.2", - "babel-plugin-macros": "^3.1.0", - "convert-source-map": "^1.5.0", - "escape-string-regexp": "^4.0.0", - "find-root": "^1.1.0", - "source-map": "^0.5.7", - "stylis": "4.2.0" + "node_modules/@esbuild/aix-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@emotion/cache": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", - "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", - "dependencies": { - "@emotion/memoize": "^0.8.1", - "@emotion/sheet": "^1.2.2", - "@emotion/utils": "^1.2.1", - "@emotion/weak-memoize": "^0.3.1", - "stylis": "4.2.0" - } - }, - "node_modules/@emotion/hash": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", - "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" - }, - "node_modules/@emotion/is-prop-valid": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", - "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", - "dependencies": { - "@emotion/memoize": "^0.8.1" - } - }, - "node_modules/@emotion/memoize": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", - "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" - }, - "node_modules/@emotion/react": { - "version": "11.11.3", - "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.3.tgz", - "integrity": "sha512-Cnn0kuq4DoONOMcnoVsTOR8E+AdnKFf//6kUWc4LCdnxj31pZWn7rIULd6Y7/Js1PiPHzn7SKCM9vB/jBni8eA==", - "dependencies": { - "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.11.0", - "@emotion/cache": "^11.11.0", - "@emotion/serialize": "^1.1.3", - "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", - "@emotion/utils": "^1.2.1", - "@emotion/weak-memoize": "^0.3.1", - "hoist-non-react-statics": "^3.3.1" - }, - "peerDependencies": { - "react": ">=16.8.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@emotion/serialize": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.3.tgz", - "integrity": "sha512-iD4D6QVZFDhcbH0RAG1uVu1CwVLMWUkCvAqqlewO/rxf8+87yIBAlt4+AxMiiKPLs5hFc0owNk/sLLAOROw3cA==", - "dependencies": { - "@emotion/hash": "^0.9.1", - "@emotion/memoize": "^0.8.1", - "@emotion/unitless": "^0.8.1", - "@emotion/utils": "^1.2.1", - "csstype": "^3.0.2" - } - }, - "node_modules/@emotion/sheet": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", - "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" - }, - "node_modules/@emotion/styled": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.0.tgz", - "integrity": "sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==", - "dependencies": { - "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.11.0", - "@emotion/is-prop-valid": "^1.2.1", - "@emotion/serialize": "^1.1.2", - "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", - "@emotion/utils": "^1.2.1" - }, - "peerDependencies": { - "@emotion/react": "^11.0.0-rc.0", - "react": ">=16.8.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@emotion/unitless": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", - "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" - }, - "node_modules/@emotion/use-insertion-effect-with-fallbacks": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", - "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", - "peerDependencies": { - "react": ">=16.8.0" - } - }, - "node_modules/@emotion/utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", - "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" - }, - "node_modules/@emotion/weak-memoize": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", - "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" - }, "node_modules/@esbuild/android-arm": { "version": "0.17.19", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz", @@ -1048,6 +776,99 @@ "node": ">=12" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/@floating-ui/core": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.0.tgz", @@ -1057,12 +878,12 @@ } }, "node_modules/@floating-ui/dom": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.1.tgz", - "integrity": "sha512-iA8qE43/H5iGozC3W0YSnVSW42Vh522yyM1gj+BqRwVsTNOyr231PsXDaV04yT39PsO0QL2QpbI/M0ZaLUQgRQ==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.3.tgz", + "integrity": "sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==", "dependencies": { - "@floating-ui/core": "^1.6.0", - "@floating-ui/utils": "^0.2.1" + "@floating-ui/core": "^1.0.0", + "@floating-ui/utils": "^0.2.0" } }, "node_modules/@floating-ui/react-dom": { @@ -1098,14 +919,61 @@ "react-dom": "^16 || ^17 || ^18" } }, - "node_modules/@heroicons/react": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.1.1.tgz", - "integrity": "sha512-JyyN9Lo66kirbCMuMMRPtJxtKJoIsXKS569ebHGGRKbl8s4CtUfLnyKJxteA+vIKySocO4s1SkTkGS4xtG/yEA==", - "peerDependencies": { - "react": ">= 16" + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" } }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "dev": true + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -1122,52 +990,56 @@ "node": ">=12" } }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "ansi-regex": "^6.0.1" }, "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "engines": { "node": ">=6.0.0" } @@ -1178,14 +1050,653 @@ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", - "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@million/lint": { + "version": "0.0.73", + "resolved": "https://registry.npmjs.org/@million/lint/-/lint-0.0.73.tgz", + "integrity": "sha512-UR1VR/GorYt5bRKBtNeS2ZWj6PZk8RVpwV7WDjWmdbLqLAYv4JlRnkPAImZbJR5R50jsHpopmcqqm4mcbyZwiw==", + "dependencies": { + "@babel/core": "^7.23.7", + "@babel/helper-module-imports": "^7.22.15", + "@babel/types": "^7.23.6", + "@radix-ui/react-dialog": "^1.0.5", + "@radix-ui/react-tooltip": "^1.0.7", + "@rollup/pluginutils": "^5.1.0", + "cmdk": "^0.2.1", + "esbuild": "^0.20.1", + "escalade": "^3.1.2", + "isomorphic-fetch": "^3.0.0", + "posthog-node": "^3.6.3", + "react": "^18", + "react-dom": "^18", + "react-draggable": "^4.4.6", + "react-reconciler": "^0.29.0", + "unplugin": "^1.6.0", + "zustand": "^4.5.2" + }, + "bin": { + "lint": "dist/wizard/index.js" + } + }, + "node_modules/@million/lint/node_modules/@esbuild/android-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@million/lint/node_modules/@esbuild/android-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@million/lint/node_modules/@esbuild/android-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@million/lint/node_modules/@esbuild/darwin-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@million/lint/node_modules/@esbuild/darwin-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@million/lint/node_modules/@esbuild/freebsd-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@million/lint/node_modules/@esbuild/freebsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@million/lint/node_modules/@esbuild/linux-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@million/lint/node_modules/@esbuild/linux-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@million/lint/node_modules/@esbuild/linux-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@million/lint/node_modules/@esbuild/linux-loong64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@million/lint/node_modules/@esbuild/linux-mips64el": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@million/lint/node_modules/@esbuild/linux-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@million/lint/node_modules/@esbuild/linux-riscv64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@million/lint/node_modules/@esbuild/linux-s390x": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@million/lint/node_modules/@esbuild/linux-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@million/lint/node_modules/@esbuild/netbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@million/lint/node_modules/@esbuild/openbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@million/lint/node_modules/@esbuild/sunos-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@million/lint/node_modules/@esbuild/win32-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@million/lint/node_modules/@esbuild/win32-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@million/lint/node_modules/@esbuild/win32-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@million/lint/node_modules/@radix-ui/primitive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.0.tgz", + "integrity": "sha512-3e7rn8FDMin4CgeL7Z/49smCA3rFYY3Ha2rUQ7HRWFadS5iCRw08ZgVT1LaNTCNqgvrUiyczLflrVrF0SRQtNA==", + "dependencies": { + "@babel/runtime": "^7.13.10" + } + }, + "node_modules/@million/lint/node_modules/@radix-ui/react-compose-refs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.0.tgz", + "integrity": "sha512-0KaSv6sx787/hK3eF53iOkiSLwAGlFMx5lotrqD2pTjB18KbybKoEIgkNZTKC60YECDQTKGTRcDBILwZVqVKvA==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@million/lint/node_modules/@radix-ui/react-context": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.0.0.tgz", + "integrity": "sha512-1pVM9RfOQ+n/N5PJK33kRSKsr1glNxomxONs5c49MliinBY6Yw2Q995qfBUUo0/Mbg05B/sGA0gkgPI7kmSHBg==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@million/lint/node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.0.tgz", + "integrity": "sha512-n7kDRfx+LB1zLueRDvZ1Pd0bxdJWDUZNQ/GWoxDn2prnuJKRdxsjulejX/ePkOsLi2tTm6P24mDqlMSgQpsT6g==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.0", + "@radix-ui/react-compose-refs": "1.0.0", + "@radix-ui/react-primitive": "1.0.0", + "@radix-ui/react-use-callback-ref": "1.0.0", + "@radix-ui/react-use-escape-keydown": "1.0.0" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@million/lint/node_modules/@radix-ui/react-focus-guards": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.0.tgz", + "integrity": "sha512-UagjDk4ijOAnGu4WMUPj9ahi7/zJJqNZ9ZAiGPp7waUWJO0O1aWXi/udPphI0IUjvrhBsZJGSN66dR2dsueLWQ==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@million/lint/node_modules/@radix-ui/react-focus-scope": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.0.tgz", + "integrity": "sha512-C4SWtsULLGf/2L4oGeIHlvWQx7Rf+7cX/vKOAD2dXW0A1b5QXwi3wWeaEgW+wn+SEVrraMUk05vLU9fZZz5HbQ==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.0", + "@radix-ui/react-primitive": "1.0.0", + "@radix-ui/react-use-callback-ref": "1.0.0" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@million/lint/node_modules/@radix-ui/react-id": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.0.tgz", + "integrity": "sha512-Q6iAB/U7Tq3NTolBBQbHTgclPmGWE3OlktGGqrClPozSw4vkQ1DfQAOtzgRPecKsMdJINE05iaoDUG8tRzCBjw==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-layout-effect": "1.0.0" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@million/lint/node_modules/@radix-ui/react-portal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.0.tgz", + "integrity": "sha512-a8qyFO/Xb99d8wQdu4o7qnigNjTPG123uADNecz0eX4usnQEj7o+cG4ZX4zkqq98NYekT7UoEQIjxBNWIFuqTA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.0" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@million/lint/node_modules/@radix-ui/react-presence": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.0.0.tgz", + "integrity": "sha512-A+6XEvN01NfVWiKu38ybawfHsBjWum42MRPnEuqPsBZ4eV7e/7K321B5VgYMPv3Xx5An6o1/l9ZuDBgmcmWK3w==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.0", + "@radix-ui/react-use-layout-effect": "1.0.0" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@million/lint/node_modules/@radix-ui/react-primitive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.0.tgz", + "integrity": "sha512-EyXe6mnRlHZ8b6f4ilTDrXmkLShICIuOTTj0GX4w1rp+wSxf3+TD05u1UOITC8VsJ2a9nwHvdXtOXEOl0Cw/zQ==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-slot": "1.0.0" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@million/lint/node_modules/@radix-ui/react-slot": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.0.tgz", + "integrity": "sha512-3mrKauI/tWXo1Ll+gN5dHcxDPdm/Df1ufcDLCecn+pnCIVcdWE7CujXo8QaXOWRJyZyQWWbpB8eFwHzWXlv5mQ==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.0" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@million/lint/node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.0.tgz", + "integrity": "sha512-GZtyzoHz95Rhs6S63D2t/eqvdFCm7I+yHMLVQheKM7nBD8mbZIt+ct1jz4536MDnaOGKIxynJ8eHTkVGVVkoTg==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@million/lint/node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.0.tgz", + "integrity": "sha512-FohDoZvk3mEXh9AWAVyRTYR4Sq7/gavuofglmiXB2g1aKyboUD4YtgWxKj8O5n+Uak52gXQ4wKz5IFST4vtJHg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-callback-ref": "1.0.0" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@million/lint/node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.0.tgz", + "integrity": "sha512-JwfBCUIfhXRxKExgIqGa4CQsiMemo1Xt0W/B4ei3fpzpvPENKpMKQ8mZSB6Acj3ebrAEgi2xiQvcI1PAAodvyg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-callback-ref": "1.0.0" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@million/lint/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.0.tgz", + "integrity": "sha512-6Tpkq+R6LOlmQb1R5NNETLG0B4YP0wc+klfXafpUCj6JGyaUc8il7/kUZ7m59rGbXGczE9Bs+iz2qloqsZBduQ==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@million/lint/node_modules/cmdk": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cmdk/-/cmdk-0.2.1.tgz", + "integrity": "sha512-U6//9lQ6JvT47+6OF6Gi8BvkxYQ8SCRRSKIJkthIMsFsLZRG0cKvTtuTaefyIKMQb8rvvXy0wGdpTNq/jPtm+g==", + "dependencies": { + "@radix-ui/react-dialog": "1.0.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@million/lint/node_modules/cmdk/node_modules/@radix-ui/react-dialog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.0.0.tgz", + "integrity": "sha512-Yn9YU+QlHYLWwV1XfKiqnGVpWYWk6MeBVM6x/bcoyPvxgjQGoeT35482viLPctTMWoMw0PoHgqfSox7Ig+957Q==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.0", + "@radix-ui/react-compose-refs": "1.0.0", + "@radix-ui/react-context": "1.0.0", + "@radix-ui/react-dismissable-layer": "1.0.0", + "@radix-ui/react-focus-guards": "1.0.0", + "@radix-ui/react-focus-scope": "1.0.0", + "@radix-ui/react-id": "1.0.0", + "@radix-ui/react-portal": "1.0.0", + "@radix-ui/react-presence": "1.0.0", + "@radix-ui/react-primitive": "1.0.0", + "@radix-ui/react-slot": "1.0.0", + "@radix-ui/react-use-controllable-state": "1.0.0", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.5.4" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@million/lint/node_modules/esbuild": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" + } + }, + "node_modules/@million/lint/node_modules/react-remove-scroll": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.4.tgz", + "integrity": "sha512-xGVKJJr0SJGQVirVFAUZ2k1QLyO6m+2fy0l8Qawbp5Jgrv3DeLalrfMNBFSlmz5kriGGzsVBtGVnf4pTKIhhWA==", + "dependencies": { + "react-remove-scroll-bar": "^2.3.3", + "react-style-singleton": "^2.2.1", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.0", + "use-sidecar": "^1.1.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@mole-inc/bin-wrapper": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/@mole-inc/bin-wrapper/-/bin-wrapper-8.0.1.tgz", @@ -1205,250 +1716,6 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, - "node_modules/@mui/base": { - "version": "5.0.0-beta.34", - "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.34.tgz", - "integrity": "sha512-e2mbTGTtReD/y5RFwnhkl1Tgl3XwgJhY040IlfkTVaU9f5LWrVhEnpRsYXu3B1CtLrwiWs4cu7aMHV9yRd4jpw==", - "dependencies": { - "@babel/runtime": "^7.23.9", - "@floating-ui/react-dom": "^2.0.8", - "@mui/types": "^7.2.13", - "@mui/utils": "^5.15.7", - "@popperjs/core": "^2.11.8", - "clsx": "^2.1.0", - "prop-types": "^15.8.1" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@mui/base/node_modules/clsx": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", - "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/@mui/core-downloads-tracker": { - "version": "5.15.7", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.7.tgz", - "integrity": "sha512-AuF+Wo2Mp/edaO6vJnWjg+gj4tzEz5ChMZnAQpc22DXpSvM8ddgGcZvM7D7F99pIBoSv8ub+Iz0viL+yuGVmhg==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - } - }, - "node_modules/@mui/material": { - "version": "5.15.7", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.7.tgz", - "integrity": "sha512-l6+AiKZH3iOJmZCnlpel8ghYQe9Lq0BEuKP8fGj3g5xz4arO9GydqYAtLPMvuHKtArj8lJGNuT2yHYxmejincA==", - "dependencies": { - "@babel/runtime": "^7.23.9", - "@mui/base": "5.0.0-beta.34", - "@mui/core-downloads-tracker": "^5.15.7", - "@mui/system": "^5.15.7", - "@mui/types": "^7.2.13", - "@mui/utils": "^5.15.7", - "@types/react-transition-group": "^4.4.10", - "clsx": "^2.1.0", - "csstype": "^3.1.2", - "prop-types": "^15.8.1", - "react-is": "^18.2.0", - "react-transition-group": "^4.4.5" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@emotion/react": "^11.5.0", - "@emotion/styled": "^11.3.0", - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@emotion/react": { - "optional": true - }, - "@emotion/styled": { - "optional": true - }, - "@types/react": { - "optional": true - } - } - }, - "node_modules/@mui/material/node_modules/clsx": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", - "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/@mui/private-theming": { - "version": "5.15.7", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.7.tgz", - "integrity": "sha512-bcEeeXm7GyQCQvN9dwo8htGv8/6tP05p0i02Z7GXm5EoDPlBcqTNGugsjNLoGq6B0SsdyanjJGw0Jw00o1yAOA==", - "dependencies": { - "@babel/runtime": "^7.23.9", - "@mui/utils": "^5.15.7", - "prop-types": "^15.8.1" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@mui/styled-engine": { - "version": "5.15.7", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.7.tgz", - "integrity": "sha512-ixSdslOjK1kzdGcxqj7O3d14By/LPQ7EWknsViQ8RaeT863EAQemS+zvUJDTcOpkfJh6q6gPnYMIb2TJCs9eWA==", - "dependencies": { - "@babel/runtime": "^7.23.9", - "@emotion/cache": "^11.11.0", - "csstype": "^3.1.2", - "prop-types": "^15.8.1" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@emotion/react": "^11.4.1", - "@emotion/styled": "^11.3.0", - "react": "^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@emotion/react": { - "optional": true - }, - "@emotion/styled": { - "optional": true - } - } - }, - "node_modules/@mui/system": { - "version": "5.15.7", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.7.tgz", - "integrity": "sha512-9alZ4/dLxsTwUOdqakgzxiL5YW6ntqj0CfzWImgWnBMTZhgGcPsbYpBLniNkkk7/jptma4/bykWXHwju/ls/pg==", - "dependencies": { - "@babel/runtime": "^7.23.9", - "@mui/private-theming": "^5.15.7", - "@mui/styled-engine": "^5.15.7", - "@mui/types": "^7.2.13", - "@mui/utils": "^5.15.7", - "clsx": "^2.1.0", - "csstype": "^3.1.2", - "prop-types": "^15.8.1" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@emotion/react": "^11.5.0", - "@emotion/styled": "^11.3.0", - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@emotion/react": { - "optional": true - }, - "@emotion/styled": { - "optional": true - }, - "@types/react": { - "optional": true - } - } - }, - "node_modules/@mui/system/node_modules/clsx": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", - "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/@mui/types": { - "version": "7.2.13", - "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.13.tgz", - "integrity": "sha512-qP9OgacN62s+l8rdDhSFRe05HWtLLJ5TGclC9I1+tQngbssu0m2dmFZs+Px53AcOs9fD7TbYd4gc9AXzVqO/+g==", - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@mui/utils": { - "version": "5.15.7", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.7.tgz", - "integrity": "sha512-8qhsxQRNV6aEOjjSk6YQIYJxkF5klhj8oG1FEEU4z6HV78TjNqRxMP08QGcdsibEbez+nihAaz6vu83b4XqbAg==", - "dependencies": { - "@babel/runtime": "^7.23.9", - "@types/prop-types": "^15.7.11", - "prop-types": "^15.8.1", - "react-is": "^18.2.0" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1491,12 +1758,12 @@ } }, "node_modules/@playwright/test": { - "version": "1.41.2", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.41.2.tgz", - "integrity": "sha512-qQB9h7KbibJzrDpkXkYvsmiDJK14FULCCZgEcoe2AvFAS64oCirWTwzTlAYEbKaRxWs5TFesE1Na6izMv3HfGg==", + "version": "1.42.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.42.1.tgz", + "integrity": "sha512-Gq9rmS54mjBL/7/MvBaNOBwbfnh7beHvS6oS4srqXFcQHpQCV1+c8JXWE8VLPyRDhgS3H8x8A7hztqI9VnwrAQ==", "dev": true, "dependencies": { - "playwright": "1.41.2" + "playwright": "1.42.1" }, "bin": { "playwright": "cli.js" @@ -1505,40 +1772,6 @@ "node": ">=16" } }, - "node_modules/@popperjs/core": { - "version": "2.11.8", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", - "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } - }, - "node_modules/@preact/signals-core": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@preact/signals-core/-/signals-core-1.5.1.tgz", - "integrity": "sha512-dE6f+WCX5ZUDwXzUIWNMhhglmuLpqJhuy3X3xHrhZYI0Hm2LyQwOu0l9mdPiWrVNsE+Q7txOnJPgtIqHCYoBVA==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/preact" - } - }, - "node_modules/@preact/signals-react": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@preact/signals-react/-/signals-react-2.0.0.tgz", - "integrity": "sha512-tMVi2SXFXlojaiPNWa8dlYaidR/XvEgMSp+iymKJgMssBM/QVtUQrodKZek1BJju+dkVHiyeuQHmkuLOI9oyNw==", - "dependencies": { - "@preact/signals-core": "^1.5.1", - "use-sync-external-store": "^1.2.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/preact" - }, - "peerDependencies": { - "react": "^16.14.0 || 17.x || 18.x" - } - }, "node_modules/@radix-ui/number": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.0.1.tgz", @@ -2224,9 +2457,9 @@ } }, "node_modules/@radix-ui/react-select": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-1.2.2.tgz", - "integrity": "sha512-zI7McXr8fNaSrUY9mZe4x/HC0jTLY9fWNhO1oLWYMQGDXuV4UCivIGTxwioSzO0ZCYX9iSLyWmAh/1TOmX3Cnw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.0.0.tgz", + "integrity": "sha512-RH5b7af4oHtkcHS7pG6Sgv5rk5Wxa7XI8W5gvB1N/yiuDGZxko1ynvOiVhFM7Cis2A8zxF9bTOUVbRDzPepe6w==", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/number": "1.0.1", @@ -2235,12 +2468,12 @@ "@radix-ui/react-compose-refs": "1.0.1", "@radix-ui/react-context": "1.0.1", "@radix-ui/react-direction": "1.0.1", - "@radix-ui/react-dismissable-layer": "1.0.4", + "@radix-ui/react-dismissable-layer": "1.0.5", "@radix-ui/react-focus-guards": "1.0.1", - "@radix-ui/react-focus-scope": "1.0.3", + "@radix-ui/react-focus-scope": "1.0.4", "@radix-ui/react-id": "1.0.1", - "@radix-ui/react-popper": "1.1.2", - "@radix-ui/react-portal": "1.0.3", + "@radix-ui/react-popper": "1.1.3", + "@radix-ui/react-portal": "1.0.4", "@radix-ui/react-primitive": "1.0.3", "@radix-ui/react-slot": "1.0.2", "@radix-ui/react-use-callback-ref": "1.0.1", @@ -2266,113 +2499,6 @@ } } }, - "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.4.tgz", - "integrity": "sha512-7UpBa/RKMoHJYjie1gkF1DlK8l1fdU/VKDpoS3rCCo8YBJR294GwcEHyxHw72yvphJ7ld0AXEcSLAzY2F/WyCg==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/primitive": "1.0.1", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-callback-ref": "1.0.1", - "@radix-ui/react-use-escape-keydown": "1.0.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-focus-scope": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.3.tgz", - "integrity": "sha512-upXdPfqI4islj2CslyfUBNlaJCPybbqRHAi1KER7Isel9Q2AtSJ0zRBZv8mWQiFXD2nyAJ4BhC3yXgZ6kMBSrQ==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-callback-ref": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-popper": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.2.tgz", - "integrity": "sha512-1CnGGfFi/bbqtJZZ0P/NQY20xdG3E0LALJaLUEoKwPLwl6PPPfbeiCqMVQnhoFRAxjJj4RpBRJzDmUgsex2tSg==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.0.3", - "@radix-ui/react-compose-refs": "1.0.1", - "@radix-ui/react-context": "1.0.1", - "@radix-ui/react-primitive": "1.0.3", - "@radix-ui/react-use-callback-ref": "1.0.1", - "@radix-ui/react-use-layout-effect": "1.0.1", - "@radix-ui/react-use-rect": "1.0.1", - "@radix-ui/react-use-size": "1.0.1", - "@radix-ui/rect": "1.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-portal": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.3.tgz", - "integrity": "sha512-xLYZeHrWoPmA5mEKEfZZevoVRK/Q43GfzRXkWV6qawIWWK8t6ifIiLQdd7rmQ4Vk1bmI21XhqF9BN3jWf+phpA==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, "node_modules/@radix-ui/react-separator": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.0.3.tgz", @@ -2662,11 +2788,11 @@ } }, "node_modules/@reactflow/background": { - "version": "11.3.8", - "resolved": "https://registry.npmjs.org/@reactflow/background/-/background-11.3.8.tgz", - "integrity": "sha512-U4aI54F7PwqgYI0Knv72QFRI/wXeipPmIYAlDsA0j51+tlPxs3Nk2z7G1/4pC11GxEZkgQVfcIXro4l1Fk+bIQ==", + "version": "11.3.9", + "resolved": "https://registry.npmjs.org/@reactflow/background/-/background-11.3.9.tgz", + "integrity": "sha512-byj/G9pEC8tN0wT/ptcl/LkEP/BBfa33/SvBkqE4XwyofckqF87lKp573qGlisfnsijwAbpDlf81PuFL41So4Q==", "dependencies": { - "@reactflow/core": "11.10.3", + "@reactflow/core": "11.10.4", "classcat": "^5.0.3", "zustand": "^4.4.1" }, @@ -2676,11 +2802,11 @@ } }, "node_modules/@reactflow/controls": { - "version": "11.2.8", - "resolved": "https://registry.npmjs.org/@reactflow/controls/-/controls-11.2.8.tgz", - "integrity": "sha512-Y9YVx38sRjYtbPsI/xa+B1FGN73FV1GqqajlmGfrc1TmqhJaX+gaMXMvVazT/N5haK1hMJvOApUTLQ2V/5Rdbg==", + "version": "11.2.9", + "resolved": "https://registry.npmjs.org/@reactflow/controls/-/controls-11.2.9.tgz", + "integrity": "sha512-e8nWplbYfOn83KN1BrxTXS17+enLyFnjZPbyDgHSRLtI5ZGPKF/8iRXV+VXb2LFVzlu4Wh3la/pkxtfP/0aguA==", "dependencies": { - "@reactflow/core": "11.10.3", + "@reactflow/core": "11.10.4", "classcat": "^5.0.3", "zustand": "^4.4.1" }, @@ -2690,9 +2816,9 @@ } }, "node_modules/@reactflow/core": { - "version": "11.10.3", - "resolved": "https://registry.npmjs.org/@reactflow/core/-/core-11.10.3.tgz", - "integrity": "sha512-nV3nep4fjBy3h8mYSnJcclGcQtj8fkUBmNkEwCZCK4ps+n3HNkXFB0BRisSnQz6GRQlYboSsi0cThEl3KdNITw==", + "version": "11.10.4", + "resolved": "https://registry.npmjs.org/@reactflow/core/-/core-11.10.4.tgz", + "integrity": "sha512-j3i9b2fsTX/sBbOm+RmNzYEFWbNx4jGWGuGooh2r1jQaE2eV+TLJgiG/VNOp0q5mBl9f6g1IXs3Gm86S9JfcGw==", "dependencies": { "@types/d3": "^7.4.0", "@types/d3-drag": "^3.0.1", @@ -2710,11 +2836,11 @@ } }, "node_modules/@reactflow/minimap": { - "version": "11.7.8", - "resolved": "https://registry.npmjs.org/@reactflow/minimap/-/minimap-11.7.8.tgz", - "integrity": "sha512-MwyP5q3VomC91Dhd4P6YcxEfnjDbREGYV6rRxbSJSTHiG0x7ETQCcPelYDGy7JvQej77Pa2yJ4g0FDwP7CsQEA==", + "version": "11.7.9", + "resolved": "https://registry.npmjs.org/@reactflow/minimap/-/minimap-11.7.9.tgz", + "integrity": "sha512-le95jyTtt3TEtJ1qa7tZ5hyM4S7gaEQkW43cixcMOZLu33VAdc2aCpJg/fXcRrrf7moN2Mbl9WIMNXUKsp5ILA==", "dependencies": { - "@reactflow/core": "11.10.3", + "@reactflow/core": "11.10.4", "@types/d3-selection": "^3.0.3", "@types/d3-zoom": "^3.0.1", "classcat": "^5.0.3", @@ -2728,11 +2854,11 @@ } }, "node_modules/@reactflow/node-resizer": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/@reactflow/node-resizer/-/node-resizer-2.2.8.tgz", - "integrity": "sha512-u/EXLpvOfAmq1sGoPYwoX4gi0PnCi0mH3eHVClHNc8JQD0WCqcV1UeVV7H3PF+1SGhhg/aOv/vPG1PcQ5fu4jQ==", + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/@reactflow/node-resizer/-/node-resizer-2.2.9.tgz", + "integrity": "sha512-HfickMm0hPDIHt9qH997nLdgLt0kayQyslKE0RS/GZvZ4UMQJlx/NRRyj5y47Qyg0NnC66KYOQWDM9LLzRTnUg==", "dependencies": { - "@reactflow/core": "11.10.3", + "@reactflow/core": "11.10.4", "classcat": "^5.0.4", "d3-drag": "^3.0.0", "d3-selection": "^3.0.0", @@ -2744,11 +2870,11 @@ } }, "node_modules/@reactflow/node-toolbar": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/@reactflow/node-toolbar/-/node-toolbar-1.3.8.tgz", - "integrity": "sha512-cfvlTPeJa/ciQTosx2bGrjHT8K/UL9kznpvpOzeZFnJm5UQXmbwAYt4Vo6GfkD51mORcIL7ujQJvB9ym3ZI9KA==", + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/@reactflow/node-toolbar/-/node-toolbar-1.3.9.tgz", + "integrity": "sha512-VmgxKmToax4sX1biZ9LXA7cj/TBJ+E5cklLGwquCCVVxh+lxpZGTBF3a5FJGVHiUNBBtFsC8ldcSZIK4cAlQww==", "dependencies": { - "@reactflow/core": "11.10.3", + "@reactflow/core": "11.10.4", "classcat": "^5.0.3", "zustand": "^4.4.1" }, @@ -2758,9 +2884,9 @@ } }, "node_modules/@remix-run/router": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.0.tgz", - "integrity": "sha512-HOil5aFtme37dVQTB6M34G95kPM3MMuqSmIRVCC52eKV+Y/tGSqw9P3rWhlAx6A+mz+MoX+XxsGsNJbaI5qCgQ==", + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.3.tgz", + "integrity": "sha512-Oy8rmScVrVxWZVOpEF57ovlnhpZ8CCPlnIIumVcV9nFdiSIrus99+Lw78ekXyGvVDlIsFJbSfmSovJUhCWYV3w==", "engines": { "node": ">=14.0.0" } @@ -2962,31 +3088,6 @@ "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@svgr/core/node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dependencies": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "node_modules/@svgr/hast-util-to-babel-ast": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", @@ -3067,23 +3168,47 @@ } } }, - "node_modules/@swc/cli/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "node_modules/@swc/cli/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, "engines": { - "node": ">= 8" + "node": ">=10" } }, + "node_modules/@swc/cli/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/cli/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/@swc/core": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.4.0.tgz", - "integrity": "sha512-wc5DMI5BJftnK0Fyx9SNJKkA0+BZSJQx8430yutWmsILkHMBD3Yd9GhlMaxasab9RhgKqZp7Ht30hUYO5ZDvQg==", + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.4.11.tgz", + "integrity": "sha512-WKEakMZxkVwRdgMN4AMJ9K5nysY8g8npgQPczmjBeNK5In7QEAZAJwnyccrWwJZU0XjVeHn2uj+XbOKdDW17rg==", "dev": true, "hasInstallScript": true, "dependencies": { - "@swc/counter": "^0.1.1", + "@swc/counter": "^0.1.2", "@swc/types": "^0.1.5" }, "engines": { @@ -3094,16 +3219,16 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.4.0", - "@swc/core-darwin-x64": "1.4.0", - "@swc/core-linux-arm-gnueabihf": "1.4.0", - "@swc/core-linux-arm64-gnu": "1.4.0", - "@swc/core-linux-arm64-musl": "1.4.0", - "@swc/core-linux-x64-gnu": "1.4.0", - "@swc/core-linux-x64-musl": "1.4.0", - "@swc/core-win32-arm64-msvc": "1.4.0", - "@swc/core-win32-ia32-msvc": "1.4.0", - "@swc/core-win32-x64-msvc": "1.4.0" + "@swc/core-darwin-arm64": "1.4.11", + "@swc/core-darwin-x64": "1.4.11", + "@swc/core-linux-arm-gnueabihf": "1.4.11", + "@swc/core-linux-arm64-gnu": "1.4.11", + "@swc/core-linux-arm64-musl": "1.4.11", + "@swc/core-linux-x64-gnu": "1.4.11", + "@swc/core-linux-x64-musl": "1.4.11", + "@swc/core-win32-arm64-msvc": "1.4.11", + "@swc/core-win32-ia32-msvc": "1.4.11", + "@swc/core-win32-x64-msvc": "1.4.11" }, "peerDependencies": { "@swc/helpers": "^0.5.0" @@ -3115,9 +3240,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.4.0.tgz", - "integrity": "sha512-UTJ/Vz+s7Pagef6HmufWt6Rs0aUu+EJF4Pzuwvr7JQQ5b1DZeAAUeUtkUTFx/PvCbM8Xfw4XdKBUZfrIKCfW8A==", + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.4.11.tgz", + "integrity": "sha512-C1j1Qp/IHSelVWdEnT7f0iONWxQz6FAqzjCF2iaL+0vFg4V5f2nlgrueY8vj5pNNzSGhrAlxsMxEIp4dj1MXkg==", "cpu": [ "arm64" ], @@ -3131,9 +3256,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.4.0.tgz", - "integrity": "sha512-f8v58u2GsGak8EtZFN9guXqE0Ep10Suny6xriaW2d8FGqESPyNrnBzli3aqkSeQk5gGqu2zJ7WiiKp3XoUOidA==", + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.4.11.tgz", + "integrity": "sha512-0TTy3Ni8ncgaMCchSQ7FK8ZXQLlamy0FXmGWbR58c+pVZWYZltYPTmheJUvVcR0H2+gPAymRKyfC0iLszDALjg==", "cpu": [ "x64" ], @@ -3147,9 +3272,9 @@ } }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.4.0.tgz", - "integrity": "sha512-q2KAkBzmPcTnRij/Y1fgHCKAGevUX/H4uUESrw1J5gmUg9Qip6onKV80lTumA1/aooGJ18LOsB31qdbwmZk9OA==", + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.4.11.tgz", + "integrity": "sha512-XJLB71uw0rog4DjYAPxFGAuGCBQpgJDlPZZK6MTmZOvI/1t0+DelJ24IjHIxk500YYM26Yv47xPabqFPD7I2zQ==", "cpu": [ "arm" ], @@ -3163,9 +3288,9 @@ } }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.4.0.tgz", - "integrity": "sha512-SknGu96W0mzHtLHWm+62fk5+Omp9fMPFO7AWyGFmz2tr8EgRRXtTSrBUnWhAbgcalnhen48GsvtMdxf1KNputg==", + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.4.11.tgz", + "integrity": "sha512-vYQwzJvm/iu052d5Iw27UFALIN5xSrGkPZXxLNMHPySVko2QMNNBv35HLatkEQHbQ3X+VKSW9J9SkdtAvAVRAQ==", "cpu": [ "arm64" ], @@ -3179,9 +3304,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.4.0.tgz", - "integrity": "sha512-/k3TDvpBRMDNskHooNN1KqwUhcwkfBlIYxRTnJvsfT2C7My4pffR+4KXmt0IKynlTTbCdlU/4jgX4801FSuliw==", + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.4.11.tgz", + "integrity": "sha512-eV+KduiRYUFjPsvbZuJ9aknQH9Tj0U2/G9oIZSzLx/18WsYi+upzHbgxmIIHJ2VJgfd7nN40RI/hMtxNsUzR/g==", "cpu": [ "arm64" ], @@ -3195,9 +3320,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.4.0.tgz", - "integrity": "sha512-GYsTMvNt5+WTVlwwQzOOWsPMw6P/F41u5PGHWmfev8Nd4QJ1h3rWPySKk4mV42IJwH9MgQCVSl3ygwNqwl6kFg==", + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.4.11.tgz", + "integrity": "sha512-WA1iGXZ2HpqM1OR9VCQZJ8sQ1KP2or9O4bO8vWZo6HZJIeoQSo7aa9waaCLRpkZvkng1ct/TF/l6ymqSNFXIzQ==", "cpu": [ "x64" ], @@ -3211,9 +3336,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.0.tgz", - "integrity": "sha512-jGVPdM/VwF7kK/uYRW5N6FwzKf/FnDjGIR3RPvQokjYJy7Auk+3Oj21C0Jev7sIT9RYnO/TrFEoEozKeD/z2Qw==", + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.11.tgz", + "integrity": "sha512-UkVJToKf0owwQYRnGvjHAeYVDfeimCEcx0VQSbJoN7Iy0ckRZi7YPlmWJU31xtKvikE2bQWCOVe0qbSDqqcWXA==", "cpu": [ "x64" ], @@ -3227,9 +3352,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.4.0.tgz", - "integrity": "sha512-biHYm1AronEKlt47O/H8sSOBM2BKXMmWT+ApvlxUw50m1RGNnVnE0bgY7tylFuuSiWyXsQPJbmUV708JqORXVg==", + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.4.11.tgz", + "integrity": "sha512-35khwkyly7lF5NDSyvIrukBMzxPorgc5iTSDfVO/LvnmN5+fm4lTlrDr4tUfTdOhv3Emy7CsKlsNAeFRJ+Pm+w==", "cpu": [ "arm64" ], @@ -3243,9 +3368,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.4.0.tgz", - "integrity": "sha512-TL5L2tFQb19kJwv6+elToGBj74QXCn9j+hZfwQatvZEJRA5rDK16eH6oAE751dGUArhnWlW3Vj65hViPvTuycw==", + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.4.11.tgz", + "integrity": "sha512-Wx8/6f0ufgQF2pbVPsJ2dAmFLwIOW+xBE5fxnb7VnEbGkTgP1qMDWiiAtD9rtvDSuODG3i1AEmAak/2HAc6i6A==", "cpu": [ "ia32" ], @@ -3259,9 +3384,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.4.0.tgz", - "integrity": "sha512-e2xVezU7XZ2Stzn4i7TOQe2Kn84oYdG0M3A7XI7oTdcpsKCcKwgiMoroiAhqCv+iN20KNqhnWwJiUiTj/qN5AA==", + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.4.11.tgz", + "integrity": "sha512-0xRFW6K9UZQH2NVC/0pVB0GJXS45lY24f+6XaPBF1YnMHd8A8GoHl7ugyM5yNUTe2AKhSgk5fJV00EJt/XBtdQ==", "cpu": [ "x64" ], @@ -3281,10 +3406,13 @@ "dev": true }, "node_modules/@swc/types": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.5.tgz", - "integrity": "sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==", - "dev": true + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.6.tgz", + "integrity": "sha512-/JLo/l2JsT/LRd80C3HfbmVpxOAJ11FO2RCEslFrgzLltoP9j8XIbsyDcfCt2WWyX+CM96rBoNM+IToAkFOugg==", + "dev": true, + "dependencies": { + "@swc/counter": "^0.1.3" + } }, "node_modules/@szmarczak/http-timer": { "version": "4.0.6", @@ -3343,9 +3471,9 @@ } }, "node_modules/@tailwindcss/typography": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.10.tgz", - "integrity": "sha512-Pe8BuPJQJd3FfRnm6H0ulKIGoMEQS+Vq01R6M5aCrFB/ccR/shT+0kXLjouGC1gFLm9hopTFN+DMP0pfwRWzPw==", + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.12.tgz", + "integrity": "sha512-CNwpBpconcP7ppxmuq3qvaCxiRWnbhANpY/ruH4L5qs2GCiVDJXde/pjj2HWPV1+Q4G9+V/etrwUYopdcjAlyg==", "dev": true, "dependencies": { "lodash.castarray": "^4.4.0", @@ -3358,11 +3486,11 @@ } }, "node_modules/@tanstack/react-virtual": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.0.4.tgz", - "integrity": "sha512-tiqKW/e2MJVCr7/pRUXulpkyxllaOclkHNfhKTo4pmHjJIqnhMfwIjc1Q1R0Un3PI3kQywywu/791c8z9u0qeA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.2.0.tgz", + "integrity": "sha512-OEdMByf2hEfDa6XDbGlZN8qO6bTjlNKqjM3im9JG+u3mCL8jALy0T/67oDI001raUUPh1Bdmfn4ZvPOV5knpcg==", "dependencies": { - "@tanstack/virtual-core": "3.0.0" + "@tanstack/virtual-core": "3.2.0" }, "funding": { "type": "github", @@ -3374,9 +3502,9 @@ } }, "node_modules/@tanstack/virtual-core": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.0.0.tgz", - "integrity": "sha512-SYXOBTjJb05rXa2vl55TTwO40A6wKu0R5i1qQwhJYNDIqaIGF7D0HsLw+pJAyi2OvntlEIVusx3xtbbgSUi6zg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.2.0.tgz", + "integrity": "sha512-P5XgYoAw/vfW65byBbJQCw+cagdXDT/qH6wmABiLt4v4YBT2q2vqCOhihe+D1Nt325F/S/0Tkv6C5z0Lv+VBQQ==", "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" @@ -3402,6 +3530,82 @@ "node": ">=14" } }, + "node_modules/@testing-library/dom/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "peer": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/dom/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "peer": true + }, + "node_modules/@testing-library/dom/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@testing-library/jest-dom": { "version": "5.17.0", "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz", @@ -3424,6 +3628,21 @@ "yarn": ">=1" } }, + "node_modules/@testing-library/jest-dom/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/@testing-library/jest-dom/node_modules/chalk": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", @@ -3437,6 +3656,45 @@ "node": ">=8" } }, + "node_modules/@testing-library/jest-dom/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@testing-library/jest-dom/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@testing-library/react": { "version": "13.4.0", "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-13.4.0.tgz", @@ -3474,6 +3732,76 @@ "node": ">=12" } }, + "node_modules/@testing-library/react/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/react/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@testing-library/react/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/react/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@testing-library/react/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/react/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@testing-library/user-event": { "version": "13.5.0", "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-13.5.0.tgz", @@ -3693,9 +4021,9 @@ } }, "node_modules/@types/d3-hierarchy": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.6.tgz", - "integrity": "sha512-qlmD/8aMk5xGorUvTUWHCiumvgaUXYldYjNVOWtYoTYY/L+WwIEAmJxUmTgr9LoGNG0PPAOmqMDJVDPc7DOpPw==" + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz", + "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==" }, "node_modules/@types/d3-interpolate": { "version": "3.0.4", @@ -3706,9 +4034,9 @@ } }, "node_modules/@types/d3-path": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.0.2.tgz", - "integrity": "sha512-WAIEVlOCdd/NKRYTsqCpOMHQHemKBEINf8YXMYOtXH0GA7SY0dqMB78P3Uhgfy+4X+/Mlw2wDtlETkN6kQUCMA==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==" }, "node_modules/@types/d3-polygon": { "version": "3.0.2", @@ -3849,9 +4177,9 @@ } }, "node_modules/@types/lodash": { - "version": "4.14.202", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.202.tgz", - "integrity": "sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.0.tgz", + "integrity": "sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==", "dev": true }, "node_modules/@types/mathjax": { @@ -3873,48 +4201,34 @@ "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" }, "node_modules/@types/node": { - "version": "16.18.79", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.79.tgz", - "integrity": "sha512-Qd7jdLR5zmnIyMhfDrfPqN5tUCvreVpP3Qrf2oSM+F7SNzlb/MwHISGUkdFHtevfkPJ3iAGyeQI/jsbh9EStgQ==", + "version": "16.18.93", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.93.tgz", + "integrity": "sha512-epWuohp6c0bQt0j3RYCiP9x52axHVn+CjS1Rx1VjPwF+ySg8lrigH3yXGs88XqnA+jGM2qnSMuFTsBxft+hO1Q==", "devOptional": true }, - "node_modules/@types/parse-json": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", - "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" - }, "node_modules/@types/prop-types": { - "version": "15.7.11", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", - "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==" + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" }, "node_modules/@types/react": { - "version": "18.2.55", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.55.tgz", - "integrity": "sha512-Y2Tz5P4yz23brwm2d7jNon39qoAtMMmalOQv6+fEFt1mT+FcM3D841wDpoUvFXhaYenuROCy3FZYqdTjM7qVyA==", + "version": "18.2.73", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.73.tgz", + "integrity": "sha512-XcGdod0Jjv84HOC7N5ziY3x+qL0AfmubvKOZ9hJjJ2yd5EE+KYjWhdOjt387e9HPheHkdggF9atTifMRtyAaRA==", "dependencies": { "@types/prop-types": "*", - "@types/scheduler": "*", "csstype": "^3.0.2" } }, "node_modules/@types/react-dom": { - "version": "18.2.18", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.18.tgz", - "integrity": "sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==", + "version": "18.2.23", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.23.tgz", + "integrity": "sha512-ZQ71wgGOTmDYpnav2knkjr3qXdAFu0vsk8Ci5w3pGAIdj7/kKAyn+VsQDhXsmzzzepAiI9leWMmubXz690AI/A==", "devOptional": true, "dependencies": { "@types/react": "*" } }, - "node_modules/@types/react-transition-group": { - "version": "4.4.10", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz", - "integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==", - "dependencies": { - "@types/react": "*" - } - }, "node_modules/@types/responselike": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", @@ -3924,11 +4238,6 @@ "@types/node": "*" } }, - "node_modules/@types/scheduler": { - "version": "0.16.8", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", - "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" - }, "node_modules/@types/testing-library__jest-dom": { "version": "5.14.9", "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.9.tgz", @@ -3949,6 +4258,12 @@ "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", "dev": true }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "node_modules/@vitejs/plugin-react-swc": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.6.0.tgz", @@ -3967,15 +4282,10 @@ "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", "deprecated": "Use your platform's native atob() and btoa() methods instead" }, - "node_modules/accordion": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/accordion/-/accordion-3.0.2.tgz", - "integrity": "sha512-jbQfFaw+57OBwPt7qSNHuW+RA8smmRwkWRS1Ozh6K/QxUspBgBV/LpdSzlY7vee8TomS6j3D33B9rIeH1qMwsA==" - }, "node_modules/ace-builds": { - "version": "1.32.5", - "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.32.5.tgz", - "integrity": "sha512-Mrh+qTitOomv1kANaRHO6jpxq6j8BzN9Duwb6pmpuB2sAsfv7MHH9j3LpRHS388uid2GisauC682bemmkdNXKg==" + "version": "1.32.9", + "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.32.9.tgz", + "integrity": "sha512-dqBLPj//Gq0b92YUtRIsdWsORf4J+4xW3r8/4Wr2Vqid7O1j7YBV/ZsVvWBjZFy+EnvMCRFCFOEIM1cbt4BQ/g==" }, "node_modules/acorn": { "version": "8.11.3", @@ -3997,6 +4307,15 @@ "acorn-walk": "^8.0.2" } }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/acorn-walk": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", @@ -4005,11 +4324,6 @@ "node": ">=0.4.0" } }, - "node_modules/add": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/add/-/add-2.0.6.tgz", - "integrity": "sha512-j5QzrmsokwWWp6kUcJQySpbG+xfOBqqKnup3OIk1pz+kB/80SLorZ9V8zHFLO92Lcd+hbvq8bT+zOGoPkmBV0Q==" - }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -4022,13 +4336,14 @@ } }, "node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" }, "funding": { @@ -4045,17 +4360,14 @@ } }, "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dependencies": { - "color-convert": "^2.0.1" + "color-convert": "^1.9.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=4" } }, "node_modules/ansi-to-html": { @@ -4120,9 +4432,9 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/aria-hidden": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.3.tgz", - "integrity": "sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz", + "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", "dependencies": { "tslib": "^2.0.0" }, @@ -4155,23 +4467,15 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "engines": { - "node": ">=8" - } - }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/autoprefixer": { - "version": "10.4.17", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.17.tgz", - "integrity": "sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg==", + "version": "10.4.19", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", + "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==", "dev": true, "funding": [ { @@ -4188,8 +4492,8 @@ } ], "dependencies": { - "browserslist": "^4.22.2", - "caniuse-lite": "^1.0.30001578", + "browserslist": "^4.23.0", + "caniuse-lite": "^1.0.30001599", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", "picocolors": "^1.0.0", @@ -4206,10 +4510,13 @@ } }, "node_modules/available-typed-arrays": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.6.tgz", - "integrity": "sha512-j1QzY8iPNPG4o4xmO3ptzpRxTciqD3MgEHtifP/YnJpIo58Xu+ne4BejlbkuaLfXn/nz6HFiw29bLpj2PNMdGg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -4218,29 +4525,15 @@ } }, "node_modules/axios": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", - "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", + "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", "dependencies": { - "follow-redirects": "^1.15.4", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, - "node_modules/babel-plugin-macros": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", - "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", - "dependencies": { - "@babel/runtime": "^7.12.5", - "cosmiconfig": "^7.0.0", - "resolve": "^1.19.0" - }, - "engines": { - "node": ">=10", - "npm": ">=6" - } - }, "node_modules/bail": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", @@ -4320,20 +4613,39 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/bin-version/node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "node_modules/bin-version-check/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "yallist": "^4.0.0" }, "engines": { - "node": ">= 8" + "node": ">=10" } }, + "node_modules/bin-version-check/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/bin-version-check/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/bin-version/node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -4393,57 +4705,15 @@ "node": ">=8" } }, - "node_modules/bin-version/node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/bin-version/node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/bin-version/node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/bin-version/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/bl": { @@ -4476,9 +4746,9 @@ } }, "node_modules/browserslist": { - "version": "4.22.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz", - "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "funding": [ { "type": "opencollective", @@ -4494,8 +4764,8 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001580", - "electron-to-chromium": "^1.4.648", + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, @@ -4572,15 +4842,16 @@ } }, "node_modules/call-bind": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.6.tgz", - "integrity": "sha512-Mj50FLHtlsoVfRfnHaZvyrooHcrlceNZdL/QBvJJVd9Ta55qCQK0gs4ss2oZDeV9zFCs6ewzYgVE5yfVmfFpVg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, "dependencies": { + "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", - "set-function-length": "^1.2.0" + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -4617,9 +4888,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001584", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001584.tgz", - "integrity": "sha512-LOz7CCQ9M1G7OjJOF9/mzmqmj3jE/7VOmrfw6Mgs0E8cjOsbRXQJHsPBfmBOXDskXKrHLyyW3n7kpDW/4BsfpQ==", + "version": "1.0.30001603", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001603.tgz", + "integrity": "sha512-iL2iSS0eDILMb9n5yKQoTBim9jMZ0Yrk8g0N9K7UzYyWnfIKzXBZD5ngpM37ZcL/cv0Mli8XtVMRYMQAfFpi5Q==", "funding": [ { "type": "opencollective", @@ -4645,19 +4916,16 @@ } }, "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=4" } }, "node_modules/character-entities": { @@ -4688,15 +4956,9 @@ } }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -4709,10 +4971,24 @@ "engines": { "node": ">= 8.10.0" }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, "optionalDependencies": { "fsevents": "~2.3.2" } }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/class-variance-authority": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.6.1.tgz", @@ -4729,11 +5005,6 @@ "resolved": "https://registry.npmjs.org/classcat/-/classcat-5.0.4.tgz", "integrity": "sha512-sbpkOw6z413p+HDGcBENe498WM9woqWHiJxCq7nvmxe9WmrUmqfAcxpIwAiMtM5Q3AhYkzXcNQHqsWq0mND51g==" }, - "node_modules/classnames": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", - "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==" - }, "node_modules/cli-cursor": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", @@ -4792,26 +5063,36 @@ "node": ">=6" } }, + "node_modules/cmdk": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.0.0.tgz", + "integrity": "sha512-gDzVf0a09TvoJ5jnuPvygTB77+XdOSwEmJ88L6XPFPlv7T3RxbP9jgenfylrAMD0+Le1aO0nVjQUzl2g+vjz5Q==", + "dependencies": { + "@radix-ui/react-dialog": "1.0.5", + "@radix-ui/react-primitive": "1.0.3" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, "node_modules/code-block-writer": { "version": "12.0.0", "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-12.0.0.tgz", "integrity": "sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w==" }, "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "color-name": "1.1.3" } }, "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/combined-stream": { "version": "1.0.8", @@ -4842,6 +5123,12 @@ "node": ">= 10" } }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -4855,9 +5142,9 @@ } }, "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, "node_modules/cookie": { "version": "0.4.2", @@ -4868,29 +5155,41 @@ } }, "node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", - "dev": true, + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dependencies": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" } }, "node_modules/css-selector-tokenizer": { @@ -5052,9 +5351,9 @@ } }, "node_modules/daisyui": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-4.6.1.tgz", - "integrity": "sha512-IXI8ypN/hkl1AKsag1XPlWt0wfvL4NedTUtUkv/VFP5q/xDbBZrZthq3/9M2yU1egcbbLhp01rluIz0GICUc+g==", + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-4.9.0.tgz", + "integrity": "sha512-9JsDx4E+30kPxThE+6yEwQokqg1957uwTx/skP2RE98fG6Ten6U+S9YXeQg1a3CI958aF5aOb0oEA+KZFfrZUA==", "dev": true, "dependencies": { "css-selector-tokenizer": "^0.8", @@ -5091,6 +5390,29 @@ "node": ">=12" } }, + "node_modules/data-urls/node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/data-urls/node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -5192,6 +5514,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, "node_modules/defaults": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", @@ -5213,18 +5541,20 @@ } }, "node_modules/define-data-property": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.2.tgz", - "integrity": "sha512-SRtsSqsDbgpJBbW3pABMCOt6rQyeM8s8RiyeSN8jYG8sYmt/kGJejbydttUsnDs1tadr19tvhT4ShwMyoqAm4g==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, "dependencies": { + "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.2", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/define-properties": { @@ -5271,9 +5601,9 @@ "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" }, "node_modules/diff": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", - "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "engines": { "node": ">=0.3.1" } @@ -5297,21 +5627,24 @@ "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/dom-accessibility-api": { "version": "0.5.16", "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", "dev": true }, - "node_modules/dom-helpers": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", - "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", - "dependencies": { - "@babel/runtime": "^7.8.7", - "csstype": "^3.0.2" - } - }, "node_modules/domexception": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", @@ -5325,9 +5658,9 @@ } }, "node_modules/dompurify": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.8.tgz", - "integrity": "sha512-b7uwreMYL2eZhrSCRC4ahLTeZcPZxSmYfmcQGXGkXiZSNW1X85v+SDM5KsWcpivIiUBH47Ji7NtyUdpLeF5JZQ==" + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.11.tgz", + "integrity": "sha512-Fan4uMuyB26gFV3ovPoEoQbxRRPfTu3CvImyZnhGq5fsIEO+gEFLp45ISFt+kQBWsK5ulDdT0oV28jS1UrwQLg==" }, "node_modules/dot-case": { "version": "3.0.4", @@ -5344,14 +5677,14 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, "node_modules/electron-to-chromium": { - "version": "1.4.657", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.657.tgz", - "integrity": "sha512-On2ymeleg6QbRuDk7wNgDdXtNqlJLM2w4Agx1D/RiTmItiL+a9oq5p7HUa2ZtkAtGBe/kil2dq/7rPfkbe0r5w==" + "version": "1.4.723", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.723.tgz", + "integrity": "sha512-rxFVtrMGMFROr4qqU6n95rUi9IlfIm+lIAt+hOToy/9r6CDv0XiEcQdC3VP71y1pE5CFTzKV0RvxOGYCPWWHPw==" }, "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, "node_modules/end-of-stream": { "version": "1.4.4", @@ -5378,6 +5711,18 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-errors": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", @@ -5452,14 +5797,11 @@ } }, "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.8.0" } }, "node_modules/escodegen": { @@ -5491,6 +5833,293 @@ "node": ">=0.10.0" } }, + "node_modules/eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-es": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", + "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", + "dev": true, + "dependencies": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=4.19.1" + } + }, + "node_modules/eslint-plugin-node": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", + "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", + "dev": true, + "dependencies": { + "eslint-plugin-es": "^3.0.0", + "eslint-utils": "^2.0.0", + "ignore": "^5.1.1", + "minimatch": "^3.0.4", + "resolve": "^1.10.1", + "semver": "^6.1.0" + }, + "engines": { + "node": ">=8.10.0" + }, + "peerDependencies": { + "eslint": ">=5.16.0" + } + }, + "node_modules/eslint-plugin-node/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-node/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/esm": { "version": "3.2.25", "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", @@ -5499,6 +6128,23 @@ "node": ">=6" } }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", @@ -5511,6 +6157,30 @@ "node": ">=4" } }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, "node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", @@ -5550,6 +6220,66 @@ "node": ">=4" } }, + "node_modules/execa/node_modules/cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", + "dev": true, + "dependencies": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "node_modules/execa/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/execa/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/execa/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "dev": true + }, "node_modules/executable": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", @@ -5595,7 +6325,8 @@ "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true }, "node_modules/fast-glob": { "version": "3.3.2", @@ -5612,6 +6343,29 @@ "node": ">=8.6.0" } }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, "node_modules/fastparse": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", @@ -5660,6 +6414,18 @@ "node": "^12.20 || >= 14.13" } }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/file-type": { "version": "17.1.6", "resolved": "https://registry.npmjs.org/file-type/-/file-type-17.1.6.tgz", @@ -5717,22 +6483,20 @@ "node": ">=8" } }, - "node_modules/find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" - }, "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "dependencies": { - "locate-path": "^5.0.0", + "locate-path": "^6.0.0", "path-exists": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/find-versions": { @@ -5750,10 +6514,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, "node_modules/follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -5793,46 +6577,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/foreground-child/node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/foreground-child/node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/foreground-child/node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/foreground-child/node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "engines": { - "node": ">=8" - } - }, "node_modules/foreground-child/node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -5844,20 +6588,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/foreground-child/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -5903,6 +6633,30 @@ "url": "https://github.com/sponsors/rawify" } }, + "node_modules/framer-motion": { + "version": "11.0.24", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.0.24.tgz", + "integrity": "sha512-l2iM8NR53qtcujgAqYvGPJJGModPNWEVUaATRDLfnaLvUoFpImovBm0AHalSSsY8tW6knP8mfJTW4WYGbnAe4w==", + "dependencies": { + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/fs-extra": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", @@ -5916,6 +6670,12 @@ "node": ">=14.14" } }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", @@ -5991,35 +6751,56 @@ } }, "node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "*" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dependencies": { - "is-glob": "^4.0.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 6" + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, "node_modules/globals": { @@ -6072,6 +6853,12 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -6082,30 +6869,29 @@ } }, "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "engines": { - "node": ">=8" + "node": ">=4" } }, "node_modules/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.2" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "dev": true, "engines": { "node": ">= 0.4" @@ -6142,9 +6928,9 @@ } }, "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dependencies": { "function-bind": "^1.1.2" }, @@ -6424,6 +7210,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, "node_modules/indent-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", @@ -6433,6 +7228,16 @@ "node": ">=8" } }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -6680,10 +7485,13 @@ } }, "node_modules/is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", "dev": true, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -6711,6 +7519,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -6742,21 +7559,27 @@ } }, "node_modules/is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", "dev": true, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -6813,22 +7636,28 @@ } }, "node_modules/is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", "dev": true, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -6845,6 +7674,15 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, + "node_modules/isomorphic-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", + "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", + "dependencies": { + "node-fetch": "^2.6.1", + "whatwg-fetch": "^3.4.1" + } + }, "node_modules/jackspeak": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", @@ -6877,6 +7715,76 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, + "node_modules/jest-diff/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-diff/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-diff/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-diff/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/jest-get-type": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", @@ -6901,6 +7809,76 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, + "node_modules/jest-matcher-utils/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-matcher-utils/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-matcher-utils/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/jiti": { "version": "1.21.0", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", @@ -6969,6 +7947,29 @@ } } }, + "node_modules/jsdom/node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jsdom/node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -6992,9 +7993,16 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true }, "node_modules/json5": { "version": "2.2.3", @@ -7019,9 +8027,9 @@ } }, "node_modules/katex": { - "version": "0.16.9", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.9.tgz", - "integrity": "sha512-fsSYjWS0EEOwvy81j3vRA8TEAhQhKiqO+FQaKWp0m39qwOzHVBgAUBIXWj1pB+O2W3fIpNa6Y9KSKCVbfPhyAQ==", + "version": "0.16.10", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.10.tgz", + "integrity": "sha512-ZiqaC04tp2O5utMsl2TEZTXxa6WSC4yo0fv5ML++D3QZv/vx2Mct0mTlRx3O+uUkjfuAgOkzsCmq5MiUEsDDdA==", "funding": [ "https://opencollective.com/katex", "https://github.com/sponsors/katex" @@ -7051,13 +8059,26 @@ } }, "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", "engines": { "node": ">=6" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", @@ -7072,15 +8093,18 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "dependencies": { - "p-locate": "^4.1.0" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lodash": { @@ -7116,11 +8140,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==" - }, "node_modules/log-symbols": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", @@ -7198,19 +8217,17 @@ } }, "node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "yallist": "^3.0.2" } }, "node_modules/lucide-react": { - "version": "0.233.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.233.0.tgz", - "integrity": "sha512-r0jMHF0vPDq2wBbZ0B3rtIcBjDyWDKpHu+vAjD2OHn2WLUr3HN5IHovtO0EMgQXuSI7YrMZbjsEZWC2uBHr8nQ==", + "version": "0.331.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.331.0.tgz", + "integrity": "sha512-CHFJ0ve9vaZ7bB2VRAl27SlX1ELh6pfNC0jS96qGpPEEzLkLDGq4pDBFU8RhOoRMqsjXqTzLm9U6bZ1OcIHq7Q==", "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0" } @@ -8055,6 +9072,25 @@ "node": ">=8.6" } }, + "node_modules/million": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/million/-/million-3.0.6.tgz", + "integrity": "sha512-OLjRVASGOZdyZw2ctBSSOu5kb9PaxafqkueqVvw0iQtUUnTLVRk1EmtqcNAtJWCIm8wn+WGRpDbnp+5Hi8//Kg==", + "dependencies": { + "@babel/core": "^7.23.7", + "@babel/types": "^7.23.6", + "@rollup/pluginutils": "^5.1.0", + "kleur": "^4.1.5", + "undici": "^6.3.0", + "unplugin": "^1.6.0" + }, + "bin": { + "million": "packages/cli/dist/index.js" + }, + "funding": { + "url": "https://github.com/sponsors/aidenybai" + } + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -8109,9 +9145,9 @@ } }, "node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -8205,6 +9241,12 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, "node_modules/no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", @@ -8233,20 +9275,22 @@ } }, "node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" + "whatwg-url": "^5.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": "4.x || >=6.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, "node_modules/node-releases": { @@ -8295,6 +9339,15 @@ "node": ">=4" } }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/nwsapi": { "version": "2.2.7", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", @@ -8326,13 +9379,13 @@ } }, "node_modules/object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -8391,6 +9444,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/ora": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/ora/-/ora-6.3.1.tgz", @@ -8413,6 +9483,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ora/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, "node_modules/ora/node_modules/chalk": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", @@ -8424,6 +9505,20 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/ora/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/os-filter-obj": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/os-filter-obj/-/os-filter-obj-2.0.0.tgz", @@ -8455,30 +9550,33 @@ } }, "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "dependencies": { - "p-try": "^2.0.0" + "yocto-queue": "^0.1.0" }, "engines": { - "node": ">=6" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "dependencies": { - "p-limit": "^2.2.0" + "p-limit": "^3.0.2" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-try": { @@ -8571,13 +9669,21 @@ "node": ">=8" } }, - "node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, "engines": { - "node": ">=4" + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" } }, "node_modules/path-parse": { @@ -8586,11 +9692,11 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", + "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", + "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { @@ -8662,12 +9768,11 @@ } }, "node_modules/playwright": { - "version": "1.41.2", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.2.tgz", - "integrity": "sha512-v0bOa6H2GJChDL8pAeLa/LZC4feoAMbSQm1/jF/ySsWWoaNItvrMP7GEkvEEFyCTUYKMxjQKaTSg5up7nR6/8A==", - "dev": true, + "version": "1.42.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.42.1.tgz", + "integrity": "sha512-PgwB03s2DZBcNRoW+1w9E+VkLBxweib6KTXM0M3tkiT4jVxKSi6PmVJ591J+0u10LUrgxB7dLRbiJqO5s2QPMg==", "dependencies": { - "playwright-core": "1.41.2" + "playwright-core": "1.42.1" }, "bin": { "playwright": "cli.js" @@ -8680,10 +9785,9 @@ } }, "node_modules/playwright-core": { - "version": "1.41.2", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.2.tgz", - "integrity": "sha512-VaTvwCA4Y8kxEe+kfm2+uUUw5Lubf38RxF7FpBxLPmGe5sdNkSg5e3ChEigaGrX7qdqT3pt2m/98LiyvU2x6CA==", - "dev": true, + "version": "1.42.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.42.1.tgz", + "integrity": "sha512-mxz6zclokgrke9p1vtdy/COWBH+eOZgYUVVU34C73M+4j4HLlQJHtfcqiqqxpP0o8HhMkflvfbquLX5dg6wlfA==", "bin": { "playwright-core": "cli.js" }, @@ -8691,10 +9795,19 @@ "node": ">=16" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postcss": { - "version": "8.4.34", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.34.tgz", - "integrity": "sha512-4eLTO36woPSocqZ1zIrFD2K1v6wH7pY1uBh0JIM2KKfrVtGvPFiAku6aNOP0W1Wr9qwnaCsF0Z+CrVnryB2A8Q==", + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", "funding": [ { "type": "opencollective", @@ -8712,7 +9825,7 @@ "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "source-map-js": "^1.2.0" }, "engines": { "node": "^10 || ^12 || >=14" @@ -8787,19 +9900,14 @@ } }, "node_modules/postcss-load-config/node_modules/lilconfig": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", - "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz", + "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", "engines": { "node": ">=14" - } - }, - "node_modules/postcss-load-config/node_modules/yaml": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", - "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", - "engines": { - "node": ">= 14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" } }, "node_modules/postcss-nested": { @@ -8821,9 +9929,9 @@ } }, "node_modules/postcss-nested/node_modules/postcss-selector-parser": { - "version": "6.0.15", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz", - "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==", + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz", + "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==", "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -8850,6 +9958,27 @@ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, + "node_modules/posthog-node": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/posthog-node/-/posthog-node-3.6.3.tgz", + "integrity": "sha512-JB+ei0LkwE+rKHyW5z79Nd1jUaGxU6TvkfjFqY9vQaHxU5aU8dRl0UUaEmZdZbHwjp3WmXCBQQRNyimwbNQfCw==", + "dependencies": { + "axios": "^1.6.2", + "rusha": "^0.8.14" + }, + "engines": { + "node": ">=15.0.0" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/prettier": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", @@ -8985,12 +10114,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/pretty-format/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, "node_modules/pretty-quick": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-3.3.1.tgz", @@ -9015,20 +10138,6 @@ "prettier": "^2.0.0" } }, - "node_modules/pretty-quick/node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/pretty-quick/node_modules/execa": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", @@ -9052,6 +10161,19 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/pretty-quick/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/pretty-quick/node_modules/get-stream": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", @@ -9088,6 +10210,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/pretty-quick/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/pretty-quick/node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -9100,11 +10234,29 @@ "node": ">=8" } }, - "node_modules/pretty-quick/node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "node_modules/pretty-quick/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-quick/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, "engines": { "node": ">=8" } @@ -9121,42 +10273,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pretty-quick/node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pretty-quick/node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pretty-quick/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/prismjs": { "version": "1.29.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", @@ -9177,6 +10293,14 @@ "node": ">= 6" } }, + "node_modules/prompts/node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "engines": { + "node": ">=6" + } + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -9323,10 +10447,23 @@ "react": "^18.2.0" } }, + "node_modules/react-draggable": { + "version": "4.4.6", + "resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.4.6.tgz", + "integrity": "sha512-LtY5Xw1zTPqHkVmtM3X8MUOxNDOUhv/khTgBgrUvwaS064bwVvxT+q5El0uUFNx5IEPKXuRejr7UqLwBIg5pdw==", + "dependencies": { + "clsx": "^1.1.1", + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "react": ">= 16.3.0", + "react-dom": ">= 16.3.0" + } + }, "node_modules/react-error-boundary": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.0.12.tgz", - "integrity": "sha512-kJdxdEYlb7CPC1A0SeUY38cHpjuu6UkvzKiAmqmOFL21VRfMhOcWxTCBgLVCO0VEMh9JhFNcVaXlV4/BTpiwOA==", + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.0.13.tgz", + "integrity": "sha512-b6PwbdSv8XeOSYvjt8LpgpKrZ0yGdtZokYwkwV2wlcZbxgopHX/hgPl5VgpnoVOWd868n1hktM8Qm4b+02MiLQ==", "dependencies": { "@babel/runtime": "^7.12.5" }, @@ -9335,17 +10472,18 @@ } }, "node_modules/react-icons": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.12.0.tgz", - "integrity": "sha512-IBaDuHiShdZqmfc/TwHu6+d6k2ltNCf3AszxNmjJc1KUfXdEeRJOKyNvLmAHaarhzGmTSVygNdyu8/opXv2gaw==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.0.1.tgz", + "integrity": "sha512-WqLZJ4bLzlhmsvme6iFdgO8gfZP17rfjYEJ2m9RsZjZ+cc4k1hTzknEz63YS1MeT50kVzoa1Nz36f4BEx+Wigw==", "peerDependencies": { "react": "*" } }, "node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true }, "node_modules/react-laag": { "version": "2.0.5", @@ -9389,6 +10527,26 @@ "react": ">=16" } }, + "node_modules/react-markdown/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, + "node_modules/react-reconciler": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.29.0.tgz", + "integrity": "sha512-wa0fGj7Zht1EYMRhKWwoo1H9GApxYLBuhoAuXN0TlltESAjDssB+Apf0T/DngVqaMyPypDmabL37vw/2aRM98Q==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, "node_modules/react-remove-scroll": { "version": "2.5.5", "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz", @@ -9414,9 +10572,9 @@ } }, "node_modules/react-remove-scroll-bar": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.4.tgz", - "integrity": "sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz", + "integrity": "sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==", "dependencies": { "react-style-singleton": "^2.2.1", "tslib": "^2.0.0" @@ -9435,11 +10593,11 @@ } }, "node_modules/react-router": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.0.tgz", - "integrity": "sha512-q2yemJeg6gw/YixRlRnVx6IRJWZD6fonnfZhN1JIOhV2iJCPeRNSH3V1ISwHf+JWcESzLC3BOLD1T07tmO5dmg==", + "version": "6.22.3", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.3.tgz", + "integrity": "sha512-dr2eb3Mj5zK2YISHK++foM9w4eBnO23eKnZEDs7c880P6oKbrjz/Svg9+nxqtHQK+oMW4OtjZca0RqPglXxguQ==", "dependencies": { - "@remix-run/router": "1.15.0" + "@remix-run/router": "1.15.3" }, "engines": { "node": ">=14.0.0" @@ -9449,12 +10607,12 @@ } }, "node_modules/react-router-dom": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.0.tgz", - "integrity": "sha512-z2w+M4tH5wlcLmH3BMMOMdrtrJ9T3oJJNsAlBJbwk+8Syxd5WFJ7J5dxMEW0/GEXD1BBis4uXRrNIz3mORr0ag==", + "version": "6.22.3", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.3.tgz", + "integrity": "sha512-7ZILI7HjcE+p31oQvwbokjk6OA/bnFxrhJ19n82Ex9Ph8fNAq+Hm/7KchpMGlTgWhUxRHMMCut+vEtNpWpowKw==", "dependencies": { - "@remix-run/router": "1.15.0", - "react-router": "6.22.0" + "@remix-run/router": "1.15.3", + "react-router": "6.22.3" }, "engines": { "node": ">=14.0.0" @@ -9501,54 +10659,6 @@ "react": ">= 0.14.0" } }, - "node_modules/react-tabs": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/react-tabs/-/react-tabs-6.0.2.tgz", - "integrity": "sha512-aQXTKolnM28k3KguGDBSAbJvcowOQr23A+CUJdzJtOSDOtTwzEaJA+1U4KwhNL9+Obe+jFS7geuvA7ICQPXOnQ==", - "dependencies": { - "clsx": "^2.0.0", - "prop-types": "^15.5.0" - }, - "peerDependencies": { - "react": "^18.0.0" - } - }, - "node_modules/react-tabs/node_modules/clsx": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", - "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/react-tooltip": { - "version": "5.26.0", - "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.26.0.tgz", - "integrity": "sha512-UBbwy3fo1KYDwRCOWwM6AEfQsk9shgVfNkXFqgwS33QHplzg7xao/7mX/6wd+lE6KSZzhUNTkB5TNk9SMaBV/A==", - "dependencies": { - "@floating-ui/dom": "^1.0.0", - "classnames": "^2.3.0" - }, - "peerDependencies": { - "react": ">=16.14.0", - "react-dom": ">=16.14.0" - } - }, - "node_modules/react-transition-group": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", - "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", - "dependencies": { - "@babel/runtime": "^7.5.5", - "dom-helpers": "^5.0.1", - "loose-envify": "^1.4.0", - "prop-types": "^15.6.2" - }, - "peerDependencies": { - "react": ">=16.6.0", - "react-dom": ">=16.6.0" - } - }, "node_modules/react18-json-view": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/react18-json-view/-/react18-json-view-0.2.7.tgz", @@ -9558,16 +10668,16 @@ } }, "node_modules/reactflow": { - "version": "11.10.3", - "resolved": "https://registry.npmjs.org/reactflow/-/reactflow-11.10.3.tgz", - "integrity": "sha512-DGNrTdkWjZtPOhj5MV8fiWWGkJo+otMVdoJ9l67bQL+Xf+8NkJ4AHmRXoYIxtgcENzwTr5WTAIJlswV9i91cyw==", + "version": "11.10.4", + "resolved": "https://registry.npmjs.org/reactflow/-/reactflow-11.10.4.tgz", + "integrity": "sha512-0CApYhtYicXEDg/x2kvUHiUk26Qur8lAtTtiSlptNKuyEuGti6P1y5cS32YGaUoDMoCqkm/m+jcKkfMOvSCVRA==", "dependencies": { - "@reactflow/background": "11.3.8", - "@reactflow/controls": "11.2.8", - "@reactflow/core": "11.10.3", - "@reactflow/minimap": "11.7.8", - "@reactflow/node-resizer": "2.2.8", - "@reactflow/node-toolbar": "1.3.8" + "@reactflow/background": "11.3.9", + "@reactflow/controls": "11.2.9", + "@reactflow/core": "11.10.4", + "@reactflow/minimap": "11.7.9", + "@reactflow/node-resizer": "2.2.9", + "@reactflow/node-toolbar": "1.3.9" }, "peerDependencies": { "react": ">=17", @@ -9663,14 +10773,15 @@ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, "node_modules/regexp.prototype.flags": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", - "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "set-function-name": "^2.0.0" + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -9679,6 +10790,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, "node_modules/rehype-mathjax": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/rehype-mathjax/-/rehype-mathjax-4.0.3.tgz", @@ -9757,14 +10880,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -9836,6 +10951,21 @@ "node": ">=0.10.0" } }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/rollup": { "version": "3.29.4", "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", @@ -9873,6 +11003,11 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/rusha": { + "version": "0.8.14", + "resolved": "https://registry.npmjs.org/rusha/-/rusha-0.8.14.tgz", + "integrity": "sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA==" + }, "node_modules/sade": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", @@ -9928,18 +11063,11 @@ } }, "node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" } }, "node_modules/semver-regex": { @@ -9969,7 +11097,7 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/semver/node_modules/lru-cache": { + "node_modules/semver-truncate/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", @@ -9981,38 +11109,54 @@ "node": ">=10" } }, - "node_modules/semver/node_modules/yallist": { + "node_modules/semver-truncate/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-truncate/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, "node_modules/set-function-length": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", - "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, "dependencies": { - "define-data-property": "^1.1.2", + "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" } }, "node_modules/set-function-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", - "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, "dependencies": { - "define-data-property": "^1.0.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -10043,9 +11187,9 @@ } }, "node_modules/shadcn-ui/node_modules/agent-base": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", - "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "dependencies": { "debug": "^4.3.4" }, @@ -10072,44 +11216,6 @@ "node": ">=14" } }, - "node_modules/shadcn-ui/node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dependencies": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/shadcn-ui/node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/shadcn-ui/node_modules/execa": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", @@ -10185,26 +11291,32 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/shadcn-ui/node_modules/npm-run-path": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.2.0.tgz", - "integrity": "sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==", + "node_modules/shadcn-ui/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", "dependencies": { - "path-key": "^4.0.0" + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" }, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" } }, - "node_modules/shadcn-ui/node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "node_modules/shadcn-ui/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dependencies": { + "path-key": "^4.0.0" + }, "engines": { - "node": ">=12" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -10225,30 +11337,14 @@ } }, "node_modules/shadcn-ui/node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", "engines": { - "node": ">=8" - } - }, - "node_modules/shadcn-ui/node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dependencies": { - "shebang-regex": "^3.0.0" + "node": ">=12" }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shadcn-ui/node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/shadcn-ui/node_modules/strip-final-newline": { @@ -10262,39 +11358,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/shadcn-ui/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "dev": true, + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dependencies": { - "shebang-regex": "^1.0.0" + "shebang-regex": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "dev": true, + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/short-unique-id": { @@ -10307,12 +11387,12 @@ } }, "node_modules/side-channel": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz", - "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, "dependencies": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.7", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.4", "object-inspect": "^1.13.1" @@ -10343,22 +11423,6 @@ "node": ">=8" } }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, "node_modules/snake-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", @@ -10393,17 +11457,18 @@ } }, "node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 8" } }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "engines": { "node": ">=0.10.0" } @@ -10473,16 +11538,19 @@ } }, "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/string-width-cjs": { @@ -10499,29 +11567,23 @@ "node": ">=8" } }, - "node_modules/string-width-cjs/node_modules/strip-ansi": { + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/string-width/node_modules/ansi-regex": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/string-width/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", @@ -10535,8 +11597,7 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", + "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", @@ -10547,15 +11608,16 @@ "node": ">=8" } }, - "node_modules/strip-ansi/node_modules/ansi-regex": { + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "engines": { - "node": ">=12" + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "engines": { + "node": ">=8" } }, "node_modules/strip-bom": { @@ -10596,6 +11658,18 @@ "node": ">=8" } }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strip-outer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-2.0.0.tgz", @@ -10633,11 +11707,6 @@ "inline-style-parser": "0.1.1" } }, - "node_modules/stylis": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", - "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" - }, "node_modules/sucrase": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", @@ -10667,16 +11736,36 @@ "node": ">= 6" } }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, + "node_modules/sucrase/node_modules/glob": { + "version": "10.3.12", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", + "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", "dependencies": { - "has-flag": "^4.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.6", + "minimatch": "^9.0.1", + "minipass": "^7.0.4", + "path-scurry": "^1.10.2" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, "node_modules/supports-preserve-symlinks-flag": { @@ -10695,42 +11784,11 @@ "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" }, - "node_modules/switch": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/switch/-/switch-0.0.0.tgz", - "integrity": "sha512-Pvi4hlAXWHEIT+4XlQEPPIQ02hRzvn38K/cnZ5sZeM11FsDPoXvBD6i/zyVxFK6cgqSlS8sA5/sIwUGp9+ZMhw==" - }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" }, - "node_modules/table": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", - "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", - "dependencies": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/table/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/tailwind-merge": { "version": "1.14.0", "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-1.14.0.tgz", @@ -10741,9 +11799,9 @@ } }, "node_modules/tailwindcss": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz", - "integrity": "sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz", + "integrity": "sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==", "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -10753,7 +11811,7 @@ "fast-glob": "^3.3.0", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", - "jiti": "^1.19.1", + "jiti": "^1.21.0", "lilconfig": "^2.1.0", "micromatch": "^4.0.5", "normalize-path": "^3.0.0", @@ -10784,21 +11842,19 @@ "tailwindcss": ">=3.0.0 || insiders" } }, - "node_modules/tailwindcss/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" + "node_modules/tailwindcss-dotted-background": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tailwindcss-dotted-background/-/tailwindcss-dotted-background-1.1.0.tgz", + "integrity": "sha512-uFzCW5Bpyn8XgppTkyzqdHecH7XCDaS/eXvegDrOCYE6PxTm7dRrD9cuUcZe6mxQFVfkLu9rDmHJdqbjz9FdLA==", + "dev": true, + "peerDependencies": { + "tailwindcss": "^3.0.0" } }, "node_modules/tailwindcss/node_modules/postcss-selector-parser": { - "version": "6.0.15", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz", - "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==", + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz", + "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==", "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -10807,6 +11863,12 @@ "node": ">=4" } }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -10890,15 +11952,9 @@ } }, "node_modules/tr46": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", - "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", - "dependencies": { - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=12" - } + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "node_modules/trim-lines": { "version": "3.0.1", @@ -10974,10 +12030,34 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", + "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", "devOptional": true, "bin": { "tsc": "bin/tsc", @@ -10987,6 +12067,37 @@ "node": ">=14.17" } }, + "node_modules/ua-parser-js": { + "version": "1.0.37", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.37.tgz", + "integrity": "sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + } + ], + "engines": { + "node": "*" + } + }, + "node_modules/undici": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.10.2.tgz", + "integrity": "sha512-HcVuBy7ACaDejIMdwCzAvO22OsiE6ir6ziTIr9kAE0vB+PheVe29ZvRN8p7FXCO2uZHTjEoUs5bPiFpuc/hwwQ==", + "engines": { + "node": ">=18.0" + } + }, "node_modules/unified": { "version": "10.1.2", "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", @@ -11118,6 +12229,20 @@ "node": ">= 10.0.0" } }, + "node_modules/unplugin": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.10.1.tgz", + "integrity": "sha512-d6Mhq8RJeGA8UfKCu54Um4lFA0eSaRa3XxdAJg8tIdxbu1ubW0hBCZUL7yI2uGyYCRndvbK8FLHzqy2XKfeMsg==", + "dependencies": { + "acorn": "^8.11.3", + "chokidar": "^3.6.0", + "webpack-sources": "^3.2.3", + "webpack-virtual-modules": "^0.6.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/update-browserslist-db": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", @@ -11151,6 +12276,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -11165,9 +12291,9 @@ } }, "node_modules/use-callback-ref": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.1.tgz", - "integrity": "sha512-Lg4Vx1XZQauB42Hw3kK7JM6yjVjgFmFC5/Ab797s79aARomD2nEErc4mCgM8EZrARLmmbWpi5DGCadmK50DcAQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.2.tgz", + "integrity": "sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA==", "dependencies": { "tslib": "^2.0.0" }, @@ -11247,14 +12373,6 @@ "node": ">=8" } }, - "node_modules/uvu/node_modules/kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "engines": { - "node": ">=6" - } - }, "node_modules/vfile": { "version": "5.3.7", "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz", @@ -11284,9 +12402,9 @@ } }, "node_modules/vite": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.2.tgz", - "integrity": "sha512-tBCZBNSBbHQkaGyhGCDUGqeo2ph8Fstyp6FMSvTtsXeZSPpSMGlviAOav2hxVTqFcx8Hj/twtWKsMJXNY0xI8w==", + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.3.tgz", + "integrity": "sha512-kQL23kMeX92v3ph7IauVkXkikdDRsYMGTVl5KY2E9OY4ONLvkHf04MDTbnfo6NKxZiDLWzVpP5oTa8hQD8U3dg==", "dependencies": { "esbuild": "^0.18.10", "postcss": "^8.4.27", @@ -11745,9 +12863,9 @@ } }, "node_modules/web-streams-polyfill": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.2.tgz", - "integrity": "sha512-3pRGuxRF5gpuZc0W+EpwQRmCD7gRqcDOMt688KmdlDAgAyaB1XlN0zq2njfDNm44XVdIouE7pZ6GzbdyH47uIQ==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", "engines": { "node": ">= 8" } @@ -11765,6 +12883,19 @@ "node": ">=12" } }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack-virtual-modules": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.1.tgz", + "integrity": "sha512-poXpCylU7ExuvZK8z+On3kX+S8o/2dQ/SVYueKA0D4WEMXROXgY8Ez50/bQEUmvoSMMrWcrJqCHuhAbsiwg7Dg==" + }, "node_modules/whatwg-encoding": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", @@ -11776,6 +12907,11 @@ "node": ">=12" } }, + "node_modules/whatwg-fetch": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==" + }, "node_modules/whatwg-mimetype": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", @@ -11785,27 +12921,31 @@ } }, "node_modules/whatwg-url": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "dependencies": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=12" + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" } }, + "node_modules/whatwg-url/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dependencies": { "isexe": "^2.0.0" }, "bin": { - "which": "bin/which" + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" } }, "node_modules/which-boxed-primitive": { @@ -11825,31 +12965,34 @@ } }, "node_modules/which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, "dependencies": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/which-typed-array": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", - "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.6", - "call-bind": "^1.0.5", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.1" + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -11896,15 +13039,63 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { - "ansi-regex": "^5.0.1" + "color-convert": "^2.0.1" }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/wrap-ansi/node_modules/ansi-styles": { @@ -11918,25 +13109,18 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "ansi-regex": "^6.0.1" }, "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/wrappy": { @@ -11995,17 +13179,31 @@ } }, "node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", - "dev": true + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz", + "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==", + "bin": { + "yaml": "bin.mjs" + }, "engines": { - "node": ">= 6" + "node": ">= 14" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/zod": { @@ -12017,9 +13215,9 @@ } }, "node_modules/zustand": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.0.tgz", - "integrity": "sha512-zlVFqS5TQ21nwijjhJlx4f9iGrXSL0o/+Dpy4txAP22miJ8Ti6c1Ol1RLNN98BMib83lmDH/2KmLwaNXpjrO1A==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.2.tgz", + "integrity": "sha512-2cN1tPkDVkwCy5ickKrI7vijSjPksFRfqS6237NzT0vqSsztTNnQdHw9mmN7uBdk3gceVXU0a+21jFzFzAc9+g==", "dependencies": { "use-sync-external-store": "1.2.0" }, diff --git a/src/frontend/package.json b/src/frontend/package.json index 5ee8b6741..fd27d8bd6 100644 --- a/src/frontend/package.json +++ b/src/frontend/package.json @@ -3,12 +3,8 @@ "version": "0.1.2", "private": true, "dependencies": { - "@emotion/react": "^11.11.1", - "@emotion/styled": "^11.11.0", "@headlessui/react": "^1.7.17", - "@heroicons/react": "^2.0.18", - "@mui/material": "^5.14.7", - "@preact/signals-react": "^2.0.0", + "@million/lint": "^0.0.73", "@radix-ui/react-accordion": "^1.1.2", "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-dialog": "^1.0.4", @@ -19,7 +15,7 @@ "@radix-ui/react-menubar": "^1.0.3", "@radix-ui/react-popover": "^1.0.6", "@radix-ui/react-progress": "^1.0.3", - "@radix-ui/react-select": "^1.2.2", + "@radix-ui/react-select": "^2.0.0", "@radix-ui/react-separator": "^1.0.3", "@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-switch": "^1.0.3", @@ -29,31 +25,31 @@ "@tailwindcss/forms": "^0.5.6", "@tailwindcss/line-clamp": "^0.4.4", "@types/axios": "^0.14.0", - "accordion": "^3.0.2", "ace-builds": "^1.24.1", - "add": "^2.0.6", "ansi-to-html": "^0.7.2", "axios": "^1.5.0", "base64-js": "^1.5.1", "class-variance-authority": "^0.6.1", "clsx": "^1.2.1", + "cmdk": "^1.0.0", "dompurify": "^3.0.5", "esbuild": "^0.17.19", + "framer-motion": "^11.0.6", "lodash": "^4.17.21", - "lucide-react": "^0.233.0", + "lucide-react": "^0.331.0", + "million": "^3.0.6", "moment": "^2.29.4", + "playwright": "^1.42.0", "react": "^18.2.0", "react-ace": "^10.1.0", "react-cookie": "^4.1.1", "react-dom": "^18.2.0", "react-error-boundary": "^4.0.11", - "react-icons": "^4.10.1", + "react-icons": "^5.0.1", "react-laag": "^2.0.5", "react-markdown": "^8.0.7", "react-router-dom": "^6.15.0", "react-syntax-highlighter": "^15.5.0", - "react-tabs": "^6.0.2", - "react-tooltip": "^5.21.1", "react18-json-view": "^0.2.3", "reactflow": "^11.9.2", "rehype-mathjax": "^4.0.3", @@ -61,8 +57,6 @@ "remark-math": "^5.1.1", "shadcn-ui": "^0.2.3", "short-unique-id": "^4.4.4", - "switch": "^0.0.0", - "table": "^6.8.1", "tailwind-merge": "^1.14.0", "tailwindcss-animate": "^1.0.7", "uuid": "^9.0.0", @@ -98,7 +92,7 @@ }, "proxy": "http://127.0.0.1:7860", "devDependencies": { - "@playwright/test": "^1.38.0", + "@playwright/test": "^1.42.0", "@swc/cli": "^0.1.62", "@swc/core": "^1.3.80", "@tailwindcss/typography": "^0.5.9", @@ -114,13 +108,17 @@ "@vitejs/plugin-react-swc": "^3.3.2", "autoprefixer": "^10.4.15", "daisyui": "^4.0.4", + "eslint": "^8.57.0", + "eslint-plugin-node": "^11.1.0", "postcss": "^8.4.29", "prettier": "^2.8.8", "prettier-plugin-organize-imports": "^3.2.3", "prettier-plugin-tailwindcss": "^0.3.0", "pretty-quick": "^3.1.3", "tailwindcss": "^3.3.3", + "tailwindcss-dotted-background": "^1.1.0", "typescript": "^5.2.2", + "ua-parser-js": "^1.0.37", "vite": "^4.5.2" } } diff --git a/src/frontend/playwright-report/index.html b/src/frontend/playwright-report/index.html deleted file mode 100644 index e634446de..000000000 --- a/src/frontend/playwright-report/index.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - Document - - -
- - diff --git a/src/frontend/playwright.config.ts b/src/frontend/playwright.config.ts index a563c65f7..59f30c4ba 100644 --- a/src/frontend/playwright.config.ts +++ b/src/frontend/playwright.config.ts @@ -20,18 +20,22 @@ export default defineConfig({ /* Opt out of parallel tests on CI. */ workers: process.env.CI ? 2 : undefined, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: [ - ["html", { open: "never", outputFolder: "playwright-report/test-results" }], - ], + timeout: 120 * 1000, + // reporter: [ + // ["html", { open: "never", outputFolder: "playwright-report/test-results" }], + // ], + reporter: process.env.CI ? "blob" : "html", /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Base URL to use in actions like `await page.goto('/')`. */ - // baseURL: "http://127.0.0.1:3000", + baseURL: "http://localhost:3000/", /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ trace: "on-first-retry", }, + globalTeardown: require.resolve("./tests/globalTeardown.ts"), + /* Configure projects for major browsers */ projects: [ { @@ -48,39 +52,28 @@ export default defineConfig({ // name: "webkit", // use: { ...devices["Desktop Safari"] }, // }, - - /* Test against mobile viewports. */ - // { - // name: 'Mobile Chrome', - // use: { ...devices['Pixel 5'] }, - // }, - // { - // name: 'Mobile Safari', - // use: { ...devices['iPhone 12'] }, - // }, - - /* Test against branded browsers. */ - // { - // name: 'Microsoft Edge', - // use: { ...devices['Desktop Edge'], channel: 'msedge' }, - // }, - // { - // name: 'Google Chrome', - // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, - // }, ], - /* Run your local dev server before starting the tests */ - // webServer: [ - // { - // command: "npm run backend", - // reuseExistingServer: !process.env.CI, - // timeout: 120 * 1000, - // }, - // { - // command: "npm run start", - // url: "http://127.0.0.1:3000", - // reuseExistingServer: !process.env.CI, - // }, - // ], + webServer: [ + { + command: + "poetry run uvicorn --factory langflow.main:create_app --host 127.0.0.1 --port 7860", + port: 7860, + env: { + LANGFLOW_DATABASE_URL: "sqlite:///./temp", + LANGFLOW_AUTO_LOGIN: "true", + }, + stdout: "ignore", + + reuseExistingServer: !process.env.CI, + timeout: 120 * 1000, + }, + { + command: "npm start", + port: 3000, + env: { + VITE_PROXY_TARGET: "http://127.0.0.1:7860", + }, + }, + ], }); diff --git a/src/frontend/run-tests.sh b/src/frontend/run-tests.sh index 76e2fd756..f04a09662 100755 --- a/src/frontend/run-tests.sh +++ b/src/frontend/run-tests.sh @@ -3,6 +3,17 @@ # Default value for the --ui flag ui=false +# Absolute path to the project root directory +PROJECT_ROOT="../../" + +# Check if necessary commands are available +for cmd in npx poetry fuser; do + if ! command -v $cmd &> /dev/null; then + echo "Error: Required command '$cmd' is not installed. Aborting." + exit 1 + fi +done + # Parse command-line arguments while [[ $# -gt 0 ]]; do key="$1" @@ -23,56 +34,85 @@ done terminate_process_by_port() { port="$1" echo "Terminating process on port: $port" - fuser -k -n tcp "$port" # Forcefully terminate processes using the specified port - echo "Process terminated." + if ! fuser -k -n tcp "$port"; then + echo "Failed to terminate process on port $port. Please check manually." + else + echo "Process terminated." + fi +} + +delete_temp() { + if cd "$PROJECT_ROOT"; then + echo "Deleting temp database" + rm -f temp && echo "Temp database deleted." || echo "Failed to delete temp database." + else + echo "Failed to navigate to project root for cleanup." + fi } # Trap signals to ensure cleanup on script termination -trap 'terminate_process_by_port 7860; terminate_process_by_port 3000' EXIT +trap 'terminate_process_by_port 7860; terminate_process_by_port 3000; delete_temp' EXIT -# install playwright if there is not installed yet -npx playwright install +# Ensure the script is executed from the project root directory +if ! cd "$PROJECT_ROOT"; then + echo "Error: Failed to navigate to project root directory. Aborting." + exit 1 +fi -# Navigate to the project root directory (where the Makefile is located) -cd ../../ +# Install playwright if not installed yet +if ! npx playwright install; then + echo "Error: Failed to install Playwright. Aborting." + exit 1 +fi -# Start the frontend using 'make frontend' in the background -make frontend & +# Start the frontend +make frontend > /dev/null 2>&1 & -# Give some time for the frontend to start (adjust sleep duration as needed) +# Adjust sleep duration as needed sleep 10 -# Navigate to the test directory -cd src/frontend - -# Run frontend only Playwright tests with or without UI based on the --ui flag -if [ "$ui" = true ]; then - PLAYWRIGHT_HTML_REPORT=playwright-report/onlyFront npx playwright test tests/onlyFront --ui --project=chromium -else - PLAYWRIGHT_HTML_REPORT=playwright-report/onlyFront npx playwright test tests/onlyFront --project=chromium +# Install backend dependencies +if ! poetry install; then + echo "Error: Failed to install backend dependencies. Aborting." + exit 1 fi -# Navigate back to the project root directory -cd ../../ - -# Start the backend using 'make backend' in the background -make backend & - -# Give some time for the backend to start (adjust sleep duration as needed) +# Start the backend +LANGFLOW_DATABASE_URL=sqlite:///./temp LANGFLOW_AUTO_LOGIN=True poetry run langflow run --backend-only --port 7860 --host 0.0.0.0 --no-open-browser > /dev/null 2>&1 & +backend_pid=$! # Capture PID of the backend process +# Adjust sleep duration as needed sleep 25 -# Navigate back to the test directory -cd src/frontend - -# Run Playwright tests with or without UI based on the --ui flag -if [ "$ui" = true ]; then - PLAYWRIGHT_HTML_REPORT=playwright-report/e2e npx playwright test tests/end-to-end --ui --project=chromium -else - PLAYWRIGHT_HTML_REPORT=playwright-report/e2e npx playwright test tests/end-to-end --project=chromium +# Navigate to the test directory +if ! cd src/frontend; then + echo "Error: Failed to navigate to test directory. Aborting." + kill $backend_pid # Terminate the backend process if navigation fails + echo "Backend process terminated." + exit 1 fi -npx playwright show-report +# Check if backend is running +if ! lsof -i :7860; then + echo "Error: Backend is not running. Aborting." + exit 1 +fi -# After the tests are finished, you can add cleanup or teardown logic here if needed +# Run Playwright tests +if [ "$ui" = true ]; then + TEST_COMMAND="npx playwright test tests/end-to-end --ui --project=chromium" +else + TEST_COMMAND="npx playwright test tests/end-to-end --project=chromium" +fi -# The trap will automatically terminate processes by port on script exit +if ! PLAYWRIGHT_HTML_REPORT=playwright-report/e2e $TEST_COMMAND; then + echo "Error: Playwright tests failed. Aborting." + exit 1 +fi + +if [ "$ui" = true ]; then + echo "Opening Playwright report..." + npx playwright show-report +fi + + +trap 'terminate_process_by_port 7860; terminate_process_by_port 3000; delete_temp; kill $backend_pid 2>/dev/null' EXIT \ No newline at end of file diff --git a/src/frontend/src/App.css b/src/frontend/src/App.css index 095c63bd7..6aa681415 100644 --- a/src/frontend/src/App.css +++ b/src/frontend/src/App.css @@ -90,3 +90,12 @@ body { .jv-indent::-webkit-scrollbar-thumb:hover { background-color: #bbb !important; } + +.custom-hover { + transition: background-color 0.5s ease; +} + +.custom-hover:hover { + background-color: rgba(99, 102, 241, 0.1); /* Medium indigo color with 20% opacity */ +} + diff --git a/src/frontend/src/App.tsx b/src/frontend/src/App.tsx index 0624c0064..da3c50325 100644 --- a/src/frontend/src/App.tsx +++ b/src/frontend/src/App.tsx @@ -1,9 +1,9 @@ -import _ from "lodash"; import { useContext, useEffect, useState } from "react"; import "reactflow/dist/style.css"; import "./App.css"; import { ErrorBoundary } from "react-error-boundary"; +import { useNavigate } from "react-router-dom"; import ErrorAlert from "./alerts/error"; import NoticeAlert from "./alerts/notice"; import SuccessAlert from "./alerts/success"; @@ -15,109 +15,27 @@ import { FETCH_ERROR_MESSAGE, } from "./constants/constants"; import { AuthContext } from "./contexts/authContext"; -import { getHealth } from "./controllers/API"; +import { getGlobalVariables, getHealth } from "./controllers/API"; import Router from "./routes"; import useAlertStore from "./stores/alertStore"; import { useDarkStore } from "./stores/darkStore"; import useFlowsManagerStore from "./stores/flowsManagerStore"; +import { useGlobalVariablesStore } from "./stores/globalVariables"; import { useStoreStore } from "./stores/storeStore"; import { useTypesStore } from "./stores/typesStore"; export default function App() { - const errorData = useAlertStore((state) => state.errorData); - const errorOpen = useAlertStore((state) => state.errorOpen); - const setErrorOpen = useAlertStore((state) => state.setErrorOpen); - const noticeData = useAlertStore((state) => state.noticeData); - const noticeOpen = useAlertStore((state) => state.noticeOpen); - const setNoticeOpen = useAlertStore((state) => state.setNoticeOpen); - const successData = useAlertStore((state) => state.successData); - const successOpen = useAlertStore((state) => state.successOpen); - const setSuccessOpen = useAlertStore((state) => state.setSuccessOpen); + const removeFromTempNotificationList = useAlertStore( + (state) => state.removeFromTempNotificationList + ); + const tempNotificationList = useAlertStore( + (state) => state.tempNotificationList + ); const [fetchError, setFetchError] = useState(false); const isLoading = useFlowsManagerStore((state) => state.isLoading); - // Initialize state variable for the list of alerts - const [alertsList, setAlertsList] = useState< - Array<{ - type: string; - data: { title: string; list?: Array; link?: string }; - id: string; - }> - >([]); - - // Use effect hook to update alertsList when a new alert is added - useEffect(() => { - // If there is an error alert open with data, add it to the alertsList - if (errorOpen && errorData) { - if ( - alertsList.length > 0 && - JSON.stringify(alertsList[alertsList.length - 1].data) === - JSON.stringify(errorData) - ) { - return; - } - setErrorOpen(false); - setAlertsList((old) => { - let newAlertsList = [ - ...old, - { type: "error", data: _.cloneDeep(errorData), id: _.uniqueId() }, - ]; - return newAlertsList; - }); - } - // If there is a notice alert open with data, add it to the alertsList - else if (noticeOpen && noticeData) { - if ( - alertsList.length > 0 && - JSON.stringify(alertsList[alertsList.length - 1].data) === - JSON.stringify(noticeData) - ) { - return; - } - setNoticeOpen(false); - setAlertsList((old) => { - let newAlertsList = [ - ...old, - { type: "notice", data: _.cloneDeep(noticeData), id: _.uniqueId() }, - ]; - return newAlertsList; - }); - } - // If there is a success alert open with data, add it to the alertsList - else if (successOpen && successData) { - if ( - alertsList.length > 0 && - JSON.stringify(alertsList[alertsList.length - 1].data) === - JSON.stringify(successData) - ) { - return; - } - setSuccessOpen(false); - setAlertsList((old) => { - let newAlertsList = [ - ...old, - { type: "success", data: _.cloneDeep(successData), id: _.uniqueId() }, - ]; - return newAlertsList; - }); - } - }, [ - _, - errorData, - errorOpen, - noticeData, - noticeOpen, - setErrorOpen, - setNoticeOpen, - setSuccessOpen, - successData, - successOpen, - ]); - const removeAlert = (id: string) => { - setAlertsList((prevAlertsList) => - prevAlertsList.filter((alert) => alert.id !== id) - ); + removeFromTempNotificationList(id); }; const { isAuthenticated } = useContext(AuthContext); @@ -126,7 +44,13 @@ export default function App() { const getTypes = useTypesStore((state) => state.getTypes); const refreshVersion = useDarkStore((state) => state.refreshVersion); const refreshStars = useDarkStore((state) => state.refreshStars); + const setGlobalVariables = useGlobalVariablesStore( + (state) => state.setGlobalVariables + ); const checkHasStore = useStoreStore((state) => state.checkHasStore); + const navigate = useNavigate(); + + const [isLoadingHealth, setIsLoadingHealth] = useState(false); useEffect(() => { refreshStars(); @@ -138,22 +62,26 @@ export default function App() { getTypes().then(() => { refreshFlows(); }); + getGlobalVariables().then((res) => { + setGlobalVariables(res); + }); checkHasStore(); fetchApiData(); } }, [isAuthenticated]); useEffect(() => { + checkApplicationHealth(); // Timer to call getHealth every 5 seconds const timer = setInterval(() => { getHealth() .then(() => { - if (fetchError) setFetchError(false); + onHealthCheck(); }) .catch(() => { setFetchError(true); }); - }, 20000); + }, 20000); // 20 seconds // Clean up the timer on component unmount return () => { @@ -161,6 +89,30 @@ export default function App() { }; }, []); + const checkApplicationHealth = () => { + setIsLoadingHealth(true); + getHealth() + .then(() => { + onHealthCheck(); + }) + .catch(() => { + setFetchError(true); + }); + + setTimeout(() => { + setIsLoadingHealth(false); + }, 2000); + }; + + const onHealthCheck = () => { + setFetchError(false); + //This condition is necessary to avoid infinite loop on starter page when the application is not healthy + if (isLoading === true && window.location.pathname === "/") { + navigate("/flows"); + window.location.reload(); + } + }; + return ( //need parent component with width and height
@@ -170,51 +122,71 @@ export default function App() { }} FallbackComponent={CrashErrorComponent} > - {fetchError ? ( - - ) : isLoading ? ( -
- -
- ) : ( - <> - - - )} + <> + { + { + checkApplicationHealth(); + }} + isLoadingHealth={isLoadingHealth} + > + } + + {isLoading ? ( +
+ +
+ ) : ( + <> + + + )} +
-
- {alertsList.map((alert) => ( -
- {alert.type === "error" ? ( - - ) : alert.type === "notice" ? ( - - ) : ( - - )} -
- ))} +
+
+ {tempNotificationList.map((alert) => ( +
+ {alert.type === "error" && ( + + )} +
+ ))} +
+
+ {tempNotificationList.map((alert) => ( +
+ {alert.type === "notice" ? ( + + ) : ( + alert.type === "success" && ( + + ) + )} +
+ ))} +
); diff --git a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx index 533d60842..6a5029101 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx @@ -6,9 +6,9 @@ import CodeAreaComponent from "../../../../components/codeAreaComponent"; import DictComponent from "../../../../components/dictComponent"; import Dropdown from "../../../../components/dropdownComponent"; import FloatComponent from "../../../../components/floatComponent"; -import IconComponent from "../../../../components/genericIconComponent"; -import InputComponent from "../../../../components/inputComponent"; +import { default as IconComponent } from "../../../../components/genericIconComponent"; import InputFileComponent from "../../../../components/inputFileComponent"; +import InputGlobalComponent from "../../../../components/inputGlobalComponent"; import InputListComponent from "../../../../components/inputListComponent"; import IntComponent from "../../../../components/intComponent"; import KeypairListComponent from "../../../../components/keypairListComponent"; @@ -16,18 +16,27 @@ import PromptAreaComponent from "../../../../components/promptComponent"; import TextAreaComponent from "../../../../components/textAreaComponent"; import ToggleShadComponent from "../../../../components/toggleShadComponent"; import { Button } from "../../../../components/ui/button"; +import { RefreshButton } from "../../../../components/ui/refreshButton"; import { + INPUT_HANDLER_HOVER, LANGFLOW_SUPPORTED_TYPES, + OUTPUT_HANDLER_HOVER, TOOLTIP_EMPTY, } from "../../../../constants/constants"; -import { postCustomComponentUpdate } from "../../../../controllers/API"; import useAlertStore from "../../../../stores/alertStore"; import useFlowStore from "../../../../stores/flowStore"; import useFlowsManagerStore from "../../../../stores/flowsManagerStore"; import { useTypesStore } from "../../../../stores/typesStore"; -import { APIClassType } from "../../../../types/api"; +import { + APIClassType, + ResponseErrorDetailAPI, + ResponseErrorTypeAPI, +} from "../../../../types/api"; import { ParameterComponentType } from "../../../../types/components"; -import { NodeDataType } from "../../../../types/flow"; +import { + debouncedHandleUpdateValues, + handleUpdateValues, +} from "../../../../utils/parameterUtils"; import { convertObjToArray, convertValuesToNumbers, @@ -67,6 +76,7 @@ export default function ParameterComponent({ const edges = useFlowStore((state) => state.edges); const setNode = useFlowStore((state) => state.setNode); + const [isLoading, setIsLoading] = useState(false); const flow = currentFlow?.data?.nodes ?? null; const groupedEdge = useRef(null); @@ -83,32 +93,94 @@ export default function ParameterComponent({ const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot); - const handleUpdateValues = async (name: string, data: NodeDataType) => { - const code = data.node?.template["code"]?.value; - if (!code) { - console.error("Code not found in the template"); - return; - } - + const handleRefreshButtonPress = async (name, data) => { + setIsLoading(true); try { - const res = await postCustomComponentUpdate(code, name); - if (res.status === 200 && data.node?.template) { - data.node!.template[name] = res.data.template[name]; + let newTemplate = await handleUpdateValues(name, data); + if (newTemplate) { + setNode(data.id, (oldNode) => { + let newNode = cloneDeep(oldNode); + newNode.data = { + ...newNode.data, + }; + newNode.data.node.template = newTemplate; + return newNode; + }); } - } catch (err) { - setErrorData(err as { title: string; list?: Array }); + } catch (error) { + let responseError = error as ResponseErrorDetailAPI; + + setErrorData({ + title: "Error while updating the Component", + list: [responseError.response.data.detail ?? "Unknown error"], + }); } + setIsLoading(false); + renderTooltips(); }; - const handleOnNewValue = ( + useEffect(() => { + async function fetchData() { + if ( + (data.node?.template[name]?.real_time_refresh || + data.node?.template[name]?.refresh_button) && + // options can be undefined but not an empty array + (data.node?.template[name]?.options?.length ?? 0) === 0 + ) { + setIsLoading(true); + try { + let newTemplate = await handleUpdateValues(name, data); + if (newTemplate) { + setNode(data.id, (oldNode) => { + let newNode = cloneDeep(oldNode); + newNode.data = { + ...newNode.data, + }; + newNode.data.node.template = newTemplate; + return newNode; + }); + } + } catch (error) { + let responseError = error as ResponseErrorDetailAPI; + + setErrorData({ + title: "Error while updating the Component", + list: [responseError.response.data.detail ?? "Unknown error"], + }); + } + setIsLoading(false); + renderTooltips(); + } + } + fetchData(); + }, []); + const handleOnNewValue = async ( newValue: string | string[] | boolean | Object[] - ): void => { + ): Promise => { if (data.node!.template[name].value !== newValue) { takeSnapshot(); } + const shouldUpdate = + data.node?.template[name].real_time_refresh && + !data.node?.template[name].refresh_button && + data.node!.template[name].value !== newValue; data.node!.template[name].value = newValue; // necessary to enable ctrl+z inside the input - + let newTemplate; + if (shouldUpdate) { + setIsLoading(true); + try { + newTemplate = await debouncedHandleUpdateValues(name, data); + } catch (error) { + let responseError = error as ResponseErrorTypeAPI; + setErrorData({ + title: "Error while updating the Component", + list: [responseError.response.data.detail.error ?? "Unknown error"], + }); + } + setIsLoading(false); + // this de + } setNode(data.id, (oldNode) => { let newNode = cloneDeep(oldNode); @@ -116,7 +188,9 @@ export default function ParameterComponent({ ...newNode.data, }; - newNode.data.node.template[name].value = newValue; + if (data.node?.template[name].real_time_refresh && newTemplate) { + newNode.data.node.template = newTemplate; + } else newNode.data.node.template[name].value = newValue; return newNode; }); @@ -180,11 +254,7 @@ export default function ParameterComponent({ return (
{index === 0 && ( - - {left - ? "Avaliable input components:" - : "Avaliable output components:"} - + {left ? INPUT_HANDLER_HOVER : OUTPUT_HANDLER_HOVER} )} 2 ? item.display_name.split(", ").map((el, index) => ( - + {index === item.display_name.split(", ").length - 1 @@ -231,7 +301,7 @@ export default function ParameterComponent({ {item.type === "" ? "" : " - "} {item.type.split(", ").length > 2 ? item.type.split(", ").map((el, index) => ( - + {index === item.type.split(", ").length - 1 ? el @@ -252,11 +322,14 @@ export default function ParameterComponent({ refHtml.current = {TOOLTIP_EMPTY}; } } + // If optionalHandle is an empty list, then it is not an optional handle + if (optionalHandle && optionalHandle.length === 0) { + optionalHandle = null; + } useEffect(() => { renderTooltips(); }, [tooltipTitle, flow]); - return !showNode ? ( left && LANGFLOW_SUPPORTED_TYPES.has(type ?? "") && !optionalHandle ? ( <> @@ -265,7 +338,7 @@ export default function ParameterComponent({
@@ -291,7 +364,7 @@ export default function ParameterComponent({ !showNode ? "mt-0" : "" )} style={{ - borderColor: color, + borderColor: color ?? nodeColors.unknown, }} onClick={() => { setFilterEdge(groupedEdge.current); @@ -304,24 +377,40 @@ export default function ParameterComponent({ ) : ( - {showNode && ( -
-
- Building... - ) : !validationStatus ? ( - - Build{" "} - {" "} - flow to validate status. - - ) : ( -
- {typeof validationStatus.params === "string" - ? `Duration: ${validationStatus.duration}\n${validationStatus.params}` - .split("\n") - .map((line, index) => ( -
{line}
- )) - : ""} + {STATUS_BUILDING} + ) : !validationStatus ? ( + {STATUS_BUILD} + ) : ( +
+
+ {lastRunTime && ( +
+
{RUN_TIMESTAMP_PREFIX}
+
+ {lastRunTime} +
+
+ )} +
+
+
Duration:
+
+ {validationStatus?.data.duration}
- ) - } - > -
-
-
-
+
+
+ + Output + +
+ {validationString.split("\n").map((line, index) => ( +
+ {line} +
+ ))} +
- -
-
+ ) + } + side="bottom" + > + + )}
@@ -413,6 +671,7 @@ export default function GenericNode({ autoFocus onBlur={() => { setInputDescription(false); + setInputName(false); setNodeDescription(nodeDescription); setNode(data.id, (old) => ({ ...old, @@ -460,7 +719,7 @@ export default function GenericNode({ ? "font-light italic" : "" )} - onDoubleClick={() => { + onDoubleClick={(e) => { setInputDescription(true); takeSnapshot(); }} @@ -475,15 +734,7 @@ export default function GenericNode({ <> {Object.keys(data.node!.template) .filter((templateField) => templateField.charAt(0) !== "_") - .sort((a, b) => { - if (priorityFields.has(a.toLowerCase())) { - return -1; - } else if (priorityFields.has(b.toLowerCase())) { - return 1; - } else { - return a.localeCompare(b); - } - }) + .sort((a, b) => sortFields(a, b, data.node?.field_order ?? [])) .map((templateField: string, idx) => (
{data.node!.template[templateField].show && @@ -500,13 +751,31 @@ export default function GenericNode({ })} data={data} color={ - nodeColors[ - data.node?.template[templateField].type! - ] ?? - nodeColors[ - types[data.node?.template[templateField].type!] - ] ?? - nodeColors.unknown + data.node?.template[templateField].input_types && + data.node?.template[templateField].input_types! + .length > 0 + ? nodeColors[ + data.node?.template[templateField].input_types![ + data.node?.template[templateField] + .input_types!.length - 1 + ] + ] ?? + nodeColors[ + types[ + data.node?.template[templateField] + .input_types![ + data.node?.template[templateField] + .input_types!.length - 1 + ] + ] + ] + : nodeColors[ + data.node?.template[templateField].type! + ] ?? + nodeColors[ + types[data.node?.template[templateField].type!] + ] ?? + nodeColors.unknown } title={getFieldTitle( data.node?.template!, diff --git a/src/frontend/src/alerts/alertDropDown/index.tsx b/src/frontend/src/alerts/alertDropDown/index.tsx index 967d82174..3577a5de6 100644 --- a/src/frontend/src/alerts/alertDropDown/index.tsx +++ b/src/frontend/src/alerts/alertDropDown/index.tsx @@ -1,3 +1,4 @@ +import { Cross2Icon } from "@radix-ui/react-icons"; import { useState } from "react"; import IconComponent from "../../components/genericIconComponent"; import { @@ -5,6 +6,7 @@ import { PopoverContent, PopoverTrigger, } from "../../components/ui/popover"; +import { ZERO_NOTIFICATIONS } from "../../constants/constants"; import useAlertStore from "../../stores/alertStore"; import { AlertDropdownType } from "../../types/alerts"; import SingleAlert from "./components/singleAlertComponent"; @@ -45,15 +47,15 @@ export default function AlertDropdown({ setTimeout(clearNotificationList, 100); }} > - +
@@ -68,7 +70,7 @@ export default function AlertDropdown({ )) ) : (
- No new notifications + {ZERO_NOTIFICATIONS}
)}
diff --git a/src/frontend/src/assets/Gooey Ring-5s-271px.svg b/src/frontend/src/assets/Gooey Ring-5s-271px.svg deleted file mode 100644 index 6c3433420..000000000 --- a/src/frontend/src/assets/Gooey Ring-5s-271px.svg +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/frontend/src/assets/froze-flow.png b/src/frontend/src/assets/froze-flow.png deleted file mode 100644 index 893ce8f85e55d4aadcd8a1df16e7e662a42fe9c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11568 zcmeHt(9OgB zzW>2d$xv-VnR?W+V`dist1wC)w4qPPlDtf6vg$hxH>`_^aj`>)hm}fp(9G1Z^JABPL9fN(J+lreh zjPAj+;r-t*u z;Z5HOBDU#R7e`pJg+I8BFM9V+0?V0*-)ffNPnfX)otUziTGu$b<>8mP3vw`V9T9}G|9mU!;?fOFgJs1;|CC|toP5=5Xk&73Ag?9T#`3vsg7}Zg zvf;|ztr9!4~=8rC}B~y3g~%;t9l(XnXsK-2{|{^hppYj8Bf0;iEp|T zYV5dQ+(sssdoayuj*@)!`hD=z`|7!`=hbj}K%K!AvNsGtZ^}7Fck}5pPlhU`A?bjA zwRM6qfa?{2@%8w({Lt-TAPHew8oOI9$>hoR5k+|ullr%_lC@3Ht!_3dqk!6`j;;3M zM*H^TWBDj!N+Kj#u;$RzfJu`^+ohO( zn2H%b@zIgZ`#<$^d>i1*nCMXL)6=7}#(-CRZ(fgZJAX|rwP1E5=zt|2{m3y{*BbOz%@@G;>hogSCBc;9_mThj>Zrg(_Q z=#Ghumak8Vq*fdVJ204)JdYi_5FzxeZ*wvCKYd(+|E$w!e=Dolp!5T#M~K%CaY6^s zV5*Odv;}Bq5@ZBF3;uaOgfl;a3bJ@4qY+2~H)(lv1Yc9*h1I-u5*6!G2H4AJj{AK7o= zbFD@Yf0oNWayJ-tcb1pzY#+lOs_>>rLCcQCWlV_c)-MYN~b57c92O`QPL{_NC3#cw5U@?$&*g6u&ew$yxw)cEmbZEygh%H zCFQMxTCY9|K|`e7e$}xn&!(oe3v}|i>7*a0G<{@{_MZr2w5P0Jm%wF=7`;}f?-`=W7v&HIjm)m5CxF0?khzbdoHnftphT%ge-qH{;6ri|FmP%dm^SnyT~q zJNL(#qQJXteUZnunX5IgG8we70&yDs%9Pj09v#V*sA{@+8Pk4Qnf@6pq zc|fMyk*=hm8AtxQcw}j%*M3dMGz`g7dgQx z&jTGbC7=gqj3pcigh}3+<#AJ`KN=WypB1tf6o~z=YZB^nJNZ!4A(%5}rBqmC z_1hQ>banyQ$Vaq?t($?)$1Sh5&g@LnJ5M(O01KnruZBDhZd}YuoGs&$X2MI;6B_9A zM8iz6h6kE;sb)!$RKIY+QP(k96U-Ql2!2yhTd}5Q=Vl-;8x^uWl-EsD=f`Cp9``$w zY-4+_Z*uKy@$rvUPLd1W2M^<~>}CX>MapxV<*d#v)4#eMYPG1V%E>Uj*iv=o-I6YscXtnq%Sk5N%K*p zDBk5f+Ax*=Ez62!e9d&R7LjMj0O;)E=1kjJ<CB{@6)TMrG*iQq2i;b@QF6`IKN z7$>x;8i}Rw#j$X?bQ)7>hd-7d-p4-+pjoHI`qA*SuaheMBU@I0Sj&~!3N7f$sh^eN zqE8@LHDa=^;KyRPAndA#eMkJD&X?W;$IY8)c4)m1_V0>(HyD{zFm)ZX>|3+yEJsqX zCu|_euCj(v+Dw42pX9ysURHJ>XwxgFSKO7kts`sYy?5rJ#Kvhmrd#KtH{e?FNWY+| z(Y*=$Juo(qFkM1YG@h!%_W8#2U@J53inMU!+0Aa0JMRv^Uk5NL7eKJdXKWFrY~K9A zi3j(~^VK<^=uTIl8lUm-H{od`T->G#g?|V}95Lbc#M6)p|ApJt8h{o!t|Ch9ITVO7+q%J|@BTXc(iPzrESJBBR1D%21ZzgdP zJD3GW+}}RtWaGk*%kRbs+U9)9!g(;yN@vhL1n$l$zL=RwV z(ncaiD|rl+rpymvNyqL4JzMhd#}YRN*GGbV!!mAe5|}M#jEda*W{d9^`w1O1d*X$p z--Rb@ovRIOJ7jLWN(>aP5Z43{M(p$JNTC$su0#P_I$TC<;;4_mAFb~W?lkJdG9jJ; z7uF9>@qSI``a(X6&IUyB^N$2=5Uahv12SL0f0;^4XFSFTrw$`+wWNFpn>2vz~Zk5aFs)jr5 zLo*f{#%%dmf6RdU-ZN-H_uorJ$%iW~so8@Qa&glzH=@NCIZH2Mp23OXgYhM3gr7F< zB9_$>WEmTZ40CxaIk;ZIC`+ASe;#P^Wu_27bdug@kA4bP;QO zPXvSSPbhWg+H$m%HAyJlO#V1{jj}AjppUY1g_ubHeO>+B#b10*_Uf96=|K7{O#7>PgvDcI<;wZZ%w7P0wvvFt4uj!2MlSV>e|toljd?}@E0D1&|J=+Uo; z+2Y$c{C;Usak6%wFI@XEu6x4vZPAoOBH5-|v{T$mVx)?3Q@1I5*>-`RpO{aDC_kA@ zvS6%xXYQK^J;CG2W$D5(>{Xqr^RKvPN^RS zJ$`awub~?^EMAdDHTf%^pT?!1zl_UTK_{oB`lHn;b%S@WvyL;J&@rv3@7vCY!z>hG z9DZ+Lz!xrLGF30nd!6?ZzAh0wj;e`XVQI<)vY94=_=tvhp5oT-8kHR9=E72Ueafcw zObe?$voWwiuugVFD36+kifEGDm`igSMeYtr`*%>Nql}S3uq-E=l1ao{r1bg;EzgJY zZN;8$TF^s`Xv>WU@@Gq*?ZE~;`H7it!?oF$Re?34Rmm^=67La{-tO$)_jBfVHb;d0 z@`bZ(O}+Dcz7ob1Xl2exXn*9{27U=YRETh;Nu;zKlr2|bVvw@ zxm0bV?aXURM%*SO^O}wwyCJWVv*jnU_h;M`we8T;T;9@@UD3ouMVu;UlE+y)YE=EU z7*tlJ&fiauANA|Fy-tg1fNVJnI@8%*(KZWaJNeyyJkghrNS;-T>rro^3Ev-M2{tD{ zAc^|0HU2z@*VJHzxKU(?5i~V;D0{N)ASfWTR*bkm$?Hj4HRO6jXhSH8Js5dDbHH)% zH32G<7$t5T0I#+T0C)2^^TzS6xA5W;@akFvD6~5MKCSTb@)V-rwR*Ups z=Y1NjHfkLSiX0{irki1QNEhfBp> zR<30EI$mvjlSpW9`k0Q}Y7&mtV-edyakQdhD(3U{x~p_;@ok-P5X*dm+G}LU-TsYz z^JO*}gfZsPn*ywnh=tMJ06WHOs`P8bC|wNs9Tjn)Bpbrn+(O`xX+_zU-!-j4RQM+> z8Je_%m1!yyG{M&!#(7p70BDo`D}4kyiukgv=%fG`-mG4_9$SgdpHwf{5tdA(3HuL5 z=LD^({JK{l6Le{~!Bxm5rdy!DJKyD$sE}KWJI0P!iNJ|YfVX#UxveBHEv%PCT#m(^ zHcJ1W9Fq*M=Za>4%j>&!Z^13fRvaHcKxh2tAzlKR&7!`O^%^eNWw9GJjZd>afSWD* zm}}Gxj^`;&C?ab{8!0>(ZLwz2xG{NOt%35_Tk;bpbZ`I{L&XhSUS+~wcfLB0Gf^>Z zyHZ=*{nM^Bx3Glu%e&&_a)a{z?aEWFAtTtFSXQXAEV@>4Hcu!r4-=Sc&!7OJ-Vbx9 zR!h-bTpod1!%;1;k~9Vg64>~A0e7hO$CMFnOelvq7L4oj7dQ@tK`K-;9lVCsN=(6+ zj<;20K!K0%?U&mfl{^0Yb}^j2_(IWz@tgBRknbXyNpot9b;n5VK;Y}60y+B16P9k| zs^rXr#PJ&C+gA0sP1AQmNq+l7vRX%OH2GvdEup@-I5FXHJfX-Fb_@>|Sd<=3G}d#< z)queqkV_nJxjY#~(32gh=XE4m*xD?Pf5azv{rOZ##bsa2b6wm|Y|Z&nvccNGLtI=P zNDN`hT;U@|#W%X&ya`m}5RxwdihIA?&3OOXAi#`xPfgHQR%Fq7Tb4NSAg=!^r#wo(XED5L<0}MBi6MEtJ{D(< zMyV?Ld>I%YmjlyINKwxlm4jo$SzMVdV1`svDSJk5oXl0*xfpyR+yjgG4#SZjC$#u| zY}{v0)}?OMEW`y@`tn1E<@kaRmjozVB8ej38_X4sjx&XltB7?LfI%z{AczN7+_t0K z0)@>+JY=_@u2@R0@`=>|!G zq}AkVDXVP5E&Pn;&t~b8+8-8WlOIgaq9NUsuOS<5g~UeP8BFh*!7jpv>Kmp;N6*Fd z3|~AY2;||C&YYcbh*arTzBFItkY$pa@S<4wG3MMm&#+$Eu=f-#d6q{~I^ zKJQ0wiEx#c+w7}HwSN}^f-w5ZfMW$#VZ5)SJJr##KuFTx-7pUiF7LGiuM=9IL*bf) z=z^S<3i(pVA30axFImuFLuRbE0K;^bQ7!)m*NGV56r*PAv>d7*pd-_vx<0b z7tg1^e&JC0mg5z4V;8$(8}yEveG3DL|XwO2q3DNdH=>4Qf^B1w+VB=L~ zU4oUvebC8?L;?!VY{bwWZC|9l0QJ))GYAcyZ}6=-zeo?*%6Z=`MK&g65QyVJ_f!8( z;t((&XaSQAL$nf*5B6Nzge=0NM`f>o24Y zL@8z4kz$<<6K4>4;s?DWvzw{|&}dyE{`Gp~E3E^+COI1@tOl+_ETmoa0&kQ}etrHJ zCK?LIlYU+_($UQ zK~71K^-s??hic>2PE22xbfM?&H5R*rOxDF{m3T{tA5{v^(MHa>W?yYSl|%_(BkhIM6!v|ta% zHs|?!N;bw)=4fo$!U^@cV(pmL2vl=k=KUbWA9TT}WaVPNt0|O!hSrn;vJNnK-EgRI z>ab8-C-|gGeqEk}V?w&M=WQHtMj-I~dN9+1+Ae6yLcEp+09auSJl`z40qA$X?2&V<@wN3(QD{k2 zf$L9d)<25Uc{Kg$4*t6~?|eb0oX&8KO_`@qR1(nK>L4sd=~SF`XI~>3u47*g;GnW1 zXE8wTCq*eUyn-%!U6P37EaU5|xUqs+@Qt*FTp6M7b=oe`ErnVwH8w+yc{V({%*hj| zTiw1R2Eil=p+z3Wy&5!yv!%I$>MWloH_TCnv#;bF7N&7?eCx*bR<)o5@(f=?cbR{I z9JT3uq=o67ib1%-x3?$XeVapwuJV?q;;XC7OtI74Xjw@-7=kQH$RcYc6;=f*e*PRO zwcX+ldm~kbir8!MX!eUZvK(Uib$VUXGDTBf+08{GnJ0ZJU_!UNIfA77wKZrUxtzP4 z?5qNjN~CjI$u%uI`3ZE1S3n!vAbzIjD5d`mWS#zR@F->;`9&{y!@Kcf_@HVeOviwP z^oNy+JOkCXC@>LgY0v?Cnvb7qQv%_72YrdKy63Ybh0qHBk?&5)EGp&mpcxBlc1yoa zDIrd#So~$BU?$?Bf0Rz>$(3)(CXKtp-Seof7yOv|UBBM|TB@8~_@ zppkN)9C88uLxjB$`|3-V8TJ}_iWR!rh{4W_dqNM^60*<02I(ODWG5&qRYVKbU+#!p zNnSH1cIbxDM1*THS++TW;?;F~fodSbni=O}gNH?xb|p}g6{RpzQM#QCx1xIQsl5Nl z=Z`LpRkJm90n}UzIJUtza#MM`s?c3-@;w zm!UtYe-D@Rq048w3a=0xqtB>r-^(qO)NVb-|Yz$97f&I*pk|T9vS#QN&VZ}G6!PyLNn|*df?S+T($DPSgts0@#G_$u$oBO_ zSd&Q5DpB97np2Gk)?k@D37^{QnZsQ%5~5Hp!jpD`UI-(dZun9g&yWag*qUm;HZrN` z)6Qrb<`U7RwH-phzj{9~@ygrL6&G)^|rcnz{NJGnQ?WiK5!g~^O2O@@_@ab#sP z^$p)&8R!!A$juGkq#mQf6}3HR+6bHq)OueMo%nsRdOg=Ba__vemPW1HAvKW}xfk&Q{m^`{$z)}!Txc+9!Ow1wxL{%H9o-q?5m_1BG>3of&6E%xvf53N z12y%EVn6v*Uc%^drl8cJeO(k0eO11Xa3jU6h~;x?sycA##0}?u7CpiYQb6DGZ9)+v zm477Bi&<;ectrENZAmiLt>aY!i$TAQ44f`P4e-9xK3@>aY$R%c`IA?N+Rr*lHm!z` z?~BX@uxP_IuA@GpL@Dn>Fcdd{TSdN`FdKyq{3NN&LW|V zv?%%g7g|rcvhu;ka0_2GblgQp=WIdTiF<2`RB_!=y+p>Hna@s4|vX}WSo49HoXs4sSJ4h;8U2q98e0R zT>+!t76d#wW)IpM)0Z76Us{YE%wEIq1^c(pTrV<)ek5$2j#d8CY(Y00E~CUom56KU zn|r!lylIDp4=N11%vHf(KU;ajOC9xmqwuiFwge*J8q71-#={ z$JlVp@9r-6AVA}gSe6*%M3pE8^bixwIMpJko)yvR&r=$ zYLk6&E#D?zF|l~uFB1dPZdsM7V$P=0~5SB^i26z;TS{)+<{Yc|xzSYzaEF~=x6bIp)WCnbY_uXWSo zvH)q{#0V+zu&1C*)QR`oV*ljxoL!X3;cgNYK^}dBk|UE=n*D?s zYDg2_(M=u`6)qS+6UDApDke1I;8m%qc?_)i#^(htHMTCM#ELA{G9=WobKnn}Na%Bw zP9?B3A>EQ_ETnAlu%xd#-g=MHeQMbyOe0&-OqY{^wlX&x-PBWrS*7~1>XK#2d>;}W zI1io$o_!+LS*-r^k)u+abR|)FHkD6NuB6t!d|>!+b~}|eE^TYL+?i%ujU$Zh&ORRu z>%}N`3Pef5<4Bj7X-TAl z0ZAwm6HUuqCQ7q-`Wort&7mrOxD_$7ZW&znR?l$W8cm4TO$TtuNm$+0K2uSX$e_d@?W;Tt=- zNnL+O=DFW_l^5&{3!FwMAFpMx41+oR06@xmM)u`|MZ@Xtf_~dv1M@o>*zJA(o{gu2IHu;PY6ALP8LA}4|8%@}pEm1uJJ8QJ^&EKqR z3#z3*1OEsh0A)wvFmZCDV7^ThEO=JCe@*7?y$8ysoh{*DrtxpJ(C{TvQT^;t@zKo5 z%nqE&^TI=$1>O0n!Fo&g`q`MBE=a@q7KF{d?FIVRA-B4M%i$C+=h$`f@~WxIQN0>a5K&OpoI@Q5KY?g0{58WgfWMmSeMu$xqm4M)d z2=LUHf3Mr7WB}?QX0-n(f_|oy`ziU*?VwY4;(18v387n}u>vrx5I-xus>|BBs+P0M z{ynLofw*j}4S$(xp;IVTr%^JUV641KhLEW~_jCL>+aS*o3H{+e>>&Rf%sIS(@yW`@ z7E12a`sj?h>*(%%gg-jpoa%O9%$fZE6_%5L7--fDZv4fe$H;x!EHsh?C&IB7OastX zl3BpLP}6czW1GEneVmSIV3XBlhd>XJ2^4rJ28U9kqSPr!AdC-bL9Prp>$F+#|N6fB zuJK^G0-eivJ~isiANFSUf{v@B;mG`^uKjkhY9pXiqM?zl#{wUQg*||dJs_>k5<~4e zdGHi{iM)xLM{?%i$a{5X*A~ra&>mb>zT8ha2iUAd!7RjALAt-iyo$TdP32^PSvZN+ z=R=wC+|P!TY+JyNvT_=N5yL+ro=CMS+UuLC_;^X(yZ$Qa>2H8tD!<3F2IWZk1_dc| zF)oJs!Ik^`PQLe^wA2Uo1MTiUfTs9d(VbiCIR@cL9KGktPFb95M4`*W2TJ z7Uh2f2}wyD#Q14X;H2DH$z{;5Ud%mP7@x@YVipe!3B!uF3uW#9K~^Q8eXUS{NuZ|4v@H(kmLYw|18<+~q@7oV{(5PV5>vU5Y za(W(vf1l!5h@$x{u_asw8~0QY+lF<74@Cn;X+ngzmSwKVCx$fjlJu@Gd>TKy3AejB zq23O;+#TJMmHFN8Zr9m;qiwB158^Yf1iG-VgRzaNhMKZz$J_lJxvrPPP@7@neXeHE zIIA%YjMVAA)&V#0Ib}{BA4_UZ@m>Cyahq|`S&~H7v|#^{Hyu3dyQx_2_z~rjcA2G^ z|2CxiutJi@EZ4eMJ2q(Zs=ha}GTaaPJE*?FCT78-Fz*tnrjA_HzLQ%)p6SbXOu24> zUxQocnVy)ia-TR6_itc;r1$ldX0cIJ@jicYrJeh}-bUUh zyQtU$sTl7GX$X(cujD@w&BkPT@=O|^%Il?~2A2O{LXxRu`eS$YpJ|D&<90IanJcrv zm`YBBC)%E1VQp6A_qx^SDr7fq5Ox%fJS{GU1Q97QDV_%v2hF;;PD#(-iJfpCpB9i^ z<3ytrwUg8EN2A>a7j2(J*$o+z#F(Xp>G<0lBO5(zYLB|;Crw_Cbqn@@c$ix=WB2L5 zAv{@pFD1qIdLN{6{&PAZAb4qHI zN2kF8#_`Vu_fHy7lDjXZZ1;2H|0Ro(1C~?nb{cQAl)PV05&UDLeSSV^EaRV6Wk#tw z>E71BObtLaD+W(?x+u?dI++cRMu?f&pI$xf8A(dbaxgLemEExLz)y^vc$Gox)?4CV zL3BC7+oxLBTasE2{v5#Q$gH3AnEyMu diff --git a/src/frontend/src/assets/undraw_blog_post_re_fy5x.svg b/src/frontend/src/assets/undraw_blog_post_re_fy5x.svg new file mode 100644 index 000000000..96bcbea23 --- /dev/null +++ b/src/frontend/src/assets/undraw_blog_post_re_fy5x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/frontend/src/assets/undraw_chat_bot_re_e2gj.svg b/src/frontend/src/assets/undraw_chat_bot_re_e2gj.svg new file mode 100644 index 000000000..0d7af9195 --- /dev/null +++ b/src/frontend/src/assets/undraw_chat_bot_re_e2gj.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/frontend/src/assets/undraw_cloud_docs_re_xjht.svg b/src/frontend/src/assets/undraw_cloud_docs_re_xjht.svg new file mode 100644 index 000000000..6a0029370 --- /dev/null +++ b/src/frontend/src/assets/undraw_cloud_docs_re_xjht.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/frontend/src/assets/undraw_design_components_9vy6.svg b/src/frontend/src/assets/undraw_design_components_9vy6.svg new file mode 100644 index 000000000..c21e134e9 --- /dev/null +++ b/src/frontend/src/assets/undraw_design_components_9vy6.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/frontend/src/assets/undraw_mobile_messages_re_yx8w.svg b/src/frontend/src/assets/undraw_mobile_messages_re_yx8w.svg new file mode 100644 index 000000000..f232003d2 --- /dev/null +++ b/src/frontend/src/assets/undraw_mobile_messages_re_yx8w.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/frontend/src/assets/undraw_real_time_analytics_re_yliv.svg b/src/frontend/src/assets/undraw_real_time_analytics_re_yliv.svg new file mode 100644 index 000000000..32873b55f --- /dev/null +++ b/src/frontend/src/assets/undraw_real_time_analytics_re_yliv.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/frontend/src/assets/undraw_short_bio_re_fmx0.svg b/src/frontend/src/assets/undraw_short_bio_re_fmx0.svg new file mode 100644 index 000000000..95cbf86e6 --- /dev/null +++ b/src/frontend/src/assets/undraw_short_bio_re_fmx0.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/frontend/src/assets/undraw_team_collaboration_re_ow29.svg b/src/frontend/src/assets/undraw_team_collaboration_re_ow29.svg new file mode 100644 index 000000000..38bc4b3d5 --- /dev/null +++ b/src/frontend/src/assets/undraw_team_collaboration_re_ow29.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/frontend/src/assets/undraw_transfer_files_re_a2a9.svg b/src/frontend/src/assets/undraw_transfer_files_re_a2a9.svg new file mode 100644 index 000000000..c5930b9ea --- /dev/null +++ b/src/frontend/src/assets/undraw_transfer_files_re_a2a9.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/frontend/src/components/AccordionComponent/index.tsx b/src/frontend/src/components/AccordionComponent/index.tsx index e00932c76..fd9e42580 100644 --- a/src/frontend/src/components/AccordionComponent/index.tsx +++ b/src/frontend/src/components/AccordionComponent/index.tsx @@ -12,6 +12,7 @@ export default function AccordionComponent({ children, open = [], keyValue, + sideBar, }: AccordionComponentType): JSX.Element { const [value, setValue] = useState( open.length === 0 ? "" : getOpenAccordion() @@ -45,12 +46,14 @@ export default function AccordionComponent({ onClick={() => { handleClick(); }} - className="ml-3" + className={ + sideBar ? "w-full bg-muted px-[0.75rem] py-[0.5rem]" : "ml-3" + } > {trigger} - - {children} + +
{children}
diff --git a/src/frontend/src/components/CrashErrorComponent/index.tsx b/src/frontend/src/components/CrashErrorComponent/index.tsx index 0cf376195..57dc83d83 100644 --- a/src/frontend/src/components/CrashErrorComponent/index.tsx +++ b/src/frontend/src/components/CrashErrorComponent/index.tsx @@ -26,7 +26,7 @@ export default function CrashErrorComponent({

- Please report errors with detailed tracebacks on the{" "} + Please report errors with detailed tracebacks on the{" "} {" "} page.

- Thank you! + Thank you!

diff --git a/src/frontend/src/components/DropdownButtonComponent/index.tsx b/src/frontend/src/components/DropdownButtonComponent/index.tsx index 9491336d6..d49076809 100644 --- a/src/frontend/src/components/DropdownButtonComponent/index.tsx +++ b/src/frontend/src/components/DropdownButtonComponent/index.tsx @@ -13,6 +13,8 @@ export default function DropdownButton({ firstButtonName, onFirstBtnClick, options, + plusButton = false, + dropdownOptions = true, }: dropdownButtonPropsType): JSX.Element { const [showOptions, setShowOptions] = useState(false); @@ -23,28 +25,35 @@ export default function DropdownButton({ = ({ onChange={handleDescriptionChange} value={description!} placeholder="Flow description" - className="mt-2 max-h-[100px] font-normal" + className="mt-2 max-h-[100px] resize-none font-normal" rows={3} onDoubleClickCapture={(event) => { handleFocus(event); diff --git a/src/frontend/src/components/LightTooltipComponent/index.tsx b/src/frontend/src/components/LightTooltipComponent/index.tsx deleted file mode 100644 index 08ea76266..000000000 --- a/src/frontend/src/components/LightTooltipComponent/index.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import Tooltip, { TooltipProps, tooltipClasses } from "@mui/material/Tooltip"; -import { styled } from "@mui/material/styles"; - -export const LightTooltip = styled(({ className, ...props }: TooltipProps) => ( - -))(({ theme }) => ({ - [`& .${tooltipClasses.tooltip}`]: { - backgroundColor: theme.palette.common.white, - color: "rgba(0, 0, 0, 0.87)", - boxShadow: theme.shadows[2], - fontSize: 14, - }, - [`& .${tooltipClasses.arrow}:before`]: { - color: theme.palette.common.white, - boxShadow: theme.shadows[1], - }, -})); diff --git a/src/frontend/src/components/LoadingSpinner/index.tsx b/src/frontend/src/components/LoadingSpinner/index.tsx deleted file mode 100644 index ea02a88d6..000000000 --- a/src/frontend/src/components/LoadingSpinner/index.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function LoadingSpinner({}) { - return <>; -} diff --git a/src/frontend/src/components/RadialProgress/index.tsx b/src/frontend/src/components/RadialProgress/index.tsx deleted file mode 100644 index 5c46fd6b8..000000000 --- a/src/frontend/src/components/RadialProgress/index.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { RadialProgressType } from "../../types/components"; - -export default function RadialProgressComponent({ - value, - color, -}: RadialProgressType): JSX.Element { - const style = { - "--value": value! * 100, - "--size": "1.5rem", - "--thickness": "2px", - } as React.CSSProperties; - - return ( -
- {Math.trunc(value! * 100)}% -
- ); -} diff --git a/src/frontend/src/components/ReactTooltipComponent/index.tsx b/src/frontend/src/components/ReactTooltipComponent/index.tsx deleted file mode 100644 index 18eb67b33..000000000 --- a/src/frontend/src/components/ReactTooltipComponent/index.tsx +++ /dev/null @@ -1,45 +0,0 @@ -"use client"; -import type { FC } from "react"; -import React from "react"; -import { Tooltip as ReactTooltip } from "react-tooltip"; -import "react-tooltip/dist/react-tooltip.css"; -import { TooltipProps } from "../../types/components"; -import { classNames } from "../../utils/utils"; - -const TooltipReact: FC = ({ - selector, - content, - disabled, - position = "top", - children, - htmlContent, - className, - clickable, - delayShow, -}: TooltipProps): JSX.Element => { - return ( -
- {React.cloneElement(children as React.ReactElement, { - "data-tooltip-id": selector, - })} - - {htmlContent && htmlContent} - -
- ); -}; - -export default TooltipReact; diff --git a/src/frontend/src/components/ShadTooltipComponent/index.tsx b/src/frontend/src/components/ShadTooltipComponent/index.tsx index 62d5bc2e4..080935b6f 100644 --- a/src/frontend/src/components/ShadTooltipComponent/index.tsx +++ b/src/frontend/src/components/ShadTooltipComponent/index.tsx @@ -1,4 +1,5 @@ import { ShadToolTipType } from "../../types/components"; +import { cn } from "../../utils/utils"; import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip"; export default function ShadTooltip({ @@ -14,7 +15,7 @@ export default function ShadTooltip({ {children} - {children} - - ); -} diff --git a/src/frontend/src/components/ViewTriggers/chat/index.tsx b/src/frontend/src/components/ViewTriggers/chat/index.tsx new file mode 100644 index 000000000..9610f22ff --- /dev/null +++ b/src/frontend/src/components/ViewTriggers/chat/index.tsx @@ -0,0 +1,31 @@ +import { Transition } from "@headlessui/react"; + +import IconComponent from "../../genericIconComponent"; + +export default function ChatTrigger({}): JSX.Element { + return ( + + + + ); +} diff --git a/src/frontend/src/components/addNewVariableButtonComponent/addNewVariableButton.tsx b/src/frontend/src/components/addNewVariableButtonComponent/addNewVariableButton.tsx new file mode 100644 index 000000000..8dab6420f --- /dev/null +++ b/src/frontend/src/components/addNewVariableButtonComponent/addNewVariableButton.tsx @@ -0,0 +1,99 @@ +import { useState } from "react"; +import { registerGlobalVariable } from "../../controllers/API"; +import BaseModal from "../../modals/baseModal"; +import useAlertStore from "../../stores/alertStore"; +import { useGlobalVariablesStore } from "../../stores/globalVariables"; +import { ResponseErrorDetailAPI } from "../../types/api"; +import ForwardedIconComponent from "../genericIconComponent"; +import InputComponent from "../inputComponent"; +import { Button } from "../ui/button"; +import { Input } from "../ui/input"; +import { Label } from "../ui/label"; +import { Textarea } from "../ui/textarea"; + +//TODO IMPLEMENT FORM LOGIC + +export default function AddNewVariableButton({ children }): JSX.Element { + const [key, setKey] = useState(""); + const [value, setValue] = useState(""); + const [type, setType] = useState(""); + const [open, setOpen] = useState(false); + const setErrorData = useAlertStore((state) => state.setErrorData); + const addGlobalVariable = useGlobalVariablesStore( + (state) => state.addGlobalVariable + ); + function handleSaveVariable() { + let data: { name: string; value: string; type?: string } = { + name: key, + type, + value, + }; + registerGlobalVariable(data) + .then((res) => { + const { name, id, type } = res.data; + addGlobalVariable(name, id, type); + setKey(""); + setValue(""); + setType(""); + setOpen(false); + }) + .catch((error) => { + let responseError = error as ResponseErrorDetailAPI; + setErrorData({ + title: "Error creating variable", + list: [responseError.response.data.detail ?? "Unknown error"], + }); + }); + } + return ( + + + Create Variable + + {children} + +
+ + { + setKey(e.target.value); + }} + placeholder="Insert a name for the variable..." + > + + { + setType(e); + }} + selectedOption={type} + password={false} + options={["Generic", "Credential"]} + placeholder="Choose a type for the variable..." + > + + -
- -
- )) - : null} - {flowState?.memory_keys!.map((key, index) => ( -
- - - {key} - -
- {}} - size="small" - disabled={true} - /> -
-
- } - key={index} - keyValue={key} - > -
-
- Source: Memory -
-
- -
Xg)A-Z&h-6Q-5l9 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 literal 0 HcmV?d00001 diff --git a/docs/static/img/astra-rag-flow-dark.png b/docs/static/img/astra-rag-flow-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..60482e09aad207401e3a770218482492c556cb13 GIT binary patch literal 164630 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⪻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%0DrB2d$ zhgd&v0VrW>SfM<5IfX1hHZe6L>#E2)tr%wq@<-wrXvdo*l=6Db9IPNT2K?6jXIHXJ z>3uh)6-|YN0yDUG-Om2`+Kro)=Yrs+CPq%LELYbgmxTJT;A-}Sw&8uKT zn3qSbXs5f(?i$omm5QK)i2en_k#Oc@&fQNqK>S%-QZwt~I}@h5AHFQwvBl~QbScL* z@-~j+)|zG$(x3dB)W@Ft{UZ~&(K1f#t0_e#+eI^W{57g=p=&BPM-`5sepv1={>n!O z2huvoqfL8EBbDQ20v{SpF=i{0xc^$QY1q%RP|=XEw&#h(%h>e4_k9n(Mk!h!esaMV zM*oR4E(PP}YSFwVi*-^Fhoy4@PM3DM@1{y6KH!)T`P5w68cC=)1B3;?`I0W4^)X$T z5NCX(L0w*tM3gy_fZN`NKW+YVKsrQvH<|bBR%`c|Pz9+Fp}h5GY;KIYGa@I?@;LkeFl@WYhCXPw1O_hIxQ2cv-#R}XAWDB{uAX{Wx_Zl z+aKa744@929RF7CzK~#9;smlXF!_=oY2NKkR!VG@`}A@=9TdL-Z$C~&m3`*F2e<5RcC3f>T0cdv@P zX8Xd!7f(rZVbALE@~gKjw*OmIzTT)XmG~%Krb2{7X%ozHaBwd`i^WUi{p`0czKQlU z#EQlr??0sCe)S6$86E#U{SO4xW*iz!iZeRfFcwrRLS`fpCj)h@pbrVdfRhIfp+bav zW7)3q#uj7etB;Xi>LKTcwzlx}-r>{! zAlDmMF{AS&FS9u$y0A=S18^q<0Gg zO@Zk;&nIYX2=ONWP8GyxW@?&pEsYC4#veF!)9~HB&J-MSR=UQv3pV!W7xq>2*B7qe zElG7Z2#!fg69nU>4T+LdlvmxmqTnTH5Bpe8^`d@~mJr|vARY|2KZ03tT{^$lT>|vB zYeudQU1g6C4viNyf-JxZ!%;Vub^buCn&cEOy{h1E~YHmBM&712e zF849bKgJyQT3t(1%bnbmcZNbHGA5J+JdQ(u)d6)08QB-xdR)8FcS9fUB>p@h8UKIA0)%YjrL-pVN1rCuSc0JG+#6|{N6=j7I;MoZ$(;$CPN4D z6dsLF4{%8G_o&WdE6#n1>Q#mD0^?Xno7v^O$J9ZA$-}md*7ex>5!f4YPRE8l;oK%} ziZPvp+<`IR9~3l4SL9WBQ$-1L#w8$NO0j&Fd?gIMHC3WKB zI#`T$-H~fWZmMH9aLn7EoiXAXMlxO*aoddy^)i>weQMmCu5>pPh7-}WGYWI6Clkl zxC$AS8OT=n`cH-&x2{c4qN$dhm9`hyxHEr2-MATSZ<|J3$dmbENhT#F9bsv07bZ3) z00vkq_rtWbe+=?fp)M~MCMA`6umEXK(wI0Q-nqSvDvDNH$`^YoK-)z_6crnrt4~o{ zTKcDD`wTayrNwWXdPlUdJ5*Ff@mN(jphiJo-(S{Js4A0}mR6y(f9PYyIqvt;QVT;N zjTNO+w~wSYucnI|Rk7-rAoob`VQ(+@%frVLakn2oB^BKQSy5D2ZiJja9QGA0@0X}k z)vI#EhNAMLPvjB*;8*kTc)ln(^e&QtgURTEzcG$Yb&Uql_s$GD7S^c)>^NKIFeq%8 z6A;RXhQkHS!Z^~zee0%+TFMF%;Uyp2Zs}x}W_PhB1p(MZ2SHExqg(Np@_(Wk+fM3Y z23A%%&r)ro=M72r3l?KUM2V(C9VH#92Y6Y#&vBuk8bbr_or{~h3>r1?ns zhFDOfvpH1k1Xi6SOD+Ex<$3lm-q}hf(hh-&X0@ z&B;jeGBZWa)0bCA+5u^(x8M<9o?|-@*1J18u9%DU3)IKP% zrNyj_U(~+QZ(K_UG06)ONcppTx3!IwU07rHk82Wz4wQO9+Fa7P3;Pw3?eEX7hfyq%)(a9yZT_;7a`$n>?_a$Sew=SW#6K-dT z9{x$|r;ox}VL0ntGmO~+Tnw2LDn{AnXn4k`k-P7E8ps7+d)OtL9#;$M^3qYcuc<>s z#k0DVRt1RHQ}Of{Q__>8+<;eS4aSERmCKA%*C3Co<1WftI$%=&`aLsa_Dor852F7w zigG`SoJ`(aJa!oXkhAGf-U(fqY%1hC-5Qv?@oDBK(km>nkvM^T_K7kH*;dJ|B@-?RRkV&TJZ#?uK~X=prjvJ=p9 zEp+RCcjDh5C?}_VKzUjANJgk7=Jr|pa(g6KaQ}nj*ki-0sBq)}4mA(!dng@8Z;mfg zfZE)p#qLeyG0oC*xRo4|np^^%W@kK*0q9d2Yg$}vvN%Kg*Swpmar=f#L9-#~^c5D# zMQs1bZbS~-SDL0{_!X&c`KLuGZ7LdrR*lPZzLo4YF?;7VOMZHfP8F{4WWWcz`aJA` z4Tu>1>orFa4Sfz*+Xafjdh8IPjhDxb38(E{W*Yq_5j9B|iL-fG-&wo3q@+yU;9!Iq zJ)cGm`78(;3~vt$lD6KDiP*(l@NE}VD%j`J9Ojv*7#|!Fmsg_%e)8+?-h0_gTz$G*ln3>t_f4pC8w!_CMQB29Q0C2MUGA5b+Qu48az zQllC!7@6T5ud2p#dP|eq3*!ZkmQZEDxl8c883QJf&1Z#zG z-aPPEniBjOiSF`EpcN&C>;8BdtmiJ!fQ5&l(-e4kFv@zn7!huE_c?+FVnzK9GwkAE zjJ4bvFlOLd)4zI3%?Xpi&JZ`Ab%g2yr*tx;qU1?iH~&5U_QInQ8>hpA_GP5?8Kqvq@p$S2V#D0ItW90P{ZD$M#kCM7%@26p?Q8hJ|eGPG9!H;*GPZj zlh-ZS;?Ww(1Bj2`rTD}OJ4?P;YwA+sY^rvG0P_;!P5e5&Uf#4=4V|Kgm#!}#JTtj$ zp$0D@q?(lx_X z!5N_|^6Mb8f<(jGUK?C`bxlApRwZltg!6> z3!BCqca1Vp`bbq+v|0np<_u4qF>&Thh_0-G^fqffg?MK&kyED$5~5Zl4v zXd-zyuOPZ1uT#B|dbP(w>;ZXsv?}j9zv3(ZO74O0^!d#+@!KN$8z+|$B|ZPrE40XS zT~77&9N(yxNc?P+T}#>9 zFeZrZ$4<4JGE?nl6lWXcifeoJAW{5}d%N!V=Le4N0@*U=6GnM>+t`SXmD6`cEN1&_ zo+)+R`-h|13%GX3UmX6+}c8Y1ZmI~MFxy-ldn_wtVj}H3NXq##5ws-Zu$y!S1|8yID@YL&79aqZo^ z>8|dbJiEV}pI{pAL!G2?$)&ya5_pZ2?&%thFSiGLoe$%0_tV(4^68fz$V|;kc9*b! zQI!jF1r0Y|i)rmdDM#a@j<*P{j&}taa|H1m(mVjYZ_j`PSO1fCRSl77m}X<7$>Kf7 z0XP38m=`?my%~S7dPQS7dWa&yh@m(=8vc9B#(UBCEiB#s(!<64hb1D+{6NOJ@h&;J;3~bbxBeNR<|6V2e{1nzHWG)| zYay1TCVtCGbOnDG>fXb;(kUbo6WA%CQ;YIL>JM7arv3jPRx7>dWzNab<=+if*8k3) zmq$h|RWvgri8~=Kne4QKE2&*sUV_Ptr9^KxRSiGzO zdkY+M&)QrUb#O*NK*5THA;`=XZzqPJQ z{kX;0pp8vU?OXRqp1XA4nHBQ!?-svEt~ucrRclTTbZsg$*@d54RNt+1`Tkj&WA-y^ zmPqQ>&Jhu0WPJsl%8n{FG3IBb&98xWdjGDM83n>W#1Y@K#K2hQ$LT3Nk~AWNAIF!J z0&VF=C_sK0Pf7ozgmE~}zq6W$${`NpVadZ6LijyQcdeQT> z7_FQ)^z$=}O}uj4r|iOpa4hbJUq2b=4oaH}Exa0}1TERA>c;Z3<~kX{CzlZewCZ+c zer6+}tllQ87XE;4va6ugZ!`n6M&4WMkTX&cfCI;A=L4G2$olt+|08T*T#!rDS8Geg zyx-*bR~=w_h^x}T^jEuw2k%|!>lVSmw<<9;Ut_xR#0Jlg(D+< z588qF7;mj!@Q+A4%fFp?d}~AuMu>EAd~DX%?fS}BP4*jy(ENtBtHGPAvZMg^Vu zn^qErpNNhwe&gP%m7?yfrh^K}jLrX;=-gR_sBP<>cc^ll5sS(6CDQ%^e9moTm|L)m zYew~R=o=1c!GX|0p9uWfN9WJpucj&I z;G*#pV*TG29wMnQyfy{A1HEd2r)x5NprD$TpPMVKqvNAEpPelrDk*uRj2$T8(vTFJ z4nzs1?O>0tIb2imXv%e%`4Ey+MW1ftQCT?c&0=27nvCcD9}GB`Q1BZ8s7@D!|``yRBdP3b(iY z-4Si62vn<_(Yq_fe+Ef9#mE4W3G0wuRELpQjKR}v1F?jIuRm4RSkxkwO5yU}8aoQm znfm(u1TlAcWu@TN zXr3rDln;V}hC&tkV;8rldizP%i7v?0%DOFEQr>0Q^{^Y6QiqHr?e?KaiDi?MMZ zC@-P7ax-}|73&?6T)4}KhMKJgL^&AjZyj@{X?B~NRcsWxdI*-&6E+>$h=ZpY9qvov zKr(QcA=SJb=={ehsctU3_i4Qq4lb~urnF1X#>yGCjnnRnb@x&kb6d_U(MSS%5i!FJ zJEVaUOv4AN5V0jc8~3P%PO(%Of@WqxBO0=U!9xPfJSL!!{Oxy!8aAfS^YcRE+AeVM zK8&^{>GTpe@boCd!^8g~x2rR#vb`+KFa8a1Dvie{uj>kme?f!s~aMlaNkmJ)V z;*{5yD{bR$n<;H7VKA!OX55!H#W^a56L-lum|_(FNfB}9+UDb6gRrm&H&0`a^p+gt%nWoF*KQWe zAPLXd=LYF>z1FYGdO}uqYn+-h6cdh1iZ0sXqb6Hdis>V{z(4z&h_n(frH+hpD>ZQbrDi)O@(h>XQ82y z4|w!lY@ptb4_C4y;~H>bHrhX(f025;iqTui6takbrt%>MIdXX#C(tn&_F zYxdP5xWJwrlTMI);?($w0~|fpe%>e5;RlTdjPT-4gx=chJhUp514Z(8@}~mfBVWqP zGN+HdYHiZ!%F7Pi+)5#SBiH}m3m^eY@{I7O=ubUZ8CZaHE~C(GlP9g(Y)+J=UBS^}PCKaPsEFcfhcki$?|)VOjVznXz|HMn$es};kr#|HkW z*y7n01xK2gF(LO`0p@0=_V)?|S0V2Q6wz2Gq3nLrd`TFhtfp?oFZT5{2^1f$=8C{M z>XPiEJ%6_#v=f~GWhPo3Ad?R}akKTaU)`bc z6jIO>T?`S*sKl1X`-&OiN81WRIvA0kIQHT{G%(fymMX|-k-2>Z$}f`SLFo}&4x0?r z%KsYOg4R%pHOctB}= z9oyzQr&jKWyuiSf81m0WgL`}J;)7;%(^nRB{=#a7uix2;2Dp%kgNOn?If^FrEsY2>{`0wQ84MaJvf(5ivl zf&=Vu7#~Zg*h4`(Eb&Ld_VR)Q-?B`qmP9k^K;CCd~n zG`hO6K9slhAqJA2Kd5iWTP7c%4MRHDj;2w2+wZ=jk7;e1v3|Vke$Rf2t=o3EwR|x< zE}%{S_J}XvK~spVJriOO2+@`j&|S(7MMe)$AcHc)e1m>x#TK!9eqUx9Io^htj=^$J z)mbk#q=!=7h?QX)-lX8d*RUw04pRFbm{PGD%~c4aP;LNg_;zA`Jp1J-yl(%3nfvS4 zw?w^E)*K zRW_i_x-oSuU9nLsh3y2H)7km<6a#r#tY=*66U>1 zUH|?)1|=0$GVa0Qkyh6QR`Fi@OUsR&61pT=>A)Z~XwEs`TY^cK%3ay+W(yFP(OcM2LzngdS@Kj->ef#;t@P1C{3;o?2%l(b_C{tszMwBqT%{ZoGOvzqoaS zgGt(|JdSGq_kq#vQzTQaW`k?EtZP7J(7aqEukft87pa?OjkKa8YRl8?E<5>-P2(l? zs;hcz7>rF_@;h!F1&ds6fHwgMbRbC!|qsz+^l2v}* zoX?=`Bh`8Q;^|Lje-K5!ws(?olq96?_WU74mWOd?8(Y1|74?pvh!6eD4OVG?BhUT= z@12wTIy2%%_J-`ki`R3oW%Gks1|8^$^A*l7XMmN{#3=a z%=_hYE8$(Y6!~9T@;7Gx+ASg-EALiNb?OBY;f`!>Tf;@Nl#Hk;RS<7*?ke{aACZ?*XA@Bc5#)#AwxXFDxtsOy zv#tR@6rCR?phzr7=QHlq9x)kya7xEV<)pKRFG`Y}GvNVNo~PCu?FX-W8eql7lGs_E`C!r_ErvDT)w z;)cd^6SOM(k-A=br&EmX&6~40$mM!L&Otej$(N6h7=r!h)qLHh+pbtJ*rY_zcvPAq zB`#d&gOT zj_n!L*$B=8BO%#RjJ(gec%7bNS%_0h%#hX$avv_nK?7eNU}&=3{)wnhzQp~u+1z+& zXKo(bW|fllr-=z@7ZOoGQ|db+X0XdO7#2 zhDZ>_s#Kb?EZaV&Q3ZXlOrEwe&ul3T|F#6YAybpfr4Q`SVay82XuY;0y(?Gi>PkR8 zVTIn#z4r6va4ub`>fqd^z4BXx#t6F@HvJ!sCMT|hG<#GbWk}!gP9O?$>YJ)3vqVDGiL0*+`|V*lZeUX;b4X z!dA@>Y*>Dn$$&CO`x|joa?Akzvk2wDJng^X9l28Ei4?A1wXsW=nyN&%a66!VL1#lJs|3GL0g8p;}SdaA6<%%P1c6gh*3>!c!mG?>vF zaczD{J1n6##~b+A1O#b+HmMBM(M-+`%7|-%wr{_)Q;Ug+K!*9$889LO(QQl_IHfpb$kg3neq zh6%aQ%9w#RH6dlNs^rVfH>T0HR($=DJ-P4_q}EgPemIEySTiVYN}TfRJ52>k@z1-VB|23k4?x=%F4U}ic_59Q-{`4v2I*XMJ5$7^-v zOg~Bz5@W@^o|elwcJ@9Tqcvc^lLgE>kwCu2&c@cAgQN6w$^2h*b+aj0IDSzT8yWeb z>;1YcmRLj`6dVzdZt-yv3^o5`Bbmt|K;yL;p&T)@yLcLJ(LEr&rcDAin5{* z>+evHG0{4!yA8hE)d0bo=BN;B=<$yw_LIGXnv2$!X69yJKK>&bOr_2FQwq*aau(4F z^Wkw~i=`?R7={qtJ8B9N>q@iNm6CPTZ+y(EMD^$!Q24F7bxmji69fYbeMDQr!>VVX zb%8%HaQoD3&Z=5=^OFrdx;EHwAat6X=SPlj`;#CMV390neKWGZ&~b{TZm7l8Dc0`R zO_VAqcv4T~7nhsVogwq49eDk&{X$)DYsXYjJXi!`uRbRT1}Z=4_-{LSFi0vL0b^RQ z_bT!VlkJ+Stsg8OAL>XE>9j~`jz`%*0&_p;S(zgrI2Q`?3unl?LW9BiiF*{aFcFGb z9wkSm)02~89-c8qo#cL+P~jmJ?$GZ2O#g61fC(8hYT;K3@ExYlysUM{90T2mfW!5U zCb1k&1x5WI-{dKkJ@B2M@1Q|&C*OlEpgLGvyvLvY-T;f~4{#BLh~o7qx@hrd`ri;D zBJdq4u!4T!zm(f)Qq(=6Ypwr$TU5a-QCiZ*R)2C@(gp^H1SjXHo!R@oUFuS`K7GO6 zGtMf={aUno{_Xg2lAe2NtSNw7UM3nn)$40aR1l^Pi>upXVfb#c=5NTbE6)$g|Ef*k zkbf&WchF#>n=J+E-TqgD;-iC|VG}mBx0Hd;U@)NlpAYt~PAiQ1`zfi=jWsN233v?& zCzmJLe4a4L@OfQF%hE7Hgse;Uu&9+5%frKvrKt4UDB<6VTr=>$UNv?Z#$DqAwowOm zGx47yZE$x?%M_wCnJ|^1s5hYPWIztQMWorM`?XN z|F!M^Jxid)z=x)&U+B549lgvNIC}$2kU-x%wqccJ<$)VCB=j*x?e=3ISWZ>y)Ity_ z%SiA5j?)G79b%>v7lvl&7)EYtED z3j0-P>h{xRi=DQD!2kRc26Ykm=L`7*4RTK`&hL=7dxrLzi8t(AZAhWZOk3nt>>svj zy0pYvdhCdIi8v|}4rD{m9n)%u%+da^14E7Wa&(8w&$bcPVlk@}flLu^`2QwA7= z5U$@{Y+G>)4)Q)59Ng`ZwZ6}lMcQmZwz7ZHSpg%g^J=aVxj*!sfl=&E=qM@z**{=3 z|Aidb|05o16il#XM??R(eX8{z428}YEbzZyJQdx0x5?R>BZp-7?V0@_P|%)A64jTE zp5}Sd65u?M8Q93_dNgLG;*2Hm>u10HA){23Or&C)uBGkRRXn;Tm3chD?83m3a<( zK##ahd2?;$m2lE@OQ>39&awWWTQ<8qEp&d40HiTkKAb%}?E}K|zes24&POuS@lT{c zrO)igCn}nan1M)-^madBd=MZGmMk>czuGY?AIrCVqG`EXVm=^vzE`u%*Lry(_jj_q zzT=udl&NGw`o~Inm$2G#MBhW+_bzNx=H>gG{Zn{Y>JV1gga8s6^cLAiLe!_FaHP|e z-{_-cFz7PlcJnPt9v`q1q=n{f$`AIiC5_5gznq^;2Z#*}+X3}2OW)|b8MW5Tt?pt< zr)OA9Y%H-fte}D&o{vljZ-W;iA_zWM95M23S@5Cn4n1!%ErAq0pF{_NIRw_wcOurh<5Ci&4oBGKD2F>a`k#?TzX_o| zZR8IeEJ4i;l-62Nta<$>PeSyF0V>3imn>3v6zK@JaIJo{5`@ z1ZbTq*<2%Q60l4*301R~EX5}6`=ePW*w;4bjS9#KFOAe&(aHfQ}0gsmrg zhhDd6rmK4gFD&~ASCe@Sf7!oGOj|U30n@O9-1l4JTn>aej|X2xm#-D%+b-XUQmF6` z^1hbB22~;}L%{MNd`IVMW`Au*mdJ{KliEs;NA?sg|3ksNn^|AVmSCL685yT$7sc9K z*S-z(59c7!tpGI@O2@p_r+Z$2T>@LmYxWK(&{C!*_2lL{IMvauOp&Q`I`~sQ^znJM zHL|o1R7XK><<8wsn}t5udVzl%*Vr~~VsF$2{!&Lc3v&ZhkAUa0AW?uIMs2NwIGBsG z1v{@6*rA57Vb1(l{!f4#QlngO%TdfkaX)$LC7AL2L@T-<;Pkj}ls*jiS#7CmTEinX zqUFqu^STTGArcC5c#xyWA z^5+qt$vkW%v~m+)z#)G~I8Q&fqHpD^^W3+@VyX*nX)9~Iam7Mh#fe~85i}H8Ao<0< z`Wwj1CMJQ}H2#Qw?;Aqjntt=Nu4%etpoTHy@q}&hl<-LTtEF)v@@V{U!jDO<9Ga30 zdhhaMA7Caj9?rHbJ{%q%8=X|hUC_ubzGh_gLgL_PZynt2xNzU!ONBWB2wGT% z?pg5Phzz9u-wy!$r=34v9`?G>@U7gq1Gn$9$;9?++UA!wIl%ATB0Yp%Opg~^!~&S? zG1my5w}~T<``;|i#srBN86&Xf^*qx)Nn3pesvKoy@RHl;YXS78#?zX|t!?_KG%AMi zpx4!|h*$nehac|M*fXz_8Amx{*sI*@INntKvqs49P)_RzYZdD(*GjzJ|36Z_1y@lg zGG5N`ID;;E=+r7h!us%dmY1(ePdy_6zTQz_c$QAq)SR?b96mZ|oI`#5cR0b{mf}dN z2Qu+mYWJ;$PC+O{I_H7Wudp^JQ*&YJraaAV0+VS9y%d~elky!{=;$U$3d4kp0=|5i zq)<|J-#>Zde~s$P^Q9&wO~b`Y5$}bLgh5jKUTYUj%dF}+J*?kPoptMZhIL?Ol36mz zI#HC;Cb4*Ok9u9llB|&MR#vaUL5rEwgjWW(B$P%CQ*coJvg^MRmu;^vN{Al0gre3P zqTuFE6?E>FhNpHN>eJQHIY_z}^1Y zK_7;{{_V@Dmz+6`n)j{h@d`fg>p2=Zc*OIG_qC9_CJHFVD*`j)cMN^oQPNd&ayA8O zd0#Y_A209nIdNWhyLU4xGe~AX&UzaT5}>%wphZkW_q;7__jsAdgC?bQ^9)Y`*pTpIKFWJoaYH z;wVMBS{Dbrn37W6B2!N|U?qgw#s1?t5Wc~ttJ?_oa$%qumvDzJq(F>S6C-I>(MjlN z7OT9O_efW#497>wxrX##HI7R+b&!XpNt%i#M&hgw&d#*?kgXQ5A%7u>0+Kg|xs8&C z=NU}fnM3b~!zy~Z@QuE&GEiGNdTDEO3&4+>Ma3~zW9%qz8H9bj-9g^%6XyIpKuZvt z8`ee)buZ0uI_g@YC^r*x*J5Gd(i`=Qf#+*1O0LT%6&V$?g)ixC?C}b9CVfR6)Hg9R zJ-DJeR3OJ={APUU|M$P{&k|cYJVMgNGuAdz+TwAWK|6R?`!PBAHa&S>mUU zEs|&+#J8>xRp|U_q5F`;Q&}Q3rvw#RN%{2v0$Nk%JAgdYJ+wc_JE9nGaa zzX&QpE&yvQxOm=&pqVH^5-mVy=Ibg`#C~r)plx{&7(Mt&+*YKwAxIlb$Hr6 zL1AF{>v(u59;2k#;n~uG?=WDpvUD)JHNOK67z=1zZT<5+_R?yQHK|R9?$GY{f(Ygw za&ohK2R9|^p_SHmmFH1H)e~9vB;cWUpiKOO8US~LzmNt}TIRTT0=x2OKo<<+F1<|@ zu^-aj8mc#fntd=)7uOKB>;7E5^UJWfpg_eKbnH3(50Lhn`7vuG@*0x0;X%^#LtUE~ zVB<9E--ow0%Vd@0(9r|2J-^-)WoSRO>paI(We`I|HP+Z;8Ev_M00tucFB)Gd1Ab4=M z;O_38;O&6ta$h+d%Ro@a@?YM*_rXoL$x2`5i)`~++wXFf27VS9ST!zz4UTmM zDw6<1gQxHgEUg>Ec*~#C<5_f2S2m?hx-8MRF3#!ACGsHWVu}~IyJH&rM^w}X7S~R0 za?wiQ^b4r_KSvVKoH;?+6<@*Hp7DC7=)X0AgLSj3t$&d7McRtm)bb#GL z&cqRdrCPngx99qmECO#yzWHF}!t;*!qU)bL(h?yq-oTBir}5ozcmAj)nUUQ~jqwja z|IfE6k(|TZN^@}XAn?2$4p6JzBO}S{#*qK>=83RU*b!%`L)9L({C$g*FcPc?9*=;WmitquV|s~*E0mZMF8|~wgM&PB8tNPGzsaex&7~3@sAs# zK0x{0o;e+_a5=tn$Ncf?8&=9kIH0{zSU@{tN3y`g<6tLvv~o7_M(e!YqPlR6C1gdz zK1C$PD#kGJMVqOkOB7&5h3xOAL#)<5V8<$Zona&>*90N)EdDlF)S6b=o{x7LO-YOb zniKjnSYIV2b7tz~2uMg$YXu7ab!q=z9yknt6-&8wzCEf7H}sP1rJ|%bGsSYQk*3M= zdlZ3BI78>q6Qhs30x&J? zPbkzP!b92mWbLr6tA2t4-CgnjtZ8*5jDvUqKtO+QngybG^KifV2*1dgPRIqxa(qwU z_$2q*SWnD)8?c#*BQ!q)*AHKx{t^V%`;-+S?_;+)nNT+_B_+jF`{P<@LS}r?H=QOg z3VOZ9!7(g6mmOZX5;^Wnz{Ry+3Z&qZbpN}pFfH$6{@y0$YJMcXRTh4CwliQSC`M1o zktBuBXn4~aT^nL|-3XaVa$T)Tjtq}3f_C8$Y?A^LcvOH(@xsX-iP83!qOiheKo=pM zhj+obBsGcEja@*N_A6{X%BP}VG|~~w1H=#<@^FffCeKoalab!PEg0$M4P#QCq^+|n z#G{U5jTt;qNA-FaPC3=w7s`4s{CYpXPt^i<^lPbdl9IoA3zOpU@y93D);iz_K(AD= zQb^zc`-v$_Aqya92TDOqthstqd<_u)V7MhP?_s{Z&+c^14Jp1TBJqs?U~U4B?SmHU-7JynQ^4$njvud2xF zlV#Ca-Dh);4PaDZwA?2!jernn>v}6|D9ADLJtXw`CgLPM2)texERC*%;&&e*bE-LRzU{a>zEXw*HwMu~Ma(qC80Mc{KWS zuHArgdc4O=Ai$#pg@pW8MGA#u{jwgWQnEKU(M?B1x6@kRk7~L`^+8q!*553uFfl7u z7H>xOSD|U~W=e{>)Yx$0@87$hYj%BA3ZJfT0xL6W&%89f_j&HO^66{7v-erZNt^oX zyy16vmfs6^^@+@S8p?N?2hUE8%GW6>?0sz7=}q6A?|WwRcchLaI#|BDI{C)R*n>x} zBWKKqN%Y_q^v2Kqt(eKM5Ej=N9KYUC;7$68;1~Ymm z4zVfh#cf}<+ODwsk5NX&-yJ-h0PLBzl>xK>vnPX?dD!q?x4(yJA&IKYZKpQ#eZ^gkJ&(NuA`J(UHBTA|05jiz2?WUylW0=jWTuXL$5RJVv3_)jyu%q=N2UE^0UztVuJND9LGb66fVrz*SkwfsPLPKxPZNAWKNU~m z9iI>}V8*L5dizb@yMRE6YqT2O?AcJFxW3V*i_5?YsneC{gjs^yL+Z;HuD?BBDo+`b zMBGm}n7FeXgH|!DIuSu-_YD+>=`Q*E~t=w?O zT656p>#8DF_Hsbckzu`kEBOfTZ~jAFSy2kW*J|$0OMr%wj(hVcoY7?P3l6*cfo3qO zDvC^XkFNBv)A*-+4!ox;U@)hY%!>5mv=O?2PFWs(%g<;$kF)=X(RTD~QAnypH zq@u!IlFD_)3>j!BoOeT^{k{}D=3l`b#~!J*>KWR0pLsH2$;dC!c!y{qe06=`tCS@t zfq7IEtc;L2SD?%Qf!60?z(&IzM*w(jg7_j2zaZOtmnvo zv|O9H$dDK6duB-SicYsCMc`_l(T=6AUD4E&*Sh5tXHdVOH++mw?xgjOAhXsU*ZXud z-RX%Uc>-SW@q_T^#H6fFXXHd2w8!UlHO%qON6+0Z>GHMlK#I#HT;IH#RiD67ph&%0 z@rdNmbEl^_DQA2)SI@?-=%OpIeA>vUh)Wg3Tj7ciGGwf*Js8bNm}cAG#DYB-<&!w8 zzA&V|Od5|3eArFI&sx9cn0S7KlJGn%$zDz%pD4bi?dZU~_dXd>)7W#NwB9^8;LIoy z$n?c@u!$1VD_055`Z7S`L&Btyf}K#ApD`^T9gqNr5hiUaB`cZx^}1(V@-RI+xyUE* z);fJ+L(Jm>ChOqx(rKR~6c9|xxp2Wjk6`Kh?JvZj0Te&MeiF}MtBrp?XQxY015mVbdb>!Xn;e~tOG7xG9(}lbo6U;R8j)WkCZAtz0 zW_aW8q9W6mmg}CmIZe=rU$1yUMUEeT$^EqFawBn{o7>nA>b=w1KbAye&|vcy6{m{II|>Ks zpI_KqQW~nQF8RvIY;M04TutxaY{pUJ@?$V{e!jDI7$HhD(bJF!(a&d zRa#j!n1dM+)3G*({0lJq=Z2#ykS+-jX+DU@_LxT`>}PwAD| zjw{n^L|(6guB(yNxoE|jsH19&WHB&^o>_FS>TPf2*v~$gs@VvCxMG^YTzMdGx{GT5 z%*vbm)=6Ss`gaokcX$hJ%u1Ytnk&-@cYGZwj6HZU>x4R%lp43V3oo*ufcwE;0Z)po1)zp= zV5Si6oA`k8$Jy=ggPz2Pa<^^gfa4{2ZD)up zHC&%uM3tTU{c7uL4n=V+b!wEgc^BP_W`btU3z&qNloBVDLH5Hjr>`UM1ePqrmPbcB zXzrJ&-H6NXC}^~a&raQJgOY2B~@^6Gp4 zu&PZf3?FR_*mYFbquVdUhCYj}j?FwiThBhl0($Oyh!nHms7RiQy*AAW^z*w*l}2;* z@mM&I7eo?Ipeo>RV>1ofy`s1luPrvY^V@xe9-Uoe+1dh_2n;TAiNYg(=%-?A@jSBi zI%F=rHI+5v;oz6pwk09FhC)Rf*?U;tyI)gvP*K4~z+{En`3Q(>oUy&#H~pIw6@X$b zT6k!F1c&J4SUu7&p$14R{D`VVzdzZ8tSVSUSh9+>Keay`$#!BrCEu(V3MRt~>vLf5 z9vl=9liC_&b|Sg74Ser|zqYZl%+*;G%)4*0$OeeXwG6^f=-r0I4xE?`30Avkx=iM~ zXf>~*G2BFk->_E$>b3(cgS6Cn{Ja8%j$GRMiVkR=;>+^0)kU~1No&S{>Wo;Z2Kn9H z;z^zasr$Fj@vlfS4&Kk|c<%uyOitL#-a$>b^DusZCabx6l|jUSKZ3GYsTb6{Ke@eLFuqO zxo)}s#9n2*s*G>N@p@Yis0*2}{MO{vZj1OrBf==NO$HtFc@l(pvaqNz1!8fTSjkgq zN+?5`nHN|EV$-FQoiKb_wp9q#Z1G}RVuPGNG9m*_c42)a?2a9oP%@YqdURVl;%K_d zl1*;o(<0j2v-jn?TSl3lx+ATSmcL+X#_WI&FJTzRV5&*>IrF6_hIP!lXkv1+UAMM; zU+N})5NT&o;!QygEC&k5Z+Gt4vToQK(@J>x(?_ti_XzdIIWAf?_6laW z!w?0Z1G5ky#KU4l@y%(EfSUI;I6WpH>!V+gU4w#~ewQcuFWUUHu+oKCU%+^Fha8Uh z2y}TrGl1kkRQo7Fb=4pbNH zMT*X1?{z$`oG8jktq^D!j=eIu^fPIl8jbb_NKD$EHnDKhQQGhg1- zx@=EHo7|XVb*G_u-XwS>1RkyxuBRYMAQswlTTUgsoL;W)lphYeG=|t@z2xFy;D#Sr z98=t^3pilAIN5u-i807CJ8pM^0I&OF><(6P%iYFjk|22C->?w8{5$m3c#rP7TR%ye z>*df|1NK(rey2f?8EWz`U4H~vR)kMnk?%#S-JaLl_=)yU=@a|R@tPCM0EG9W{!cMC zk;l0b0pnhYNUEa3;w4vU`QBc)w;`>P zCGda1A*Kxa&lKxrTXc)Rw z=U20rS_yH$TK^XuScdgugYRY~h}Q`m!dU*93QdpV^qgXI5`Z8uv9SJ)yTqr_~D(Z?-wJL9?=O^TX|Av1V0E*P2!cPj)(!8Dx zdlXF0e*{kCkdg0E*EL^ymmNg@zz9np)A|nm*MGUV{u|8O!SfHuQ*7Fu1e`dg#y%dB zJ|>d!3bT><-mHndur2i4KIC-8JM<(AeRRix-&@4dMf8UeB}=2X!J-^t_P6!J=uBAt z8Z{B|CFH7>{jyI_@avE6wliq>@5;6)K&BOuos(lcuVAS7aMwUeMlP2?Rlp0n{!p{t zg06u&lefTVB41Wg_WX*LTx7R4IjhJ?)q`Ho8;y9WIbAB5uE>=1ncUNpKF`vo<>x+E zAL04EwfBkj{le-q?(%ayslzR}!{aO^fCjNJsDli0X=!O*2Z52%mlsA=a>J1dqWprg z9!!#U`st(55d1)HBK_G&V6c&=hk55>iTNv4a&6TP9a4J3J#s>l})z$y^W1#;vNv( z{=hoMoo!JfgYxlXV$u>jM+|3nWet~%EYA&Qm6PjoAFa>rO+36`$gKUS zv(fwobkzx`S3S??8tT3YVy7{&v;Q0%EWxKiu<7IP`8jch{K4m2MQP&_90eyH9UN9^ zhQ1;3%VzKoF4duhaEl=_@Yy_w-9xV&ytpqw+Ya~?@OYTD55fzwv9Sqvg2A72TfC8= zL>w*aE#X`ggXuNjM~a>FPvoMYl|Km7V>Ps^f&@z*8C1|B3Lcj|(e)s6yYDa}uNPa^ zzxeQnw%hG_6k>I>QH>{Py?c;EJ&^gp++9H3#Yl#dDy}UfNjpd)bIXS}zZP5lO6`*3 zddH`tmZaoj11o`1yk!Ro*XSJY6aV%Fko2{4d;BgkM}xKHcnZZvdxfxpgLC^poY#}^ zCTtCb?Uw#^m8-J2I3Dp*d%EL~@&fs~wiC5L|A3O()~RwghcTHLot4eD2*4B_4%NSd z)$7U=arSiFFU>C&(i^PJ72`wPRYI17CG;Dv;8b62N66vk^7R%%sFMUSur|ah32?-LTp_2OD zGFzWyUAKM4c=W+U#Be|GLU;NE4M2urr&a6Q-R*qLTiVcr=c^A12`MfqG3|WfFk1Wf zHtrbS!GwM95g!S}GWf;xpeOk5+aju|NeHqgE!Y2ahZCnK!5Z%G{H zj#(Jhtkv<3x7kXq{Jc|B{5MO>$EnAus}rW|%QvdCkKh|sFzAnC$spHSON$YBLKOLH zhC?2qDi4Cl;U$pezR{OZ<-*y1Yhsf-xc>=)&dAt(SV;4vEwi(wLScj$HK8Jqq%1R> zi-;hVDWr-#OYeC-z9}zYo?7>f`b#9nmD6dkXp+H!h2`D*y_~Y4=D?tY&9P;^&n~pQfJ0s(c!Ux8gLgBwiQHR0veuXyA@i%Rf0WGy%mBDO2{zbJ5r+ zaXcpG^C_~%>b+#>^Yv`|u*&biWI-o|sxtq!hmmsnTmCjbKdgqXgL_gzkAA1Pzw5Qy zc;SD4e~it^?~BsVttu{#HT@7ZQBcM(RIylhu2m)xy`3`Qb_7vm0IYY#P5 z%AJ+}Awz@~0;a~4Ar{OXU+B_A4&8OAch=Gx46j+;wq7ZqD{#iO^!6#%-_Z^@@S_$q zW!Kcw(lpbzi)m8PtgoKIr>phgGp;e;r1Us;w*)Ebi8VYrY-~vmIlTwL!%r_y8NPSv zbD8iM=K?3A(ZNTjbJ$FqZ`Xs!*DItfwJd2*Sm)&V(LlVeRz(2AJ}q^9Mw7E*rd1k| z6+)w7Nlla&PbIGrB5QtR2%3>LI9jRRrXvUrAsSF>fS4ta)2KOY`8IwnmFI%@S+AvJ&!>tK=% z_X0<@&q}ClR=N$9gJ(K!kK*{H=sotvcMrRt_T@zciRI4hTir59DCej7MBo1;0tv|bw%(GOZ~yjOnHh^d*8bxA-s z+1lmltcuu5iMD7IAWcwKI8bh+Lx|I*-XpA*3;K0+1t z={@|`PW^Qaye-3P-eKu1qqJ$*`F;OkyYppT{@zRoqqF4FsCr-KU8QB}PupO!<8Q}(BDv_h zty$Pbg#`mE4fi3-n1#*G+MR{hnyR>-b;zI&eaFHyxQu}?<%l!2FN4p8^3iEieUQ)n z%F|kOY6&OU!3?*2=>u!IM>Avkd)4!*pXr+bY?;I0;#Ye%8CccQn%*}WMZAtrRX{v! zeRRb~D4p~wp`c%$h_`2*BkifwECzpR#(K``8XWc)w{siGb=vJRX_ zGjcNOZxNd8V;m?*mQQFmmCye5g<_0lv%RV%muuRHGG%xvj^g6)drE1VLFp`fMyIq} zu|PAy-r2ynq_FdW(#Nq}4MsEi(w3o(_DyS-u652aN+4W$fTqPs?Afpw<+mjNN&h2l@6b$9TduU)W= z9Mibnu}%eYv(x9?ZRr@tpjBy7KZxVy5L)q{Z%f|2|pth_BhulMrN z(><^9q$VjR!{;qCN?N04RJl7;5@a7zHYwZ^C(=%}pMPALR5rbqCn41HD1dD~v*-#B zvsV7Owkhxyn zKWtH!ipzbAF!Kp^kMGwEzXtz6v>16yHk@s#_lyS!0*<%%h49b%080csa^_GYqUe^; zJxha##HN&{TCARHjmg6^*)NT$n0kk_N!$&5uj9q+*xsE^o%ZjB(ZtSM>gt(Cc7mvx zw7o`fQ`%29r8?EIk@3egSd|3SXeJsMP!dS|C+Dk2Pj1fAAgpWx%o-jkj?_t?_sa;9q8na;7b34TW~mcTH(v)ITTK&@u#ysP3u<|` z5xm~!EA_kidRp&v`$rrqvV)rkcvu&4`9wFVvVohsmW0ycUl+g(LiHhdQ@=e)#0w4< z*jWDS;crY<0T=j_;W!@&s=LqEUd7swC!#M(qqA4)}J^i=8kR@SYSqRaKlBl%(SERFSh2GbH?r8*r!POhm znp@oFKVJW9L3&UVCc`Z#q6p5_P+{kbEDDu%yEec-waZx2(o)qaE@NL|eZ`LPYF!#D z&uO9K=W9Bg{mYLGi$(1Xcgm9Z#Qz0ND8~#XL86O|wR;FRs=ODet^1ekBr?1|STyG{ zQ>#kc!@4T&{sFnzSKsVviQwPips#}Uj+C%Kh)IULJFw&<|5pT*H)(!?@A6`EC)M+; zOia?Wk6C<7hh>$NN=%J|L{<%Z^p+5ojE!47BI65-j8r1F4;Vx4jQ2X%!L{rcy zzq}&M>oTw-V=NAqx;-3;{QHyET7pb1+9*6YAov`xeoL!P^zXjA(%l=wh6@Fbxqmi} zZ4?=~h>LTm@tap-5%HFdt3UJ_6E+9Q^rQXgkQqnyKeHBGDCP!c!YCcSvWrh1;(mpo z3h%GsQ>=D=<-k*)A%{HRGlt-di_!W=>Ya=O%CD zO2%qJ9n59XlAhXvQKd`5doK9WBN0md?+-6I}{JEZ1vBPgz}fywM$>bnHRU zxPf6d%S;AD5XlO>-2!w7^>Y7bA_NVzP_?}S@oPB)%_C22YG{<%a9VD296Fd26O*Jl zI;09P3!)n_$q$w$7Ia-8#J)d})i;ioEn}iTkZCMjDtZ4izMIi}T&g6k zs2suj%B<^FA01@=8>p^yu)lr`Fv_zBy_1_t)wOW%lA57`x79%djmSniT_191rB>Ed z>+n1t@bK*3wW5Li6J|E4Rm<^CTU z*4^=C>qi$|X-C#fK6jb}GBLnz$o|k(=a_l4_WIgoq2Bj7z|!~u#{|R-nz5J}4E(&z z&p)51X(v;Y#pOQ9Wr&y2fBTV`p?1bDC2xD%Y5#IBLLJW+R9wb!Wh_rp8^&6Z4~o1d z=Bl_2crVe#QKPyzzOXPU(-)mx;l(UmQ&&Cnhz7!*(Jb52)allCFHXo>S&4YV_yqis zNM96bz0>8wDkco#O0_s;MJx(QKnaoM^zdPp&6wB}#b@s*iDZA=qw>$BOfpSm== zr9fby#0Jp=iulYI0izowy1X9)KU;%9PHQ=}GY&HZ-$ABq+LkE?Yh+_Mwa4B4SJ6cL zf2M%~L9Zdnk0|?7c}N4udFODR=tCK?T-6NhjE7jR%JIv*t@^>Fw1p%@`TV*QzqD4| z%92gb&3(7x@Q#SPzLnc}|$uXKk&l0^!` z#)u0o?e`tT@nez$STgHB=(Sez&cII#AVLsiV(v@KKtyI7E%E4{l;Ae`fht?6EYeHRGa#B+w#+OXlp!WlZp4c*%7H*?qntP0xgPHPvJN^C06< zU2XZMM)Z_Zm|jimWO{pL>~+-D^zyQpcUba{g{?a`;-7u9HRxxai}(|>IK>#IdA+|3 z{RLQ`fvwtt5^DoPSlYbRNaI+_M6m-n4-yc<*8aXp%~eP*-J-DQ-E*kFiXbo^!~$;0 zzs`$)zV4u?(?{~*W03+++N215BHDPrD@uF3)U+N%28X2{;K!#1Xsx*LxL&`?_&wmJTYIpR!c*SH_l9(G`j+}ClkW?7(WYR5-*p1l_ac<7`*q7U z2UkNlmc;lS#*=e!n6#4WResW=v5lTpqjSiCM-b`=@H=dcDJ@&u_IE3;SUK?I z9pAv=!hi#!v=svEkgPY1`KgMF&8pgKIQ_YsZx5N93 zV84U#gR+8sr zrLD;H`eCt&@wpo6(P1W>r=&&QFIsihoClIa(OO*jBlUNykUl}dh#g0ETdddc{)*&e z)%8g3(Kzp363I6KLfj{!)8F*EJq@lp8&yy`e&GJEr~!f{DOHGR7eX;(;>NgMY23!b zfDA_~A>>6^-T+alIk|)MuRD$R%4+RCtlr^0P9O_>UG-VBoOVB^W8`%U=-I1DXgz#; z6El3dF#HteJtin^`&i&QJ|!<8_i!U1-)^^>zPs((9@pme+&)<(aHhc1;L8YFZHSf2 zOmOZy9ryQvG_`U~dGwmxB8s*&EWEm2IZo_J4b z?UjE2v%Z80@pjX3PFVSdTZBo(D<2xF&^RU<7%e78_6BYIuk^B58O}Ly2c=?P>LMtg z^yTn8It9CQ%^M9-*8k-3rOt3HZCe*b*XtSwbTK{v{7}Klz$-Xv<{ktjp%Bt8Q!Mo> z1fxPbU%l*kPH7VrXPqV^6UX^w@$FE-TLyp_oos6Sh{X7rt8?^^f{V6uy066RcA@(A zExAo0yqwL=%{TU3khXBc`8}tzi0y>u&VeWnZpx%5%eJlCRX1No#F7L23=Ht}l=|x6 za4($)^6Y53%ao|#ZPu9(T5Z|_59`r!ZFze%()~km3!l`(wSYvl0F>P0fp^u~rmMdn z1WaWi}{#6hA*}xGHdPvRdUn(YvZgEhw-~sU2HepMJ`3h`F{*-(nt{ zlJ=JPUPJcaeJ=$SaXp_l#`aFpkw+p*eee3l7*dtbRQlU=7hRUVta_}KINi|d8TOiy zdTtrqk0G~9*m^$j0=nTDW~+BI@J@Zwdg9I)7+Y6&GPh1!RZe-sC?&R5znbomJobNP z7s?wydOrOmoh-X~`YaoDiiaa{qtN0_%P4<~vTf6DzXY)P@6;NmW#vIb%5y9m=AI2 zZl0rX>oD-R=?k{r;rq@T6*{%-wQo<%0+#1oNG>XAR6yMP z=(gDfwf_*5oBP-J`w@=tAW*m11o?3d)6#r@gNnR&zOB1r_wH&a^0deH-zCleJ*aZ# zP_LzpFY>?}Z>~J+%xQ-;t==I|Ina zk#mF7B~*`NrRPwBW2lCO&z`0EZWq8NH+&AiA0ryVX*vxJTj``o&l%86po%Vnv0fX~ zyXEs_bYF10H$kN=8j{?AHcc)XW=O^>#hVziadY-g9U19?cuzdIgGD}Up2nrBKhaH% zRtLwL2MT)Z3O5a}jOOMZDw&RD3CNN@wfjo7-ylE7kDlTL$0@|(pOaxWN2wruIXdr#yr+D7>JI4Y!i(^f-4Xex?Yg_l*cygd7sG#Zd~Km z<0)?KCmoWzFcsdzsnBPs?v@bWo+h8=fGOE)&;t|K< zecV$??i6e)JaX<^?%SO{;^6<_=1Z3`DRCN>%ErR@AC3lt_B8I z=h$H^X-`Rf9U^3*oF0_^^Pr8pWQrdBm($;_6`_j{m#x?KbYygR@^5%@<-qAxK+nm4 z=RPk#=k%j0_ZUtuE~;(Oe85Bq3-#mbHu@~0?gAHO$HtxRPNShD3S^(dd@Z}pp{8QN z^QqHQi_N>*JFuzT6dVG~k_<)hbFInmjRsD1%V%X4rFlbr9$Z)DSt1!6_m`l1-qPX? zGE`F@Ms;)PtJf~~Pp)l|uNq|z)n<)}*tnSmI18M77P{84#vD?%-($`Uxl!Pt608~X z8}AnC^WZLZt0<*d*yV=ch zWtif$f~*p5-MX|TTYPgv*58R|5gc2s-clsfx;H1*p0`!2s_N%7^-mr~O#nHIfRZ5r(r;X;KUU{o~;wT### zA|~AS(tm{e?(CfCj<>B>5`H0cooKsL1UB1-lq4|Hmh3!b)kvHdv-jVr>^H!!IC{4Q zf81s(*kv4h#t;bX(4<;(NuC(j|D*Hv6;k8aW=?14p{M2FhG+a&_j}q9im;0d;~#xh zl$4Zo*fXcQ!RN}j#T$jZNYj&e>14EK?()JciCn<+?Rw#zP^h1GK8IOV~&mdB@qWV34cS>Jsk2QL0LH z?AG|N$@eBxKvjR;jraHO?^W%?RWa0*+ASVDM`}uU?}#7O%3GXAEA5WDycn$Lnq16@veG+YCCY-(wLt zF7}sGVp1dNZ8z;z8DGiNsnp5%fcXu@4sOFNwxNUWs)jB#7K`MQvxx%bz1oU(37P<( z`W1?wP?%o=twfYP)%)n;KM_;KtPolK_ew66O1g%1`>;NHQidj_JfW&1C)h{`LS($K zuBlqQ3Ey?&oOnP~*8Pbu_?4-hadJ|2zOnXz_Sma3s5Wt>pHMMQKYyTQf#MsK+v2#J zL2mEsE-A@|+=K5(vl#2$(aEtL&$s!Qo%0xyi^YvcMPs@H~7>f3j~P2)%B5 zNv7F8lUxN)YtMIv)d_=(t9Lf6@zP0m4>ycZ+}3OS<9sRIHmV+JTc2yC?40D*4U#Y_ zny*R7Pf$}qv1Z%0L=M||ab(QH&DOGwH`~7FA(rwtlS5JNBHPpVgParjq#mRg8N3F+ zbp-l74WIUX4UuPWZXasrWzR$E)03H;k_$}E`_t#okw7gY0-e?M65_pX+@-WTwy5i& z%Kv{NK!kup=%Sc9E5G?bQZ%q0EbTM;ELl|;S6`p9X50k`HnQu{3IxKSB;dhvHAo%! z2-Bmy!SH7~$#lGTve0y&_z{4G1<3gJyuT{DX-OtXOWOsK!)y+#rQy+13y)LJ)m+cj zTfF;GPSQ2Uk(UY}WpF6p1IXM<$B?WR`MsjQuCb7(RjyEdekLHBSu;Ih>6~1PqP*XAMZ*AAFGy02sUFRyLD1V z+FAj!G4WOI`ZNias;3FvXE>_=Hit#GLf%``2qvtu1;*HX0oT4DZS;b0clt z8D%3Q$1iW+fjqmL&7biF#39*FX93v*`yU3<&@ODY3d*t&A*YBh#qhZ>fYEz>`$F`x zh4!y#RoPd%2nMi+AP*q=x8UqHPfBOsZT0Qq``)RUyP3t@WLzlSY%>6vq3H8zYP2kyGYgYiNix@mm{@^1r4&?nJA_ z)$_>}MH3fD&X7OgN^0-9$&x`a|KGw~NdGVDS3yt{rQ`@b=yFQJ_j@tq?M+JHzrgVP4G9&_iPy2D)J_VWj)yR|7c?z9DYDjZY=F}^`Yfv9h@+bacm z-P|uh(_jNPw7(W7T-m$m8`2U>jgi4EhtJw_KbwgL#R8g^8bD@GKQD?5;9?bC2yNHf z4|}cc4?g#RvJb1r8L{ixlZNYgT#&*2R-b?fK4V5vef!01ab8|PrU7ZuP%^{Wjca-V z%JbQYlJuLfNy#h~@K98xD|Err?M{eP=eViH2u{3-r`YpZ$wabC3DY~1s0G1bartI) zkJL9@{JxCtPAlVoS9CA$8i4B_vV4<5ZvXaFRk3*N6jPZUToYdcz|6GQ^W>vmj@t9m z!LFrVQ?~A1b$J1)*Nx!r3sfQ+80d66E?mtc!Eu#km+%q8`f^V1sdH(s>``7(kkN9r z>4AelpmK~(g^^Kws1&pwOPI~f;hGEQixs+dIj!tp9P-{};clzvSGn;oST5AHQd3Q5u4UZQV*leV0N zrS&hvzOfVy!U8F-e$ThL6N-OaF`I(@7LRnt*X=4V%zcR09U5;RoK)3Q4XTmSTr2L5 zAAWzIV#p%k5QSvByB*WFx(lCT|F0mC$`Ybhlv9dtp@9QBK-m6CbuJ5a-c;U?w0gfV zeQwJE>oF+jN;$Vx5(r=fd57rzf_i(LpY=rq9vpk>%0k92UX^)|K|ZZrBk%t8g__^5 zKYQ`YzS3J%IuLt4B6qrexKSEghq$+c?2pS$PNH`r+=AuZynWKv1unO?deCS)w}o?@ zP!L413DzHPR2@{Zjng~9qv_Mxw@=9sq`y(VC(@T2&rjHYj3j1_SAJjtLG_IQ!N^@C zwY5NFrIbw(A(8A`8bTq<3QhXSQrsJ$SST2scTCE@e@g!P^wZGFZC4YykZnMi{XcNZ zznadavT#+;sE%9josk+uICG zS{XuJV1O_{_Xk>-a=QES?U%y#bPCj#9GvW*_U3-FQuxwVd@&eU75Su(h@y`)izd`Z z@!y+jQY1_gwKm6e!#Em_9gk9VtpjM7e3bFX!H^+3ny;m1HBmZ~HYE?LO(6YdCzSlV zh89AY!Ot$s3wcQ8YK6~Zi*2Le{i6@S-x(&>UrEg>BF&?>y_fyde)RT@<>Ht0xuKJ2 z)$w2|(lmUFGl^p5^(D<=LX@ z;ry7@6OlboS4L5cX_{!kdX3(m$-q#`yVRmLZ9hfQXC+@sQp?IHZz!#!PR_uWi!{kf z`W;v)eQEe$x^JV?B-a_TA*HOm91dc(8g$TRoOCA{1{xnPMQ(R;?L*;S&~vQOl~6P~ ze1NQ0h`69kS>i26fY~QN5-4HVRL7x(ueI3WAWI$VIXyhLpK=0O4Xwh4mX;*QMekZ9 zrDQ*j8{o6H^$MawLF==%&DF{N*9ii&vXBQb`}I}8$#BUA7fp(Ne_+}j$7zhFPA%ou zM)_a2&4SEckUCXh#)X!aL{>&J5SNHx_5b`Z|3_~v*wffrvU&Il>ayOZ9(c+@dmiSuqD*Qf{FKPY`^psh z47Gsy&D4{%q_ZaD3|u0bd4V-_dDlotlbJZ|GF8xOK)Of66HKY zQP~0>enDTfS|aW~V_4&r;7Xza*oaq_?zNY_X83Tc$egcf)o&iG@he{GH+c@4h)DvL z8>+og{DOjgx2~Q&E-tZW$>G*i+Lg*vpD*%Sb#``2A3A^Z)xpudm%X(>#p_w1&}|Amt#i1|Z)y8-JCpKg^Rf!t$546i!SOzO)k`); zzt&&6XU^dZXLoqUQCF8P`f&ffg6n6Z*6vU4aW^p}*uv-f(( z#c%F;?UW+g-#LW0$+~#Y=nZ{G6QwO9J!-LPv0HxB$kdJCD> z?*+xV{nH``9l zV#7@TQW^aI(DdzIhlgj142l&WEavWN)xNuauvuR#34irae!KtG&1=^Do{zOpoNz)} z>RLXS`$E{2=QQSR(vxW3M4NSH^5&;F+J&*!tTLCUjY+|lhj!cNcYBE6im&q5zbdQv zTZR4Q1H`9Gmrfnti*oU~vCRv%=b{=4)sUz46~s~OFbK}YFu*ltX`zh^=Y5Zm*;)5% z!)WN+kM}j+&&yoKZazPzUWjO!%}cpdLPqvI%LjMv@iPEBmIQvJ@$wz%@WFvq5eyZ`Mv`ti0{3tklHwPe(8|n$9V(fb<}FQi+qa zae3`eS^wEQj?xQEb()gmBHim4*s?m^G%M?++f?9sb1-)7L!#27ld2Zh0$Jf))dshU zsdo~usVOO;_>Z3hH}8?%`D4w8&;G^EC{jJx9Nyi~$M%)uS@Vn!(0SuLM98CIuR}*p z=zR}2Jv05m_cYARo|Zb9A-Akkx*WGRH;iJ*fTQC_P5;TR5nYp_KIUX$pbTrNohMl6 z#@O~$yk1=NP=#ML+?>_(Trfv!?!`$1x^k3CZpz!!LwzRd*Ra7M%5DSq_`tx*whAud zSf7<|U1R(4W&a>WRe6_`vtvJJ>kd4-#cvL$gec`DD&dTVhOBdIVbYh zM5tUZAm=X;^c?e|_I;=(=;+SOGzn&&z+V5{8DBTZXFyl#tqWW@rNi|L_HYkGNpIqb z3-gn9m!RLHx7Knk?bWB6j`ci~8Ip*9j2>wODCzO?Z@c~CRO#-yPFaum6iP+E-x3(! zY(K@<1@)i%B6vpg#J;!J#6jqOw<0bQ$Mr+<1<#*MUvQDZ2Q+P$gDZJUBjnM^3!i1B zF1|$dIsC}P(H)+5I7J&?a-oSj~4#hg02Lm(OBG#l3dkSk?dAE~}aO+{NPCNeO531b2R@ zO>MAnGTzCYtvvWwT1yuc@Fot&jZBPsUI}b*%vSeaU#p$uPt62bnVr%R0o!b!C$eV==B>eo6ye;$HsAGHnEx*{#G}ZTOo+(K~$_cjPfg?d};icP@ zoXDGP4Q~S{O!ZLDEdE!FVE6GN18t~GlqVnf-wR0#VN5gFb#DD0)~pZ;nf#oTmX@XG z_M-WhuH0MzJtL{6$}Mw_^z}i7;dOhbyCGj~rYrlrRXF%R8CY?3^+88X^c(^S5nS3S zm;^X-DagyKmCyM5&;a07(ybsYg&XuZb0SY0d|UO*WAy#{`$tDgQX(cUFmy^&Vs-H{{Z(e1-}mQBx$ z93I3=Ykl%1#Dg<=n^?&rGDhRQ!>U%?6(-*L6vsSRsKf;-kKTPa)uM}9bV$*fqWAk~-%MR=I)j7j*@HCI*GOM?W z_t=%Fl-t+Md0EJXEU-tf^pMF^WXpEkW}yOmi|S|jWw}1EUy#J4SS!4#~W!PPk){bU0OOoRlIEOYhqF$+!3ry%qn-VX6&FLNDf?HbsFfXil?D_BU}anQry zDK%T^9MaWE#uiwbqm=NISud}VK9t*TDswV!oWDw?>Q!ZZ2BCTPq5Dixlbe#B`a=&T zP61vVvXV>M`_M+BEQD1`9R(p`14pquhFrleMPyd5nV$T#q~ysv=H?AYHl!QM%9c(} zAe$m0A`s8O%+Mqx8+7>S{(9NeN6ti&(P+uZZu+3U>;ebwhxI#XnRnB%K7nXXi8y&V zZxGx^27MHOwlbo_iEzIU^mbDETUji+Ofm#1B_)+#Rn^)rXF#y&)C*?3Z=;ha3#Wk* zNx)LsJ=fr+x+!?oL>JISq8dxpoo?NJC{>_2Rh2k2881tKU1>2Q6N%B1egnSw!3OH(&m}p%cJ%A=jR;=kv$~2ELqlLtIH!dtOB=J z^yMq-H(Z^7sZDoX5;DLr6SG#3d_>9sz-oDqWQ-#^Sa@}g4NfEjx!e} zc$E_ZqQZkVD*Az?l#c$F*!xMxe?0;vwc(jtuL}FU0xt64lCUX|BfrT(2L;l31k0_@ zti)*q+?mkKH0|ymS{g2rM>)nXC#0=h0bC~b(^WJ3TPIMdsdU>r421&Ci%uG{(yY&W z75M9_h@Z?*eH**#m4kMjSlxX@lG?hRZt7Hn-{zb?{p+QN#TF-^8oY0<{KD%ZeUkd& zriXl&>JSaWu0P$Lx)W*(BJ1w~be!<~864DA;KdKBB^AMBihqzAKrOwSG9qK{kdy)j zyq;vY475kcrmB!46Ss8sSAR{1WUKH)e^s@q=S~nX9)1rm8u1zOc$c^hoHAI|Jb7w5 z?iFujLj#>{C+X*5e$g`~QO^YrX}rC0-=F)#HJek5a>7EJ&PIz^r}4KGbm-mYSa#r) zeEntsfp-_3;gxW8(&gACiO2WB)}7~egZchJ(@>fUT<+lWDY9W$R@kx`z_@}DJN zynKKEK;^;TjDizUB?1SYt=|m)hzkb!KdB`$_mo_Z=!G7cHMTs`uV0bXJ$oPMGvJWC zPC9-|qa124AWqmqTtiSXI+yy{qyUJe+Z`n zzR`BVF(F=@|Bh-`{B@3k-FrS7XBb+WzSg+lr=##^upsmTm;-=LSlvuIWOTRoF{ztz zZR@u-iPF1En}3f_)D8rdXOW4}neZRI=S!qN&HA_=&nGM7D(9D55+-ZC1L)#Q^8kUAqZT_bQt?m9HkxzOfy z`?c3Kbh~Z=Fg6&K9P-%F>iPLe2R%rK{HaRYdhS1|aB;6a;mV8RUNxZdyQv*=xn6t^ zXB0T?BIv=2aE&h|nQ~zKi+A_)?1w>Zj(b$LiJv|4S}`TO1GL*thwFU%kYD;y6u9f3 zGx4a?;Qf#D_y2S~pm`$By{GqbESHeuPZ2pd{l6EXiFx7js|!bu9+^J&MB(>+F}=Iz z=J(G@iBmcs+f~-tu14EOgS6Axy*ZicnzEapPLIufxS_6J1KWUsbR$AqaE9RjGL|zu zKt$Ds`0*plUaQ#plOs@3c3Tg!PJ>V7of7K;1ln&M{KGo^j|cim_@cbJ(=ykAWB+576rJ3AQN&r~%|w!r z>65)D!_Kl+R=ymio_~8eYVZGy`6rv@zup!_fh1g*&}W;ol1-Pzk#asQ#4$9Kf#l<CKfL0%3t3}rQYKyZE#Y~3;rf&$<`GabDG>pMZ`8L6NALpz0Q8vSb191C z@~(Yh20}4V)q))6g8=|Ho zGGX0Kl(YOyj?xBjIJI|T*31zw z20~rnwmp~h0?uu5u2#fFLxWNw2MQ`1iCiNVno%TyW<)rdX%R0Id9%sxVt#Svy`DuE z_VGm(k&}y+<|P~_eueH{3X$b#=S-0n1U2&Mi6ugDV`JmZ)KlDF^T{u6`>x^l-S+YE zk^Y&+G!QzTu~Aip%;VxKB)`dcs9yHjqCgIJlnm(!iN0Eh;h(R}f_oq-bQ(<-jLwGl z@bsZvon1^d)N%9&sq_pd0OAbT6*vPpXMi68T&Lp37LaU)7XN_6fGV75 zfnI+^ncC07bjrgYxK>K0&!cyzGIjt6(a=l|@B}Sn-@HKmheN z>Ffx-g+hEw#w*pj61sEea~=i6m0+}CK_Rz=G0K&G1Es=w4b3~f8=#*l7*mAGA}dGx zEuz!i?}@-bOaNliFO%Ndb@g&*i6>^dn!-{PMG&?#E}>pI zQT5eyZF}9!yeC%^tkJwzDr+3=>mh|o`uJg4S^~wJP(vz?d_ZrV*N`$mxl#@}bT(DY zlRMdlgAWj?WhBZ=g_5w%X`Yy0F;LRVxp@@ELO*J^ks3k@Z{OxLi7jlTdyd^%t~byp zd8I^G>et!W%0~)K9OQ{vJcxsGe~N?rQ49hr_n2_jM3MFG^Tf__FV&L&p3q6Y3`a-A@mRf zQ9(8G953p!GBd4X_C**|p^@gB_W>wL#pOw8SVMR>JVK_u#T&nQg8xMhUd z|Cbd1KR8P8#a-&DcSj0n*ypb`k2ha?H{EZXIv7y@U4>Z?WHZ)}SYhAP`LJR#bE%i@+wD@Vzd^mLT%;F>M*C*dh*&lRtaG3G( zb$>1SMEai<+&>*^k+h2sX|Vhre%u1Gmnb=L2RfB|m`kpZ=yUGU->*A596S=u#9pAH z6SN`rkJJS?FlpZr4X2}g{`NORY1;2Qx|u@RMdg5@!BeUxuzErl+5J1J~_MGT1vB2aF~Mb zi)WOSl#uT!a5yt}7cvYMA4)Gz!|TH7caH&yT1DAZ9k?SmP`t+p==Q{@@PWQiYGOZm zY~Bg?=?mg^W-HsrEZTe-mZQN5pnKyambHaXe%az__79flfL>$-qFJ5;B?P66J_PDI zni@^&nzjXc45i_9hZ*nm(YRSk+)xi9zm3f}FNR1Wm6WuoJ5`*yfflJm7PPm?Y`9UN zGgKWaqRsVdXzLc5<&CAGWu~`gZ9a$&g%UxK-%$T-R~=o_Uf{XDom!|4SWrm|P0#=8SoEfKcD^Hw<8r*6r4FPxs5O_!2RuU4PMJ<5K) zjX+RrU9Y9ac@Fe?)6lq~p4M$ABP@O~^3Xy$+OSd7F5;T)DrL6u4h}k*K$HR0HM2X| z20aDU5cYxk9ZCXX+~vIq{J=)Ba}SZ16j=&|bL!b50D;aze_+Ft^@JbLv%=yjU;@i% zNiT5Mk_mV=QE)9bg%_R4v6PoKH#_jmGmAq`hN(7JIBs3(POt(lt3p$$ux!`kSNM#T zq*3os`*#$hK)!X{`R?vdH>y{M@BacpGd7aqBdgg9FtYG*@)LKV* zCr1*a3z9sPznwOekL`*hFX~r%E!G)^e>@L%Rxx<|xWOl%)RYp(9-Zqg9$KSm#b!Oe z96KYh1oAO^h^Tj}&6x{l!|3vnFx%c2zSRJGh=?ozJ;+?1-Oq1^z;Ik>fLyY$5(nfH zV7Y-FRh7H*xGlJV-tG=xET&SpZnm-t8QvD>)TWpXxs-6OuJ3_zN}vg-+Ugug?DCja z-&ZhrnTp2XRrVMgJS#-Pa&W7a?I6+r-7|XqBrFwL$v&tqvz?!D%ejBgW|R9neS7reS#{E}VwwxK;160I@B?Xg7Ehm(=MAerLp~ z`Wh~IE~tX|jPCMiHUMy>*?y4?_VAhu}_h!F;&z{hIC0!Arc;3O$eBf7k@Y?pu(hY_=j_KJHK&1ub0GGJ~o}JeU(LU69nHds~|w4xFE60 zTE)2M8BY=)f8KM=pT3F;SMba6ldq3|%sP>jl9aWupvjY-(9C^C?7yP-|MEHG^uce| z#Zn(*uP!Hv7Ohn};=B!n-p(xqya8$+$DcivWIH|-Es-j?!>r2?Hwg=FDy(^ae{pXR z%V5oX3@^1px52U-8AkN|noiFa6AX?R-A>+l+SsU*UnPp-L&~eot;P@QvCXNUlJic< z3mW|u9p7sr=$C+h$I5T6WZ8m9I3G|2k>nYb+zy19JD+R~HDd;blpMzVXn) zz}KB=S5lWXm1@3<9%4Xy%dy`dD+bXrF`MpnxU#w#$jY2nuZlNLmK<#j&;?v7%#pL@YFRq>8Ts=h5Y2@o2d zAL|9lYt|b-bu|rlCWC_S*0)NNyMi`i-WpeqspNsq>9>`ZQ$CCJe*Pmh?m3~MyA^on zHpjM=N7i!7lg8fu?5zHl9lSX0;QV9r*QQ{SM7sREnS);{$Z4zn@hUyrW(OF%gr0=m zxzj5KlB)WPv23nGwK1u7N+5y6kYoFE07wCwOBr<$w40*O=%%N7yXhswXklNL)y&ZD z*uZQZuC>PcvzyfL^YTtVZ2C4=89tYi+0^du)DgO;0&^ zj0AO&P=SFF4h{}Z&XSW`iK%)rx5b-2I5;{+Ja+c?PpXph?ZJ-atU-Wxj9Q zq!k`c^-Cn(%Y(>zSGRqe|GtIM2m23SuH6uM@RHSMiJgJ9n>`H*s#%$5uho$Y_^5Gb z?9(j_>!{CK)Z82%CovDksNo1)UYm3urziJu3oxTBBfc}$)$LV1aySJh8=st;S9qn=ZcOT6 z`jy90%ld1zi!weT@p`A5=%GOYGl_X=Li6q-1xfQvR72O;&EhzJp0}Tjp4ToO=MVT% z+}`&2AK0cpF5W-ACQJNY%lskS2ieP^9>VumN2`1m&-1JK|J*P8J)2m(-N<*VXcd^6t#x!5psO|my8KJhuBk}i#6rKM}ITZ4np#1M2riOdLf-%Zu zo5J32Yn%D`#kV=j!0K5qUmk*3fQ@jDcb|GgCTHAGFW9*1ZGLJ!P!sa$D3g(2zwhx? z=QoA0rvRCp^DvFt`U}NmOxmFFu7I_{{s&aLRAnxuQMyoWcT(~dj)%)6r4N1?wYA2W zZK7l++oe=G*tBg)l3HNN$gIMG_UMKxK$m*&MYtcTKm13f$r z1sDuy7U_q~I@5V@#Cj0u6r~GLtvDS)^R)^AlKEdw!AWxspL)`Q0VSF;rA(etB5z;~ z&O;KMN1Ua#%^pe#y+j?2^ALCg7!eC>%+0U&c%{ z3!)9w+-t(F?w0pJ*IPIs8)bbOfj5f$%jIQX?!nUR2yTI0{*$h?G_hH+k#S~JKQ zbF}a6>T$;Zido54j2q|a-#dw2IfS14RS+TOWVo@#Q=pk1Z#R71R$lpB5DM3lp!*p29LP?(}F+Nt}}6MTWNasn~v78kw4}2huY>7tiWXT3~Fiv+Y{~ zXpI$BPP9nUP*0U-L+i#aGsHGg-Si^R4z(R;J7M#pk%C~`t#yzM*RsvE^RjWyi54f* zvV#E33WU3yr3DdI);2#)g^=L{gVUP&>fEm=~G?`B-^L`q>lf*@ew3B(Y$RLyq*W{yV2#)%K|IbjlV z^)_H-j;`}<(`R5sC&xa0s-R6838Z`lVIf zb~cdujr%HVG>cuwe5C4c6KRsHkkv}US4m8q`r({y2k`cJsu&GK%M<9t_Cl{9HH3%} z50Kkw=G6h=xXU3+8h*SiWO{mU5j*Vm@ctKnA(8)}fy58(p?gn9sk=%%B}aJtje`Y=qPkp}w-x!4-!T-mwN#~m z?jK`DdPQ}k-BRjWbHH|@+rhl`<3_MTWLS>Xef!?p*AF5ab4G;!5nhqbrB@l`;fE>^ zK(BzS8G8OMaNDTFa1%b*0~MY3M8*F;x;6|%^4bE!ueuXf3=|PyrCdz7nbcZ(j(gUn znd>?$Zr`H&x=s;Og!8a_;I30bi)RJZC-h-k}vc2is+@H`5WRMbeAlo3=Vq({eb}w)X2=3Bv9ua#|Z6G(lhzhk2?+o_Do^ zrm&;Jg{bF??d^tBUv7@^f7rRgUsVJXys;q9abJ^lypmG9%_AJhc|agj$x zZh>Wz4}jKqrpJ||97o^q?4S=FIeGYR1!JVx@O4 zMz(2nSn`M@-#YMj*sR|wf_HD+$a|4N9o=UVr^7mB^6jq6J$m#m>HKG(stPj52>9|| z3GXKS@8Y*{=kL~#=FIA9JH5?gPARG?7+tk~fD_C8asCT~`vi9X9#Z12_@jwbCBgRC+I>91*xw42NM$P6rm@dK5IFIu!?5?iAA+T1wIGjzpI;?fueUQ?hpe4 zK+26W`ycyt6)IQw=U_4MFQ6vem4~xvh565#?VppH%+CV9db?+Z*!Mv#NH*{?zR2-z zNma68{m<|abc+*f^NkRqG7#Nvn=KHvndA<*<(KN;lw!=+8`w&9aw3d0V%N5uACtbK zTgG^#ZVgBt0;;eSN;1X1jmb(VGajv!+}v8F_`?WLlp3lvZiPQ5HM{tlCurb-X|F6W zg=&5afT~Ug-gY|rZE$0iI@{Q1$9Hu@o#*grFo8AKl}5i7VO~X>h?OdYXyt<74b?Wf z3LzGF6aitT?faNX-8BK$OrE`t0}z7REfG6s3OR((#}JI3f)?2DrKQ_JL8+21>H>Lt zclsuqm}M+QTruK}V$2{4%PllFolAk{ktHURv9J`8SgHl+H|{8AbbX zdMXDCL52gTF}PpM_Je77!v#{~d*SsPOW}<<R}?Xr@xldOrnawbi3+iJ$Z*>IzW zXS!I$H>ZnKY@wLj$p&uZ3fYNM>kJ;6_v9isuxzHbaKYC4sCrt?r5N^yhDNsX3k3eW z{>VITKt1=(CGNGDMJ-&*!z`Ob8*p#eLrC~0b9*GjRvub7iFi@${Bzd}7f;C4?nTI( zpk1OI-%|4YwT{0sCkE|mQ!7|Fpc_+~R3CcrKe4ifOpoj(+dP)skMI6Zq9waP6wSN$ zPs#tuSW`1FS|gc1w6FL-nTUtSIgY>f8UCF9jQyRq)SrEDRr=qU^Zz&*=xnh4C%-Oo z6BO0aRaVFUUMv3hWwUcF{drPn@a{lO!H+Jeqi@E+@RbmiKD&jMdF3H+z=;YaQdCn@*bik= z)vxUa9YlQqnx_HuyqT?yi;o}boArV>GJRC@2ahrKpfLGVC_Gnh&rgC2K%q+#pmph4 zU`yc^HjoAf2@FzVoa~XD$uA>Nk&j=l$H&;TKne=KNZ$L+ge|LrZ_w@8p#<@^anQC77M$#Mz20)0ze+ocE?YO*Xr z131w!X%x_&27PY-w)YI_ju-wx3?&^53h9EbIKQjC1i%S>-@bnLqW0@+PC&jW6}oU8 zjP;m+R&sC@_DN%o4JZt@`DVU5fsrbAF!2bA7rJnG(~0{z;9uE^6DE-Sx_B>+yFgth z^Ah)RQ8wgMUPOlzwN>S1M4l7b12G@5GfQc$h>r+HNhkK>ZgUruH4<3}>O|d!r+z2f z({6;>#O#mVF9dJcj>CGukkBIR8+aQUi67ZB1YlhYrLC%7Zvf=iFIk*mUob2WYJrQx zIpEGwi!j5@5YNHxS+gT%xu?!^<{crUz@iuveX8fo5ROXmm)G?Bgrb^P5UKt^G`j-^ zA+mk!IVMky09m^jYy3Kn^p(L4Kwo{`O@O{CxGjx>p)sX&Zcvh1N+sLyEA;tw6dv>X z)LsZD)!a2!X76`t<&9d7nw(?6WZMIGS91AW|+In zm)_@l?jaBiuEWw4c$UH97naD$N&>l5eJg^dez;x1dfmFb zGIVU^e=24Noq0p`!ctk%-6(vC61XElzMDYNYa1mwkpsS83Td-SNG0Dkoq^~rVo;-3 zMSi{newXXOKjz>y*j{KJ6XOgdsY>D5edbSOL(+5)#k`fzr?pPr1n}veJl?8S#CRuR zSxdw^cOl(5+XXcwywvU?S*br@#_ed~I(p{$8-Ac5>>z&cJnLytqP!JYIA>Z()bB2G zK-36@SN_twtzcdj>uOeQ53=-z{IYE6Sw|CliEVPSvX)@xbbAD>(c2-@tu=8t!G>@& z|B~xKG&XX@S23=&kS-^thpdMTM)8=V@rz;CoF*N~aip?&yF8bcidV66IK1Z&*hB&} zc~b5xzhZ@iHwAqiAY5u;d&<3bo6c4bxw0UPpxFjL*yvGSB9#fIj}xUWTgz&JVyzYu zvIzzLG3HeWqwHY%cH;iucoTAnrzXWJ%xVXz(BT#sAVe%{Xx28?x)B(CL%^a>ySHSZ!@EHTE>{ z|EZDxK#BdA8X2s(_gL}-wk{nkvkJKdb{e`x zn^Is?-U-G{4h-}lAbMpK|7Eh0-D5OZ$_bZ$_5jR%l=|$=KQbTAJv`>lu01HsZw;e* zhr#jG0-b7x#&CX&{f*N5wX-^ZqZ%hwUH{`_^9eSvGs5)M5*aw%4&FI53D|}SCzKxU zxKZ34v}Tlj=IX4LUg3i_+Pg+r-ol*)3Vq%|L7dsfWlgufO>bycZO7Khn$j0aN>}}7 zzBxGu?fkr0a;$?KZ%v1iI13o`wY6A`vje|iZe}8Dc1a$oHgKeMV|=h}u<#N(ukBxVBUd-BFVgz~UuhCkFY0x^bCXKnEDxr2E z8Lo6}rm_WJVx0(QAsKjxtz!X^e91wDP#ok^<=ol*a4r^^N=}kfti7Vt<^K(d=x|S( zPU(F+V?UqUmhdXIcdNi}R081LBFjb7O)GmhbU+bKaZ^<+b)J8NNi;`HUx8EIR!SFc z&|fdJXsR%#RUQRfR?;~7Wqf>iz1cankX36wsPz+WBRaq7MF@&qRWnBID3+88XnE1C z)JUsSgKMgUAj$+WsPa1xd?KP=!hS@)bT+WQttzc^Vz@yfHTx5MA~08&w7jjV+v^u? zu9~iT(F(IbSeDBh_7+U-T8FQlC;37F@-H~mcNLaOYFf`TS2dwk63tcfSf%tI$L^;4 z?h=`vU9HAPgITZg@pMvvMn+mm7tx>uIz79v`SN2Ih|;WCOAiiKSy));wF%y4t!Y{R zOm}y8?_(6&aQ&)r-|=`5obEQRYL!kJn3D}!UlQqXC>vByAJXBLWrS0Y4_g2iSUsI!g)P>m*ud zE5Sg&hUMaVrB^x-d!97FwlP|G*_u9JHOy$13`efRW9AV!_+=jU1uvU)2OfnEGL72! zlV~%)`pzXc;KvL21#&t@IsI_GG>pUhY5_aNuR>{BCWt-{G%}Kh8Dh9XoBOh+!IS#S z_$dGh4Klt>e`vkZ{?%Et)*n7?8y8OtDwBk%F#`iJ$hMNv#-AG^x}4YPf$de7kfcj( zbD`B|OKU%r&ab?)ijd+_Sb{_;HSX@PjARD#Nq*aX0j=clG=CD2L<=kUrR3*BsF+F;bYR4z;S)&y2S;C%{ zFxhEIOR!%d`LC=l(7*5QgP^&5+lgtew(~h;-+geUI@N7NG|g%n0-x|JPM1+5X&tM8 zX9K-fuJF1K8kVDJHr|0f36OD~uJFceq(($xC39tsdKt)OS3G9nD6trjQZut7NAg}! zut8hGsh1U-c9*kHZPuJ+AJ_cqTuZ-f)p4cP3uq*7`3=@Iwts_tk8rM)TSV4esg)+t zjrYMju(Sl0jShzsI4j`iFcK2*<`Frm90`+SZU+WZOX67X7=>*b=D@1yBDq-zw#*_i z*f^N#Z8UWgbIrBDEMaiXJgf{FrMpnE#{O#9@T-}hU)i8Z zF$c4=QL37nB?UpOHo5#UCY zW*CgZzEyf0W`0^r6V5og|MAMQi58rZmX?w;^P#KC-p*B#XJ%PUj#+e(`JsJdiormk zy%o?Im#{KLj3CVh7DWd%XY%tBOO^Pr331?G3U<1svo5YIA%HyLye zy5ySF1;BmvOVUzv7k_rk|D5kgrc{FUK+E9v+X*$sTyt}CIq`Bf7L2s?RKj9rI;Np{ z(3#qs_sW`XWgqm#QA4q`c6;7v(88vRN1XZH4g9pG6Pqhrp`vB-Jo`0ferOD9z|^5X zsOE=jS)^B1S0`H|H{rStbYJ&vvY^&O_?mu+bxK|q8I6X^Rbsb(Xa=Opei|AwU@%~G zYCIPg%E#lb)#k$d5XHf6-bZz2B0!E=TVlNq=V&K?ACo{|-mH#gJx<2h!2fa41+sE| z?|;=|<~M!6o0TVb5z(4&gB^pWuz}_BDg>rajrj)lG6@@R?&Ve58mzVO*u1K+s;<&3 z{f$kE+0IO&r+yId>w$h(csxd?=GAn!ga$(duH>dd@NDiNUTVnq15=T`2?_<#jkbA; zwdlEa{FHJBuQAGnF+3AHb-Baa7&Yos>a6)df4Mpt!hAMjp`}7#y`YQyAEnug=#l`M zD6-!AOm!(VnU_k(=reDtp~>FVQOs=LcflBXPi3$Fa3>FQtJLDV8lfg~^@K6X=Ds~n zBXQLMRGT?LvF5GB?L_ln^#}A%-v{Bgg21*<0Y#4SYgl4_4WsiVwo~0F?Q?9W7@6!j znyJ8(=M!lb4VhLnuAJ6X)dj`!dcR(Z`4xhKYHIM6$+Wx~=^jl|q=J6x&J_Y#73R~b zktf|j^oHd57&FsI)zfvVCiKb@bHenj8@)*rRye``ZVNf$gIkmIuN#j|+g(%c**edd zMQZrB$1O@Mm=mz@EH+){OW+L*~xG^T8~+)t5T|niAHimKl%a!-l<{iH((t;z+wV&YFxB~X?OvOh>}D#OwK_O>$nL0IUO%IN>0m+oGAP14R8f}lAnXcu zpTE%5l{|`o=LTfiqeaEEw{UP-#oiGYbOp{BA8zu+Y*EGfs)qB8^Y}N-g98B(^n1TS z@AfKzWxBa1Acby8BzBsoAZ!YosN(3J^}@@?DyCz3*!4@|QXw(4nX99_bL{HaUaSdX zSfl{s8BI%`LYNY>J|=<5MCaMW9K*bN6-h?>`ab9#T`0iJ_w*>fdwcyQmjj*k>B9j0 z!gN6*%L3lf;RC1V+l%y#jPNrN+gRTd^9~RWKBL1WI)W+$^1^l7HT1BU8gtZo@KR|S zpCFfAjTaV+Nzd&I!^~UbF-}%$U9&ZxD{GfZW<%^$Jp+W0&mHJ7w#;2-$yRD;m&iP~ zx@XMpPJgo~R&Nz-kk6!D;8URllSYV##C-7?XQAQ)zh@@YKA65ixMf86Z6`fgw*jFkn~ zxa&AFD%*i-W$bqV?!K;w&S^a;XBzW*Xk*y+s>?aqtO%>&QVOYcL1>=vxM!_8MAR z<(j2=Z*S#dyW0Fcu?{tqp77Mem(hW1Uz(XPD@JK)8ke1h_ZvwuzbhiaBkXxT zHke><0^40yxcPQ1vV**s+&^Y)g{*+9?SpSVfZ|-S^uv7+xJhcd4en}oPbkLqHvR0F zQs=b(^3$oKd5Rn;O)vfBWTwBLr`vYJm89qM-QNd{dIxloF%uRe3@|Lg9|f||U-FpS0) zts@lMN{6kTg2P0i4pJbX5GbM*Do`Rz*rE+2Krpf;N+6*?TeSmBNePMuaF8u4H6bif zL8OBcArUZt3KFbFjpPR+WTV88{_TC!`=0A>&doXVyzl$Xne$QoImQqg5W}%=NHn{5 z^^$=w39B?o`^h$ihh%Y!r5aAklG79xdkw#5g1b6BA$2iRo4XJl#oLe|L!Fu(N*)>t zIX3$w0Me2gX)d!!mY|>hT75ird8uI_cBxnb60|kZ_)9bZ!3iu2S6^CbVwc6TxJEQ- zd{8VH!yn3SwH}R|MXQ(_r9-fb!aUt+M-XQp0Q=g#U^d}nx77-f(V1rxo}a#Hhk$2jCpw>Y z`ZsI*58uy^L^;}Y#@i3WAtr{ho_W`^_Vw33*;by9}FV}O6tdrJJ6Md!{%%IgzBYFBT?qp*AMAdWHE{^rxd=(62NkT|_L z0Y?(Nb7kPk+@$5QX0|8CXx_^wC+U2m)b4zaw7kTqYLL=355#AU;TdS9?u%v_Bg;3K z0}QsI$Uq_@Imj&HpR(c$KjAHn+J_=KHiV_snwxY69sXgtgL0%pldRhN z{noy3tLF!F022!#tn!Des%-$|*-2 zOK~hzLx9vf^_5$i0qO`js=|r8&~#BZ#*p8n4kHdrg;#Z*ueKI{&Q8C4`@mG#F$m`+ zjR|y7oo+{kTl_GkcT4hzPbynDXzJV`-ogaDd)_x?dD22NC}0!^ zCPjbF&d;$?PjGvSKyt*%#Nh#1BZcinAW~P~L^c*06|Z-Bw@i%ouW4-~ZTsQ2?@Sw3 zC)k?&KMKqD-`&YS8?a8WNzqD%Gvs}C;?AiPI=q*49HFQGn z<%akC&K>7}?zpdfy<^-D$q3n5d(S=Bv*vu}GuP&uijoWgE+sAs3JQVj`*$BuP_Wrh zP%wS5F_GU4ZEIAbpx}#JNlL27N=nkJI6IhI*_xrCy#JP`P=9|Oev827d;5s~$CC#VozZNsYuz8BQq{lyWrWcgJ*`dRW61LI<(5g?mwq70 zu$$reyf19-93f_L;{u-p_#jX++~XJ?nPqLFtY9B@a!U9g?aTJLe&BCKA^097_yoKN z4^L86HAYFyJVC5pD+a!wwK@4v9B^_w^{Z`p%^6kv7roNzspK%MT84Dkv=EcUYoaBRuf>^B*e3a+498fhM=e%4gf`A^HafIK$+cAv$XCM41-Ng9 zT(1yu@vIaF#yEv?U*5ct7PLsJnblU4%+|tKGBCD&_q;QiIDll&^n^I;2fnOh;~XvT z0=(R4Fp#h_S~xo3WhW*v7H$PYJBhD#GW~Y~PQ9m=LG&>+SY>RT5$AQNWw=1_Qa&fH zp`~PUQrE}5H31WVVSZ^?T#;wa+gnA<^y1;3k9gcmkDlg;+orL<{~D-8Y7#bAG_4W} zu5HKH==>g~^@t$~M!oc;nWI;^BxW`D+k;OeCocr*BoDjzEU>2^;x>x0Gq7o;(G?{O z#C8#_1?w;30rn*YujclRC0!QxuOFpk@NxLW z-WY$1jz&lv;@XOJf@^O1?pKivc4=7#@fFTPx)s8h!}#L^3DK1n!is}Jk@xY(@BwMl zAPeHPK$Y(Vh!^Fm?Zyr`3$IMkZ}$d+67ZJ6U({!A5$8`&ggQPeBn8Lfd;KmX(0=sb z>rJPT3H=D>R8NzWvM|1ZpRrpzMeXIVaP#crw17qoX z5enipwwvaBMQfn1Y*uK~s~gFZ#*)Wy7S@u<#0)kq`BeNVW|`c}khVqqA{w(O{}+Xc zgts(pDozWwub^(P+Y>1dXIE!T@e9A$mgafsfo7_&O0ypJZFDG}sZXe>g%48k1W;Q= z`D?F<0@jKs_Qo>tThBZ6zP&LVTpYziZGJJnpfvVCx)oom-@eVmCK!>7e2CXc==Ao7`oX4$pj@M`rz1=U0|0X8$|MkvFc7lB1O*@kT<|xhkoPr9H9; z)?Xbx@_w-M&hXdulhz-cG$8bfo+nT6B0A&BcoZVRZE}COiYN;^k{4Z?zqpw+O*5r@ z9di`4C(?A}pp9|aw>qQtePs}Y=%m`yxT3tlMs&11%tL<=Ow$(9${5M?`*F_Wa2&JG zJD(*#b33xTJ)D31?H$c8(h-8)uIDCTqutGRb1!O z)!1;^E!hTHruUk%`oCl3`sKRil;ncs`sChbKg;II)|cx^D0wZSNl9NA&)Q47@}4V3 zIHWP9F=|esSz-4XkqXaC4H9-a>KE}`=^vExvr;nWavRk(H2BorHKR4iUJj|TY0ek= z8l1--Fp(;f>XIh*za#zD&y_&)nn`^(uQB^We&R<%YcAfH`bZr~5kNe^&x-!#u(65CI zqU+J)#}lhtiR+VF^TXFgGE;cN1Eae6Q+cQ2bW=4GF_Y;fEvmPX{)qR*v1tr-4D!;u zbY4>^ynlGVawb{*naBWVz=nG{dR0to=l3d&OJk#BOI345D6^KOMY?%DIeZG*r(AyA z&AvY4$|wRfP;$sV1w2VY2fkORPO1drC+PsXfnW)u#@pV*>o|MyAuURwwnKhc?4Cmm1V*h-T|rYLFi({wz-X#4k_6{;NU=?=RZ38r>iN)v8J#LrZMAJ< zA!N~fD7`kz#`DwhrxY72o1s2budBqZM8qC$|H@w7zUGNejr8LFeFpR?iS^z$;lX+3({&6y%iN&!^3aJvC~d!O?%L&q$`+D9~s9 zq3t(b{4tY-vM8UF9j--x5XoCPlm3z)>?!Y+cyq-PQgx7!HFKJBGCc70vhfu0WxsiS zbI4O#scr?`FxV&@^WpO4>gV#tV37!2a5Hy==YWW`W3`3KF)JQdY`Oe!{@_fA#~Z5M zKAA7AhL_|1b^Be{uR$x?u}P(^$6?_$YtQQ9oq-3H3o*XHPMw2@71d@Bf3usO4V*C| z5=#m#mg)yh^iI7PZ89n~MMU_$y0qUVg2J2woicVay4ngP zD-)`c6 z#W&@SDvMYFMx7ByXJb>kS-P`BpVI^a`1ZCpTtF^NgFdNZ-fhe6ixH6#Q9t$Ac`NHG zX)d6vr;4mu^=Y~Q)sead^QD3QO_?I2#n|b#&*6ikY zc7-4w1~71okfX!AU;A|&)+SLuEv0bLO$R*YLTPI7Q_K}zl}NOoF9PSZZy>i$xy6;$ zSK3eGWbVvMu}1B5B&{`#nVqq5-TRfdz_9LBZg;wRX^|n#)xc?Kb@RTTerZ=J7L3KO z@YKCWXw8H5TJ@R;w$?~@rgET)SRPc4R9+Kh^7j|zxW?O%Ki347f?;o4pmZP#Y7(bT zYDg&xCUbHkW-E{eMI|03qwSEwEcoh*iTUdl=(Xg6nDIG~HCI$bd5!#xje;6xg@TU!go=DoB3~#dXc=h#{S7u-#)JR< zjOlxK@E~aFGYX10itIaykDjR8P^>wUuIrxt%x|v0LtX|41{-N^lge+uI3a7`{Pv>j z$)^MU5zAkkla`U+SWo7ePf7wYFeDyI6wn8Mz*rH3)d8EJO;DfRy0u*^U-*mpL|b&Td^mc|{fHYB1^<#FWy!;%6_{VEhkeMvOWKAjZA*H++ZhxUwof~w&2vn18}|49 zBu2-C$t%zjI(RV3m@^#a_Ef(qXYVsxOZXYbS}_5!JN4SOH1)Q0w;Wz`Pmfg$k9=1i zD$NBbh~=%ceL$hmQLq6g57h`s=&Tk(TxR^L@cN~l_1NXmS+Z{++s?+au9D^0+WR61 z2VNTl(z53eN<06m*ReEJYNU6W3Qm_HrvCChody(%!M)?@F6SOMU>p{rs_E#;(mXmR zdRB~WXZ*)6)2g3L;dEg9z{2;ZoSt7!l9n-Kq_?q`ry*^hw4L|cWS8ymG)ZJ zM$&)MdsvqNC;+VCwwk8D!@D9nkj%=INEbMv7*Zt_7Y?Yd zonD!?gbU+_6Jnao#!u3QK!D`#wnk$sjUDBfkjdhPX3=F z#xmvHAp)7G{7E!KRA!8jTZ@~41mYENaT&E_TXVxdF1@Ct?FYO|{$mAr@yNWB(aeK~ zuj(LcWXC2=JChOa@O{Agw#M1awYe0bpC8Yn#qz{a>O%NjXhjap3g>=DeyVmT#vOq* z_9?6F=rz^>nQa^-XWG3s-^;6zMI6#-AbQ3mUVczfQH=04L-SBss%EsFDkLHC zlA#h!=m{mWi4VA;9#F-(Equ!ZxN~}gif*P zsKig5N=<{um8(FA+pC*P)~f&_fXG^{uCUS-)pr7~Q{ZJ7~Du!)y4@Xa;V|v=a1AuwEX< zQsE?4$1fcoM1a`HLD+oltXtK(hjXTe$uwml5=#7(uX_kEU0lwC-8u*GhTc;QlBJ)2 zEn(&{Cy$OkALUZ3m^GDg*8K^N<$qf7&e^JYeB0u=nt?r-sQfTh_nAa5{Ytoju(9;MY6ati~b_rPd78bK6v#! z0ldVnZN@hdWWlIuS?e9r=aX*u1-1lAS=aL4eUxJw5t&GxngsmG*Yx?g9Qz-K$)eRi zYJhz=67MpV2_`z73I(QIRSO5QuiYY%=p8Qi~DSV(N$^Ge@&dk_eqg~3?!wV6Q;|BlE zp-QQotBvoCQ2TR*rxL1t0*`YO%N0x{Fc__A+B6x2zMty77qIOHW$Qk;7*cY%HS4az z75X7tR}**rW7DrbICylfyiOLdQRh_551jJ<48M3NR^vUZ663-@q@I@JkUfy4A47wW z^+UBBuc70~#jiYJ53=WE)GY8dxZ)mn|2{y&)AdrXq_GHqBQa=1Z`M#gutpjm*W?@T z!dx;~uRm`T1PYw(>bzD+(duMFXYO4AM|bCtsYVaQX@6KVv&vt=kk{1@%67i|KAST) z1@f744ZyP%X8^o-TDt1~$}CtjdgU0?KZlNej{;0dgGVM0paxBezfu09TK5f7X#MB? z_b%l=vtzZ_2OFC4H8%y5aPp$phW%G7U5|6VFot5P$xW;*Ig`E&)J8^lWQbD`*SygS z1>CGesP95rl%R-|Yr|cl_HCY)QdzOjndv`3M(%I-9^$_X@N|wa@Fdi?oO!C8mjru9K3CM?xdh zF>QMMEV*L2YgJCW)?azD1Oo=!3j(!#scZdgYfz(gW|fsnt2Y&Q@dMseKUlf<39l>|Dw$_np{waApcJ6g=us3m<%9@YNWd zSR5s26MOvw@LGTnv*H27(A)#(RIKeAY4BpYOR><-0Zso}#b?GBZ0m>THN-BXaJB{&`w1|zLy=w&fw&1|?0kE)qAWWj zT0?gd&{l5Ws;JnXR+D%XPj9wAmt0PPTg+S>i8l7Bt4kV>MGI7s|z5+C{mv4{mx zu7NGY>!Fp>6e~>zOra{y_dyPS2bU?Xdolk zGkQzfZ-45_q1T*{qh2^^KCPjfL=Z;E>vws~3vF=Yx0|glYl$Lw{Oe%62o?3tXaD{d z^o8NiC?+uNJ1bv zfc#H3Zuu5Nvh5B@A`uh&=JQ0O#U1i{8A&{?F zCm9X~lC~H)KfBKr#Y4!nntemHYd!O|Yc0Rc#tbp~+n3aDZdzA26BFoJP8OaDl6R^n z^Yocf3VVJ(AH%q{@IG0$*O^Wv6?C)R3MNbDv!gVObo%=wA>C-%i55<(1w8>}%u^&n z=)XkM2qx{+%nte<^f8&AYzs*3da*G|;Qf}Sd+C`uB)F9XyS)(}E78{-vp$|sm{Qu& zuOXHy`DXj?KK#$oVQdVI3Ie*9U&PDM!(XY`26?-@e36aGmiMP(@Jfof@{e>_b@q=T zuKS(rJqC&VLJ0Yw@L^=!2^X*9;@NV5$)tWw`W9_)MrfR^Huk+h#Ga89OjeEY<%X|Y zybNxB+aHhj=_c9CnH}1=Z%X zEzYC+_y?O_r6@3lcYT)qv5yMKIhKrEqeRcD-eU`%Xfq#a|12E!Inlk&V~XxuBynmF zjWQt)m#u5XSgpC8skU2Aw3*?VMVI8v{*HAI@Svh=cp>j-;S*6fDh?XC?{CR?MsyaE z2QswxT6^!w_R6qC$({;mnp?X}f!=0PgCzeFR{vwv>*otPdM_E+IcqFGC!q?8wUY(Nd8l;(kCOA)$B7q$lFO7a%g?&=d$0BQW`uqtD zG;-@>;y+yX89j{au^D9A!27oS$`aDL7UB?fs_Cn&mrf2=Ojg zdv)#i2$Q^h!B_ViN9>3eE|Vw7_;hj!&HWw$3;7fARSe%kJao2?^U1t-)bg*R#KTd7 z@Lq8!NZ-e#pnjyoJebOy%~mygDgVkl?l6(DkM|NiQ#QW+vTn49r?OUM`fJ@^jk>d2 zMIs0;;rIZ|`tdv9*L@JIRfSFxGyJX$Tb-vtJOZz9(yML$K1p7s6dhYHPctkeO5z?q zFq(MOi_SKz*jeB<4$-|2%BsFk(h?Pr8KQZyHRxsqLYD=F%2EA;pA;vtXn z?DyV&7=HW7+D-y1rZp7P4Y#7~9vCFh&zN2aRex$J(KCv{R%E*_ldvOm4~S%-;(R1+ z97Zykf^gZ4u24+ZrSklHTrWz7p4Bsx6N8n+r4n23rSv!9dkn(~N5)e=O;75MI>zdbz_rh94Wy(>5;fd#YpW3^zZjU5I&;eveVe)wzX+&NeP6zT1{jD{$+y65}?C+~5$eWp%NJr(A7|E9kh#QApvthcT_X!5# z8I$O7!DN_3l$J-OWf<%v;flza&=FeIdiZz9prBC%Rc2ry#-4K*n4u(alKlRM)%h9!^+mKr->!EeOgcbTQ zAzGR43>FVX7o`?`R*Uy0Pj*tJsULXHDwB;wp0w5JDLVA`pM!}|+f!hMiCwARc7pw1ip1{wrydO)(nhb=7AuN>y z7hh(Ddw+o9-of_|YJ$DhQ>|DU>{8}Nf<+(oTxu$SN2|XW7qr16N@@|{!7Sn&0gg3zGPtHq!>f2P$ zy31EU`E>cd?wB$B8;p?D={>m${@eH?2t=T)HT3miJZg|PJBOpVn9B`fu;6r7yM%yR z(A3Xmv#$retGE(&UD}*%Cz{UFC44z2Z+?f;y1s{)H)uhhiWp5(h^YgNjuU1CdxSwbyjex5D$2SpH}0#=owHcjTq7p#9(PR~F}>bZ055qv<}n(=P$t$6#thfr|_QhLWW z+G*wP0Q2Tse{ILF4elGJ-Y46;-7SXIpysNZ^7EsLA#kG?EZN_0if@Zx+ktP!@sHJn z^|28J0gGO3ufmmYIgoE7f}P=z=U~GkULk^vHF)ECO24Pl9{TzT5m8?Ixw`H*fz<&k z^KOuKj^yP@&S|m;I0uN&`QYLd&jL)vRw?Fvd9$iH&ta&PYM;z&W9~lhq?^TmvMhVa z<=_5}dvM0ryhfLn3ZK^U3%&u&b$ysEt!d#boRk@~%g3s76oHdo0|TnF8I_j%OTAZ!W?f5BYHqfq$!a?)4?P}<)ghcJj^XlE>l4pn zsue{_m7lZ@%_98@K)w!z^z#HOSV^(A3z*h?_~HSGk%~Z8=XnxikAtlynP`>u1ede# z$K6XrfT=m?qW@@n1X|=!W41mlkt4sR0C#Wn+ahrc>uaGV}u&xI+3ONR49A5yDA{`^^QqIH|8O3I*d@2KF^D}x3y2=Hy z>m%=SfGy^~rT`Q)v%AT3ruAOQH!mozJlR05Pn(;AH5dJ^-EX-!{dp!rX_MO%9eOTZ zQs%idH8|!`-VTuh3q3tp%lkoNLudM?qmN^*hHOP_D|#!nE6jldCAIT&F0d?#F2Cm? zG!T0rE4Xw}6uez~t+B6dFKic3a(ikA9}1{zXVI_c(X!v2^NMW^#Yy+K_jfuuH($vk z0?8cWyH!N9DD$5#;Qg-W9he4YWMmcH-h6KD;=K4Wlz+t6LYY z(0Q4+jNd>|aHK4UXuM2=Sk>t9V+q;vgM@u=!E9RznlQ^7m&4RH6Td0#fk^KyfRV6p z#zI(to?D35CV(7NZZ^fZZ|J_i6o;}8M*nNVd zhuV4Nl{rWz9oeLA-7GA%zd5_C0OvE&q-y01X_gEj@srFQ;2$S&!8BrzC0ag9Mx^I? z0U-wqv^2at@WXZp3)UxTJ?J?ceisvCa^`-SEVp64-#WgZOv73$Z_rq^J7wP=Z+O7^SfZ*s3B6kOPE(WV5MU#5K zJRKXS47E$WcC)WkZIaPhM4w@@$caGv)pdA4HYV%Kir|-~wYP0OKmo%cg2d9JRvHg6 z(;CG4!}aB%986YAs__qP>_c^})IRML=54{DQg)MZFXTZFd(zULRA!*@82U5a9`Q>h zXhth+%_crtdPQB7rGfA74@ZDwdu~{GEhPpDkMS{lug<=zfso6cn4Qb1k(xH)%Ko`M z&*Q(u<~w?ct@l1d;}k!P#xEJbe>?lRZbX*cz&G^V+@Pc|aD8s6hva415Nb~{MRj3_ zXSj!K<~c6U*_hNVhqY8@!EfA6HKp6ALRX~$pHRE}1)^6$1gtvG`9YjZp_<^XfCjWKMSS{R^DEhoq9)vRmP_q~V;|8&aE*vembSx$YE9Cv-# zd2@d0$Jh`j0h})e%1%Lff|4NdjXE)m&1K~1}J`SSZP@{v?;1Aw!>t8>*vl7wC5TJ0l23c zkNSadhk)B$RU1rEeI(B`uhFmJznCy#B4DP9B)FP?iPFUKo7~WQp60~Q2eA+G2iD0yf;1r`fyE)RO^{aD;k#D1~EO` zoE|ieakCENux*EvX+Ng1njsxHH&xz#Db=mTZouBYkpM=dp5x*w98Oir5pX+82ljxm zIvye;4;?5s-H&!$ zTf%!ov+;H%dF#f;9r~hW0NYSQQRMYCbZ=JMP}D8DD}-#F@mDi7P4$C+mG&||APd3Y zy|1+v%CH=G7bginN;Dt|PErVwm_Yfs51r|Ji6+KHqOR={{6*E|pSFc#J$i9dW1(NI z!5;H|>|E#D+)7Su#Qwitw-X7OicxiPbZ$4FK9nw|e3?&i!(4h3Q+HBu)$iF-Bw9sR zbA7tmDQE8Xli2^#Kmz-8Zl67C=h!MLng(>oJ7#KZY>wQUm2ugg2wX^3ET8Ds$vzfK zw;lf_@y2a^cqzqVUF2AqQuRa zcrLHtjLTZ$dyc-z4nA(I-I`pAYUq4yqOjgi*z3W zF69%CIqzaCijpBV6N;O<_$UCj$bGP2FZU07xLP$7b7yfcfhnQDKh zcwm3ZAb?4$Nk@m?^67%nzq8qlhj<^Wt1E-r^B%T*%krt?4AFq$SpW_8175_tagqU?rFhD z!Lf@hW>f~%wsl@S8bPIU7xHYv{7y82ge}*{L(dM$ShOscNUvk@-B;-Nu%G2);8*E6 z9(!W!#URKLy^VP$*%m1rF{ z)#R4WF`zipSxvSFpUnz}SU(k4ocVb$c{Q3X53XP^!08_itSA49h4q=+wn?4G@vXjS zy5*1aq7c%fCzHoKZey7N`$wNe5aap^I-8Iz;Q1;bHwSDk z_!qW!tbvp)KTF1ctfL;R&avYYOVKFOGH!VMlGV}pBC_ z#Xa!Gxc^7KS9Y=3pS_cOAfDS8r_JQH5d@hMF*^29G3Z@4=3a>kJV8uU$Z%|9H5*izjAkn>aGR<$Hl5_Ef_JEhne!QMhU_+iyiQP_I9L3NdI zJPW@?^t8R#E2+}Tn!tRkc=UlqT%s}MUp(N(D!%Zx{o#A>LgAERuZV-PQ0C5S!SQ6t zS}82Crr|Y^wqf?*t}*j`ge>m++UpW5aIY#|l4@4ZbVew9IKQUX zXb+wNn1#8xNqiSHdH;OfQFD|$dlMSwCvf8u#e1OpeDClG@+)#psdmmJ3=64o*|)4F zcTSS!K-lPZn{HLPFPb>be_Zpsm|qB}Z(mq1#jfb>BBaYMRp}1$<$wO3m z{neu)*8h*d^e>!{Ksv*hcaOmQ=hoDhL7-R*3)SykH0wCV*-7kZp?!tJ#U!T}t*4sr9>bhbLwE+YXAI;v@T& z1C4h65O)d3QL7d{!=Wh5v=y_WE}Y}l2GxiLJxBF`%K=2xP3&J(b4%MhF>?Rm&YV?L zBkLQZ77=jZjo)ET7!!+5V`rs(l{beK@KHmE3aYj7;xL0U@1Y6l0j{8mCXs%FJKrW( z=3NZn2zB99lG8xgM-S=txXL%)Q0E$fwZ@1@9nhYv1kKjb zhTX;S)+g8K&FL-bGutI{_@Yeu3FP&KHeE9nDOBPwY95k-F(F|_la392T<@e3zlUp( zSA5hXW=MvkqY}CwHDze-KH~)JRIFVYwNZTY=4nbkkihxOdGp9<6shEeEY{P$FP}V7 zC#~gpT1_MpZke6QcX}KbG02^p=ISb2m?Cy70mD?{q7!?H0@5SV%iPTe7eI!<*^L@i7tTSTlhS-~& z&0^R(YdH)6Aj^l0&q%$Ml*>rGvfQUVH(lm+7Xx#DbmK|45InXg&53l0NaWzh2v_I_ zv`?AaZH+-Vr2FZSw>(MdJRCNYwuj(GOAp!ym?ZWD4EZS+f;&4NGC&MGGHE^pY)U^7 zSq>;X7G?IeeTFgN_`9Tqig(VJ?B7*We`=z~=d%a4j}N)YW`MA!pEBM1_asXiWPzw8vdsaI-HOBpr&~n z$YB0{G5~re#_e-56>GH^i|oj732%Nmh1HzsboAJ%*M5g$P6FY87;105BOTuz+XJQkUzR?K`ZAU_XstlDFUW|+A2q2zgw0=mLU zV>kR)!V7Qh2nDyFyG*O*)&&$CX})lHg$yKvUJ)WfO9_ou$sEq(Sn$$n;MccSNQoFY zp;P(Qv~HVj3dj$mB?aWf-W7o<*TCC|?X?Ao2T}E}v2$xzK>$O*so2$ISdR zSrHu0!mdD{bziHPowbFf+Pcpe+tj2NuxPHHeO)u;RclTmgN$eGG(Jc%{D8ELE!Fu#0KO-A!jI%mZAV+PJ;-OZ zBz+nUxKHO!Ex+ehV{RTasOnz!{;hkdHE|~s4pR&x6|D-e25?Q?KY-6EuI?b23aZ0j z#fo=Uf>&~NnGW`$qqZGS4phb^8*X`Pg%nN!w?el+L(4x3Abwh;nfPBsxGNu8pzQ28_jP+-JxwSlb)q~ zOq;)%YN4?;k|_(q+nKH5zHPjCau{SZJE7ha#SdM)!FXKpAdIHmuo#PDeAR=Y`S!0{e#Fl))?fd+ z%8~dsrFTxAh4RJZ!&FHs7*81noKk$7Y34C+rRy?vTf$vf+U%Wat3Ie^cEqcxw=&4Bm;<-w&9$=mG66sK!56IYqFatxk@k*Lm@RGXrF0erqJ_r>#fo$*iPx|A-n`X zh~cf#Zo?r=x{Y#^@|m8&s~{>}`?7Cd$Dv^$uNIMxqNd5@Zw({mX7c2|`$wNVl3=Na z5xs(s$t^P;yRmJiG^_`^%z2TE5lV&?IqWtaVp^zcHr&MyXT%{TjS!|3vfJa!p|=sV zSKmIXvT^)D^e?ne9ft?v8nL4Z=PKrj5jpuvwKLJAX3r&Q_W0~h9WP%UPz*cSDYRWQ zx`@;^-yGjCpE&}sB^g1R{XjD|r)*knhS3Dqi(zyire!g1m*$)9BSR0Gu`$e#c@sg& zzw2Ni?)Y2<-m%;vu1$C*GUS@4iZ&_IHHc;ZULDX(a)5*Ri*<|B$SqZ&2bC?zpH>WV z>uJ*9Vs1=SgsCpb3V+S2H{(EP z4)mP@nvi-YvO@1ycQp~f)p>(#dO;hHF-vUbeOJpmeHH%F>&>7>8?ykrb!|5wZcey0 zr&2T!3JY%q#$Vkj2zg&xA1g<5^rSdS^CrGDoVlN0WPu!ja8LU$remzEe|~Y_q`GyWiq_nxZ=tG*^wfQhHEg~64Rsf z2bu zUphknDHq%rkd`fK;{1j@PF{~|2+T) z!QHCif_nS?3EjTeVBfK7Mdk|cfr(8=c@40-*wqTN`AFOg^DF|)B!bB;-BMyvAkT#G z$@W$bLPrFQ>a(L#S{)VjN@?NPLzKrM`l@&P&qTNRfFc%ojmpEiey91wtjK44Rg)Es zwj23r`^dpipj|xMAQb* zuD%%YD0Kg`MJ$)o4hB7nS^K)ojj;xqsD5Vm#d=``RmZhM+2G3m+8nIqhOPl<4MpmD zROP6vtCia3`*GPh$h|c=K2u7&ZQUHYZ34Av>c99W$M(Rgbbxah8;6anr6vN6 zoYwP7ircCmpZlhw&wPEs4P3uf1koar%$j5OD@Ay(3sm@?<8r%QXqt}^OmTyO{LBN* ziOY?wG8ASI02euzRlnKdW%UA$oQzG!q~z*UWOrtV-!HA{%UNqExgnjIwBMU~ z@Ft`w;(Vk;_uQ5Me%QqMc&(*?CjxC*^t!$Aa{djsr8pfLdAO@) z=&@f+^MW&7J**_h;&f1oO}4t5p2NMJ9Dc4TgW2E=?+e51=pqCq9alAwTh9Dw4K)Gx zYKjJt@;OSJ{*rreQKD{x47y(P{9i6%2dSt({#XBTSPNYPxg(6-4g-E%BWwxxKeSt^ z%@4MOYZ^8LAR150AU0=rNU3&1C5VkQd*XEwS`!(}baAp_##fP$AH~aibiF;1Rahwe z(afWU&4#DGqtdkR6u!S^;BlEfi9Kmh;gdDfGof3}lPXxvZwNl`cHNmPvz5S$!p%qB zjeNaE>Nr`XtwtVMzA=2P&~suJBC;`&C2#3DQDAGcJyo>OT7vdKZCl`GaJ|f4*^RyY zVspabVL_SU@>Yk{@G!z<6rUV|Qsz{Bpkp<%^kTOn<(9eUTz_yUf1rGGSztU%mualh z>hWO*5wjvY70MH3>XzE~J25VPrGAGO&E4wfH#N<4RMkZPXR66?z1x1nv3ST1uDY#* z`L@^s3Oncga#?qDkDBZb+fqRucw~SL?zN7Kg;l3s)sQ7f zHJ4k1F%{otYv`BebQzk)28ijp_*jEQ4JKsHw||3N!Jz!e$D`RMIGBu5cOlsBT~~?+ z+zI}8)}%WlXbb%kEZ#w;5|5CRoHU$D@my*465_TUBT%Rrv`I4OTgWR*9rF^R0uE1? zYL`Ln#(~EM#wgRCsXBF7v;hIm+0_<+*4L4NLRv!(gqnYN|h9 zwUSBV^>HVN&Y>O6C(`5{@Ed?CC&kkFn#@-_2+>v!Ddp$`zf8$^|M`UfgCzrQ7ghu- zU0K!svx{+*c+f40Iez`+4~E%8t!9%@8&a82(hK_nUZ6Us6Ih2dM)2}3Fa9tT4&;sZg{$gY(x0x=>~?JLLt18 zHz7N8WBe1;gB=`qEEN&5 zSmo_T^d%m164}bSx;V-LeV7F~U!K^-mDgHXmtTcy$^c|fT;>}Q3bWP4pk$HyWSZ*v zX?&V-SYEz&I^0)e=n8RTF^3GQu(~16Wl?_3ImZ~P-9~92m+efk0|=hK|K5HsJakGL zso(JMiwP|*j5nT&oCE^|{i-2GP0i9!le6DD{_B03bL;s%yAC?V^P`P7gHI0Oy_~yt z@VgMYTYVY1Q!~?RTeeR>J7l-d$;t~I@_ipaH?^$j=Di$>0CvTiSAW`@UR5t5L!#2Gt+imK1C{QtP1S^K zuGwlUGbK^)79-TAW51{!=XX}6i@Ly|>q)NC#^Yv+TL{S^Ne%xQ*5&qo%w=0#4vyxHs_8Q zvtQ{Aap#6Mxc3ia;oPORM&8X&W10F?F72_GwZe#iqkOOZ;}N8mvf9SA`AHj0%4}CD z5l}JU4#YSd#iaE);caLci>yYh(;;FL!60Bu>zu7Fr|QKBn=arO>j>wdU^ej~drak} z2vh+mFw3G{KJErC(?IO*&Z#lK+$T9jj5UN^(nhDh=~74*hT8J{4j2w?4N-11WmHZz zn?%5Rt}LgDm!#^PDEzMa)=DChO4t0hSf&grfI9}i97go(6jE;zyf)AI!KSn9*EKLU zp49DAuk{T7l5eLU21QyjC+fP-%&yi}^0}e==_X>(9q;qJ1q+ zdvd890y@)T0McbA5IZXF)*Cp9T(-e-)lS#^*x7MU3=r)dtQ zF21z4q@bzMg!#iTLI?l!6c^i#$T@s1sA7f|cB(b{^2U_F3S)YdxeOu86Em0`#ZBf! zKE=>Rxu2ep#r@4I!XMu0S+Emw1FDVc>n(?7-a^QynJRf1ZrciiIbN?SGS+q=2}Q~H zv2c0ZGnu8e+UO1D6P>G#-|S%Wld~F|*_ri*i!A*bz6(FX+z*3@4<$7db;^6Q{8O~? z4@;YEav+!H&=?+@#0~rR`h*+J%>^*$x<*q(@e$2%*`#0KNef~|Warp4tJgs;f9*R= z<5u9{+Uex-DAUTO1&fKUq9vXB{0fm81KC=BHgz#RIBQP{$bG1Py6d|qz%OzI^g50@ zo$=X7*lpk)pXYy>;CwX~d=hZrx06aVhbZ0!xJDmUoSx}I4#ilL=Gb-D)dJYpFAFbI z04L2lJyxtfpo^Kyp49Cd#%sc}1J|h0x8mFH&wU3CYjr#S+_^$}?QSg6J_nvW0rCa;(h@uE0 zjtHnovCyT7fb=FJ%}AGyg-!_4TY`WTML>}v9h43UN=ax*R8*vQLJz%@07(cW1l~C3 zf1a7+%sDe(-!J?&A)9@dYpr|jRj$RnM7Jz6Kd=kd$GnU>St;UqL;-m+R7eVix&X zNZw8%^pq;4rFAU-n0^=~iChQ)v zPxU(qGR8L6GfwzUz}@$&Q|7TS^Ix{PF&%60Q9TgFJHBjBx7p5`BIS%Wt+QWrY17q_A^sb*iR?S~|bV{C67co@$ErFF;lzxaUO z9A_6AdtM5>#PMZ%UMKM!eyDiJUv?-0>~hLGho^ZJpfDaYc0la*Mb}OaCW{gJU_H2WNv7`uQ+PjTNze4 z()OfPiItw)QTy-;lStA?LX(G>ikV17Oo{69#k~E}8B&u>Vy99}C`vPT5c%zCd!O6{ z`8x}4x-J)oa7_mHh)J5A6jFIg-hHh~n%Yh(_mpAL3U^S1P~_WGchnYMmPJ1z z8%>5~1yX`OU2xCAYj0`;H~Xgc_9yKEnnm`Iubaa>qP&*gr+2R_l!jeaJL}xFyW1;K zBG%Nzhnfv{9^ajAA?>Ef_Neh7aYxup!|?UeGge&buc@L0HT#HjG5CW{RzcGVbiw ze23VRkVZXk8IH_is9w9Hm1tX^5HD=OHQ(<1S=j93ylJHZDVk61lnX;x(IL#UtndX&j{Er`C+k*WOktc>WmsHodJ+dTiOu7M+Py{17y-&$jasqf~dlxw^E z2@{Dru+@Ee3#>RJmPQmhc9hIen58wE6S(r|0KSRIN7yy%YQQL-BI55Ct&FEW z3vE+NulZJTpCnSh9GxwjukQqEzXudvKzB57Ws0o@sD+}7S2OlSb_~!VgRFLU=MS_1 zO=}V1pV71WRpf5wm9vD_n?9o-j-B`8<^(7nJ=noa+#)|yT^=_(l?Ag@@~nQwDuLtM ziH-z=_l4e)|dt^^-&9z z#N)L%PP}!uHJ%DA>?&O0<=*=DjgpfwUQf9~&D> z<%q7J=kt(YdKZzFr7?HQZsLXtO$z3jfQgd>yWKpA^^PP5?+~ha=45i(qR{rIzH$(F zN>l-cT!t*7gWLCF(!Q=)Smi9*!9j~7v#3VslpXqDbUXiX2zeX-u)8U>v<}WzEssc% zC+F7~>6s zRl=<(*5%XJ&RluN+(l0-9wvcYu|wk&;}vtz<~Ub&=JjSJK<(NV+%ZroDVi?HJKm;7ffn2At)1%%wZ+J9CD-nOUMBDy zL>cLyE4v%){e^qsCGBkr4E3S_pfZQ4FCkPH%1(OscgSjqE4-)$siEDwAKC(vc>O6` zdNh=$JN60RbqAhz>QBqptn>7kPneWn(Hms__-5y;sr9e2-%#oD-;q&ev+|gnI7yUT zo0)NGl99OL7qP-xiEMU7wPa!u@h&xc-3jd1F$qsG3FcnE6*9RJ%vTv}^cBW1Y1-P? zYA4n-eT}<@_zLRKtMD%GsDhd3;3I6@NKwXq5xv~zmCTZhST7N2*J8(&G0L~$^~>bD z?xyoc#DxjiMp-q=bBI;=w5Pq#3`6dVVfYTnp+fd|LyffJpGCnr=~Dt7yz~?eAcB8RTD{h@c3h*zf|LTT_MYRQ-?Q6qRNBU z!i}ZF9qES$W-fSEu5BNHiCXo9^wb8wj|T#8lhw*PAakV_HuFspjlTFo0tmr_@N$B# z;Xf^IQ+8i=zQevc7~d?Z-;0nrEq2ZnvRIv;uO<)w(TN+nXazO?nA~^( zC*vt9BC^Y%GmOcrId7wY=UTAkr5q`VYUz){+6C)^8ZhRQ1?DSyD)@F1*=Q6c_GTvI zV0>}kZq$juW8;3Ca&m=ii4|g91vO%`AHQfkO7Rx;li1zb{W&_vZc}MX|U~H-2E3;RAV@N=K z73q`}8~w~H9Qw89WZ}XHKO>S6S6m3K?CU2z(cyUFcJZ^2N}UOzELg@n0{jM23HE8s zg(_Pq4b4?{^X*^tQzLoZWme2i7Uus->3<7K?Z#mNmwK+xa`LE!uodl%_%2fR;PWgzKcL zA422epbD2?g?w#FblI>zi%pM~x0$I3kYgoBog*&T#Dt@(m@n*ZL6vojEf&fmL9Jxj zF!EBjnu^FcZ^0#2=2CK}PgdPFsf5AqkiqoF3ubktnl_y^D;hbxd&P{7OX27UFa#)8 zYL=P=H%lp1JQz6tRP-v*X?XhB2}w70edM>D&)~dR(Yv1)8+manxqUKnQ(7$!2Yf(0 z%n&l7nH!)+%%bv&bbo+*i-&fVzrBlj5eIZXQFg>ozmRSSahC2!VWZ8YZuxavqHW!v z8lW6rPDMdQJP~O|Rte6$BM#XM%+0>c=II9wT53(Rm8K3a;KAfG8F{lX!bVk?6HNY~ zY59=Pbbav=(B0KeGqWZ)KGW&o?b4WfJp;6%;$qCmFIDaPLB*DwE8o6$OJbZ$sdj4= zcS`2ln1zW3;&nB(%@$Zn!A>w~`#r<4WK+vLd0ucI2pYlIs65!qs8;&moijq>l_y`Q z9auC_U)+7i=~c*x6WvAjN!wz4#>%9p78qxEwBFn&)Iz&WrpLU;&TAxW{KG)zE7x$A z!h1XN4IIDBo8(TaOyHmLRjyPkVsHD z@0Pf+STGg5Mi2m}Qk3pyQ!g-z*ai>|<4`7O5?XOR_WK9ZU&>*F6ll+G5zXkAVn9km z4t2|&BBC{c-XWOJFTYuV+~c4z2lhkOT^pYnZ|y!;K)ZV*{lwb$E6b=)>HhY4$T6jW zl_}hEbGTOnAMRn8{K13D<8)AvOzX7e7>6evB0GI?EA*7~?t~K%lleSmzx5ahn{RjF z)O9~@qii4HCdtkFV9c2-`J9OZ^F~cyfAuSUTi`S`$Pw{vmaOlVZYWY(&MAMHh+es% zhJGXJ#ZlvvfCOw|tUCK?w-@iMcNzw$;!usR*J-{xjq7OuifMW<)tYRpwH~naG@bR{EmLSJU_51NZ}`5Q$|F(?R1R#&RXd9)?cb^Z%m8@u&pX+EpcP zyo0t*)(NYwse-17Y}i4&L^kfCbyUq(Y_{hA#FV3+q26C}F5a<$Hz6kT^59`Jvxueq z5xgYo(;n{a>bkWBpixk>f7_C#v62WeQ_l8YJM`+v3e&tnu)_t|N0Q^}-d!pn#L3Z}N!+nX9aXMU7re^Zi!1 zfnIP(<*;eL`wP%^T{*PmwjKrceZO)sm)G?DmH9XTftt7Qy1#3;e@(X6V&hv{B^%a) zt_kd7hSlK(HLoYs1b~&Ie$C5_RJn{UXGZwbNX}5++NHM(xD;YE%*u3A7bIMkq`&Mk zMoWMNZ5G6As7(ee?#xvsq&48bdfrrkn3&c>VcAJZ=!J4)sZPC5fvP267XhOB;@nTg z`jT}pytSdT{W(gYlz=%`8ndMQ@X@#($P#+T+bPieQ6P2#pq!{tQYMW@--jv{4EiM_?#P0nD&8oC!2jVSUewWhv{6npO;uk zyaN7rfl@DvRs(Q1xUWO0Cv5xCSvh-13Hoat2CFmLRpVQ-J|nt}Pu;+3ZLa#$-{)$8 zkN)J8vdil|CgGyP(Uccsi>7^*#zEB%J{k~+AFXXKmn1rov?~zhGs}@{+=^v2JI$3>uDoO-1TKBcdT~PjL zXy=)kWbxG*tnYT-3M;aX4dJ``$*H$1@qO5 zdXU`DV{0*HMunVWNygwE6lJ~7I%t#GTurix7R=ovWOgSWF|j1f(J)zZx;s}XSP3KK z7xk`yIgJ&lZEiI>Z1-9$U2lZE;sG!WGkLTa$uP4zC_9drdfSGpaew{-EXG7xH*S~I z)lDhaZAG98j!`KILITJSB?X+9`iu?5``W}8iN76;OTpQu;n3Yl6EeFl#|t{4UN!nM zkBw23vi!M>{fT>6_`Mmi_}P?X2)F(&5j(GmJ{;9XLXEcg0prfN>O#$gmklvqWnW0j zHW0%YmdV48k&8sC#e`}9DliZ{UkA9`6K`BsC>mcb%P2tGE@Vt|+1Cic&shZ+MS<#H z;}`Tf;-}rSBba+S_>(l-sxF0==kpQt0bK@>MMY^2|Gd0M3cipcXuUt zG(#li8l;gZWe##Fjf>Y4B=O{=?rELr#Be`S-F=w9X#otIyNvBNO``7Zn@j}n6co9< zp7h-&lv6D`{GEAEuWCHr7rVb7|D}esT?HyHd#l4{Wp>WQY`?}^RMvJ3PIA)fV29^E zkOeigZ)Y-=xB0S5cgBkWtojaH$|4je{HgDUx1T|ui;;}>KDDId?~ZzBOy+|#HLK$? zikX9uvQXwbjAD*M=z$VTLRnwNkECsp(59kM`KqK0^+ZX0_o{KFv=RtW8q~dwE=LFt zMszd-P!FO{tSnM;EavTs6V_+TE4-C2)Sa0uE?^w=yR~O1K2M+)PB&0cZWDU092FVG zMc!cMW8jYJL)RgDwE?PLC{_EtehXAt%GrlOXxQz!T?n*C>=#(b>0yR;#RvF5Ar5 zJ9$QQjJl#aH>r~Y=oAeTFxy%lUB@elJyros#GZCK(~z?hg5VIS;WYap1{TkefF5MV zKJT0BjtxKZQ;=NuRvK>ffS*-fWlbx;KYw`OY^yi&k>w%p#tETilaDLrjcE@oJeBZa80GR~}(FIWQJE&FI9 zLvRI=DWQHO%cbyic&T-ofqFP^9~kXnxpC`ZJpyB4Wm-Ir=e){XRgRr{kVH|Ga29oJ zY+l7r%BnbM?GAX+e|7OMLM9=$fmomOb=anRC8FxIO63>GkFl?Z1uG+ zH0L73Akj`u?)dPpOmUe&GwpC7)J$3kKf{-IAuJ$L&9k zOLyfzf>u73LEC;*;qihe9O#zM;ZH>yh>w zwy$@qNVHy1zLnEX!&978sKWe?Y1+|l6ft2loT=>IK_7f;U<@ui70Eid)rX{~;i=|G zwXRiD;ZEBa!Z^MbhX|F~m>*6Z71n}YwSi37O5D{ApLXjDTbB)~qh94<$2^ZzQFl|2 z%puZ@G2(8F+P9(_+~Wc!X4;u^b4fIOqMnVK9<3`7oe>J_&A0W!af%9!1NHJlH-k`x zXD9HYQmp|&zjj-cZZ_;wOL`z?Gd7|%stZ5!xAKSInwW_YjWC^tTM-tD^x@c!nr7HB zs}-^-TkULT^U9&A(__yyi)BZ-)~MH@YgGo_s4w|3p3^ZCn^jz+PWW=YV6F1ICU5$k zoveg~lZ(szOx++c{`Ey@l2l=t;F?%1kE}?*=!?&`UL6@S7!{jA#Y^C%XuG*yYiC#2 z>CeP{On<6~BgGsp#>7?U5Xo_-F7H@$*;UNpd2#u3Sr&7I$^>5x7Utlce$X9*6N& z0mzxjj!{z&%yt?f*aQaD6Kw%Y zdQ|U4H8iB>s4Tb_6R|v!2pja_P4DJeR3?LM91AIp*G>>vXM-WsY_0bHutVb}xEL>? zw}z+^jS!(kC6CH4+DfA#2L%!@i8P}rO*1mXv#8X^4-QaBTZdXJZX+@Mhd{3gtEXpA zuP|s%$S&pR+iDA!^aij?fA_y=W^Wy(f0;4>znVW}mYkq4r-S1a%8`f8ScT1&a!84* zwOXy!7>2fv2U@l3ux>(%Z0K)45NGd(Le^!7sfPT1aISe<&2oLnlNx2+ex+fUMQ9(b zf+5{aW{`x{`MTy_-&OcvNc&H`upS&akK-kFy1(6gTcmujN6zfXl|+xIyf1gdIz19w z8yk^--|YHi{j$01R+`L&)~Ai8m6Kd$UJ|C}X?J)gJV??z2N0yKOkIXlkeicIWIF33bz83jI-n#%bAS?dpluS| zR$^yh1ch9;-V!$bgv%@@w-HQFS-8&>5Ok@8Nu6}hO9OlFL0h9~l_(R^ zl#Qze_uR{&J@OH%LxZs{=z=J)=F^ied5oO|kc8U}agmKH`u5V;O?l!;u{1QDmfkQ~QG(XJVOk=|4AGX+J&-MMAPfDmJU)Fg_GPG{sQ`PkuY zIY6XT*y@YDGsa{xd(nwyo~IoQW`QDLP0x|`A{hJ=g5hy~BC1R{$K;EOWhlDuo4dCP zK&%>8B$S;gi=5PoYukw22F-2=~6eoo>O*A8C*c zvbWn!UWYi6EY;}Qwv>@YlgOd60hOCKSZ&d{ED!d+z&{qGrX|b0?{`Z|O0YL<6LYdW zm>2|U8hcf=3H!3uca5q{xDgTbl4f>xi`{RH4~-WG5!Cb*-pC9a`l*?%`vvyxW|$;t zo>=*V*~cVpui^_1esmN~0P`m@JnBno0EF(RyjrMF!x|!03&bYRVqYO|}aKCL5WQnbD)+ z`#s30>|}hnkX=nDwkx2TLb8+*(f{O1Pt1#m8cPp08Rz3eYU2>HsH}v-gsA;acnUX3 zWI4W$p06~33a4pJI(4QiVU>4oE?iip=h+@7*OuS6e@4-0Q^;!@)J(ze@3?$@U33O^ zq+_gZ_=s$KIU=`K?Olt3)H}8BzU=vUTjkRBUl|pIN7kO{iXSd8J99G3FSJUWtcj2udV-Y(CA4DFjQ@y0(wjC2FO+8(nQx zzYC)#=^m$9$HI67Tq8<#c~V70*%xU1oF z@K7>C!H018IZ}I6A-Q2|_ys*Pf3@fZ;?vpLZ(-974NHywmA7FRNBE=YDPmRRm~=f$ zKN+KmIfP|b)iQf;zp-&ECPhQQCoss&1)TxZy{tUJh9?}*TQh~8(dPa*EgvIL|R+K zL`{Jda-xZcDHCRr1tAWWt zWn7=Vi$ zMyC~33U$BdXr~OsOyUQ)9Y$@|2$c|itNVq3hmAnRM?B`b_%cn9liTZ;l$a*;b9by? zXbb7+v(@I^{z^y{z`ULc4JMd^YCIK5?KfwegWLhAE{ci}4a3S3~qfK#e0805(*Ax(Yz>BQ(;jiKc2M-Eo% zFDEzps~XH%YU~$8iYi?v$ZKsmvfbmT0QsE*DRHf(eq-D?rtJ}HMvuF?w;aH`e%-9> z?j5Iey}kg|y&*ZJid-#l)i!2?<wFz9 z4ljGBQUQd{HJ66vb}QDFE#BirsG|wpRU8-Hh%?-LBLwZk^2CN>4z7nn1weoyL!rw- zlfP zo1nr&ct({}dK4Y2a(;@^%cVAq6=CImq`c0(LfWeaK~jb6LR)ICZ@b+M51hVn=hMQk z9lJbjB)MVl3wDU;CFwrm5Y>K!&`LYnr;b5%%H9%Fw|(z86uO%J1Vw1@t9rfIVf`TW zpp7b?CoZ*AuSn?xc;sa)JoavUSnc%d7WRmQR)8uXTW-vstGD1jGE$V3czrR=Ji)Ce z&0p8_U9jVEdIk3uN&dvb&aSnjP5(H`?S1aiBT&0EPJ_~xI|p!X1-GWXMmO7!oy#EX z#mKH|v@1~_!MixdcV3_wA8LgQ@_4apaOYKqpu;dCs;nZNgNRShg5mS+)T(fmA$%*& z-{xOq@*&QCdIuK_b7cXORNthE>n&DcVXM1R%?ABXyl7O>%F?jhu5CO$7FCQMyxv`4 z+qf=A#P2;@0IlUZb$l4f9Vm-R7Ph-unb}rjcYlW}Y!cpweHtvGA`=`z!=cvm)0)tT zJz&hwzCorP_S+#xMzL9E)8#fIVB5OVz6NB8m7OYE- zRE^FCs%^K6kd?;U6dENt3ssZkpX(|*ENfkwVq#^voN;`+Qw!w1#GX%AC~>Hh<>tCL z)Z>@<2O|k=sJa+s$DEG-%^Q_M1AhLsu%YMyVTK@+ks8n+c`o{)n$KtguMl##1d#4txTasEX_i#f3a%2B~x~}(|g@pgKV8k*_|SY zyrpS^^x2;F>NOrM!p=&fb5s4y@JQav6Y!&urFd0Co-y9bTyNTP#|6P|fJiqRftknR z=i?@y64Dy7hKArg_;kQQS=anRr-8&SD z#wE|0AUT!g7r@rj#^p|CBPf;DHLP67tQkmidv#(Y;I%@6dr!CHf(&u|4cVhzAQz&@rQJAr%T8oyX(m`J4 zNXvDQugOHbQ zqo~Ws+LXGcyc#;@Qx-Pg4iq^egv=qXj2nFm+sg)5Sshj(l0!8^BLY~9p5d1Re7%TsvxjC^A&3N7G6IjSafRM-1II?Owq#U6TQw5vFBOyBO{PC-Tcf#zQ z41*_S72hUc7$ZWelvlkKkZcP(^T|5G1QLiH_)06R#r0G)>iRDa5yy)Lru0~Mkd!_j z$43;uek{CZEdPEQIW-YY>D^Z;XHr&CG@51=Px0NpB zrmF`XQ=;wRiii0_fJOkmUwYE;cn}Yte-K|ic~kn6Q@X1HP319kcWkS7aS{&QYm(dd z;XYD;UcY{0M1Zwx2;c2h6tPbg?m^9wZ2G8|=-rHu^gdBxT^q!HzVfsE9>Ed2%*k~| z1N6w&ErLrzk$fV=2O##0=z4!WVAyP^vG@xJ2@8V*F0aOS;GE&)9MirwJ=&~IrYWZA z9*DOOFpBV8#@OXXGz`?7$xC?`eE7CW)^1v60iemol|iiLftFZ|-AV`kU8rC5 zrWYXH{HndVClZdnfSnPxW?sybe?cnRA3WTBe5b(j&OB=iWTA#NyHevgCOtE;v(wOu z)vD*=N(5)kC0bUsQpW7#510mZsi1|$YbsqU{Aq8djv$Yh$s5}CM99rnF1qLGi6TGv zPfSg2hxX6H02zg{@3KXCMr)GAB$ge!Th_L)&rKE3mmi;!}n)3{%T zd-$hLGSA9xdCMFV`@Q_dO4Y#vz`=4Sn6#AJuIGnsiaduQ%oLSN)^v82XA82{^$5X7 zb9!u|?R&|2dW-72E2NuZ1J{>yKrSo0#ky2Wben0`it2*EJn6g%c6idSS>5`05yy(v zMVR;{7n$$DStO?ep5|k*N8xjF%gz+Kn5~;+G{ACvg4g@kOCm$It~Z9hqY=s$mudxt zH7fCx?6Uv!fGU3vpBI~GQ=+a-SZTTIp*-iblS2lJtFLE+UtGVT3##ENYSRvz z?{>Aif;Jh4%ML&M?zlL@FNU#!AKi5AdzhD^5DfIq1tRPqY+4_ButMkaN-##)Vg(>j(I=Z(LNKxwU;=KVM3+mv&lRV2^>7wlckNji5j+c{OR%?D)(>H&(hvA|M+vQmy$-SWsICPeG z;00)gF!V)|l3}G#is7jzN12yNSBiaeb|;`{ z9yHU>>NRo5WdKvF_tG!jDV~iiSU-uiJH*d4kv z6%F*1LgU>qx2YA5Y4vc$LhK@7Ld^iz1j!o@Yj+5ugimkZTOr5zYfmS6%D9UzVPzC( z(QNaSSAOZ&+U5VG+JvD~_afhfa!GFppC#q{jNy^X^*^ zKcuWt$nlUIKkf#g3XY-6GZQgFA7oX6F|u~mZNZnp>y*yZAkVI4R%;89G+Vn*T`Vn-qt)UnMOKGkP|l?f zJ(=I4q*eAhGT{pMp?d?&_Gv_$KEZ|dG|9{J?WrFC4vj%0thF#3>b#-s0r6R*dgpoP zv>4tnD3h^Fn7m81wS02W`4YNdncs3NKPK@;C|TL38a4{W){PuJSYi(hel0GkOX%ff zt#LdI{Hk3kGJQMW?qLms(`*rNyNPLWQR8qSvD&;#dH!C$%}8Finf+^*-6l%vNPtZx zk`grG$-q^U)X;QXb;|@X-S}J{roor_0(++#Hp$Pn_+e8n32>QlGkeD0Q0zUzW8%Jb zeD5#kRZa%cB>aM+uf0f)vdc8-PwFblu7H=)Xc#H3r8~XD%d{PkVD}pFrW*ypEIX^oqielGR4@-=P?NdEfMB}>Evdx- zVa%9AdjVFLVyzbzHeblXsFFx*?A=e0!5*sz0!4;>gokOZmGcn_kXKjZWaYzR%t}o! z7Pvney5^>DHOlekC|K2danRD)IoQ4j?Ho~$q9@C~ay@pq={QM-oqsG($bD)*y3^Vb zea^hxO2h)w?;!sc8tAf7={YOapJ8IR|Bcz-8r9B0#Ok0NTNQK0d|GRtCdu+m{*>!} zA(){Y1B5G0K&{ziI!fA4`W{>Z)%qE&l>u~@`g?-Fm#hM8rAgl&d4ldJ%CTPSX-mDE zWZpMdR7p`E>*JQLrTOZfa@id>VEX|a6_ujVn}IcgNTZyz%y}!zG5||-5^;x1B>N!k z5Y)>XkRNTl-vlf7w-VuW>kF-65J!9hC;;UL++V;u@+-ZBkgqB$?;6*H*^x%wGZ*Dj z66+1&eSJsHx#k&F6y1gt-;jYOn>ByNoh^$}4dQiUUO3OULJ}OfcC--z1&ZkO+RK3eUV?SP@1snQPqC~NZWh%Yr?#wsh2tAPb)pPB45DY9w6*tomoHh@NUz+ zS6cT2Ms$vxioJgbWpeGL1m`)<>9hUMwP-MUnP}jRs>^J2gXAM~jVi44LQtUi?h>JN ztGi9Mh%tIyj!xVCxDSS@S#9c9$`O`jD~~w)7yK{khmQZIDhFNwi`%|D%N<6@mPJh- zgxo^C_<0%bZZM2$e_4Qz6&go*C%t)dcZ2cmk)Jg$y~gzSWj=+E1JcbP~R$)3J%L8Dp!Tjjo?|;9tMS z3eX8q9xS_5N&b0Azd!WfS2xquAGjrRyqWns#<<^ZP+w!}nbBOkpuc_OKg;z0lFuf* zg#GrJ44c@7$Xnq*qw%kJZ(=zPS=q#dj`oiedV7~nyd$jaa^~D0Km9K^hTr>@-|M1z!WC-xzgP8tj9>i>^QpR1QODvh z{iHMh@}5&-^hthcd-X`|zdZau#uuv@{-v%?_^Pb-KO)Kre{+i7Bj(MG7i&lULLmM$ zmtGM%%aJdyyk7jD{`BV^P&Z(rPm?|7RrcSn_9=CKMLK0(Y}f3q(tm`L<3A8SBUQ!z z=jZ-;Xg7=LJKq~LE-d>`CMkW9K1qWMxBMCYV`cw(65&hq)`Axm6S)ij$$Ik((%FV$ zpEZBK^OsvqSA?8tDmnk=0{G+9PG$dq`r_kv1AqMVH_iDMKfXMrPgwf#*^%S_2glA3TUSBbFijHI6Ig%hMz1_OFzi5VjV| zuTBTQfAjY%=JH?2!Zf~gEm1EGP!Ddn-r7GikMZ}msvq-(@(z`Yv>r3~WmR>=6T+1$ z^@+t%FYU%7hO;{=p-b6>wZGzOQ=dM4V*qb-RPlU_!PIBiM2O?+_Lc7Zdmr8!*W7*! zo{^YT4$}F(D`hM={IH;xhV{7KB*K0hX9zz8JwITD@(>ZRe0$H}@J7guA~s2-m_Mry z{!;=BFoQI>R+HXTuXcEE>b7Gf0N|urhfRW z%_*%r<=Wk$$aB!nU))8_s-7ax8TM!rFR1DLAN|TrJ@qhlx4ek`TLT5?b0oyW3IY0d zjQ;8v_WLIMe)WLLn7@pww2fb2q8nguIJvIb)mzp} zNj3_pxM<``^rJLx|3R@n63RoLvn^-AAs+d+b8QEC^6jYD3@4tM|C3?%Lu2wA@(n##QIN z{r(FHb2!5(FEU}AhGY=d4EMO!D~E89gHE&H!j#U>AFN|@ACUQ_r7yOTpU(Ur_L%0< z{`LPCF#eZ6@F3Vcb1!{h-TJvC?qB9l_y%(wH3+wF7w99|R4?Er|7(WvY+v+;t+2N6 z!~Paaf|tw_gnu__ZrXjM`TL>;E~CGG2Yy z@iB7M-yM$A+x>kZ{>K&n(2)o5uTl4u?ymi#zR4eir}}3!UywL{jnjz(|1R}^ePsW( zW#5jR?pJ#La==uc^I^z$+QP_b-woZ zrV(={-C((|da1PZi15>N;;D|V1BEkOI_k|A1FyYr|C{yx(nK#!)C>j-555gjo0M?4 zk44dvnn1a0*xXAZBFDCJF1lZGICA>*jDWPX#&b@QOWMy1!fcK^OpX6{fc!rJIeYqc zN6BFUkBgudS+kl~jI1`pwIPXX6OEFfk@uVokR#W3wC#iKIK<3v(iM|unjUq0E1jhE z?N83}pV1zB?GS-UJ|#Cu&FP#5i;_Q14tjMBVVNRfW}|mT%q=Gwko@A~%O+5iESupW z*4SPjH}d48k@RHFGq019MCs?F6#wIe@jeNGoju+R=VKv%W02F|+J@naz(MD4VIQgk zew}2mER3=Z@nH0Mpc!E*Y|-Z4r}jBhhp7l{d?E5}FWOAj^9wmDp-6x#tF5f`GiO$fu5oKaEd&QN`r4 z5s_n`K@9CDbY(|ca?XqYg}VMvXr3}-c&7Y;XLM8VPS+BzrdXOT6aCohmRyg%*%;qL zfW$fg3%w$JCzQr8#q;!|)>aHqL>y=#gGVQaV}rJrNJQ1VHOx554$&x{+Yet%Rk&YmRd~{~Hog z^_z@)^a|{w#emFwjzO3Dk~=~O*!8Xu8Oj8NBwWX z`|ccGp~2D|&6*O>f_AmG_R{W6Jw!dx7Uk(A9pN@+PmqF|k{5 z%Uv1`&tiKIcXjbvVjcZzkLz}g zxP(h2%PyKuX8)gi{Ridq`ybSYk5sW(d2v71V3u(C#5&=NxX`@E9*ZejJZ|-!HPFqI z)5-G4mhKb6wcNas6aN!W>K8ef1YJIH*hZeIp)#di4-EIboONrTt>4P#HWqeN`sL4} z`d3OKRxo`0hA7?MwnLpHgl|o>`Ln?0Tl-CF~OOw`}M?IANahpGwGM zL#zUl_E${w z+XwlhDkg5#1)aG3ql?F!N9#ZEvhcrPctwBo*N*c|d1F_!fArb;PD%O)%cXwyNEf~z zU_)kwj@2X`pKXc0XmMb<lD(zwHh}U*&MAu=aqE)vgkQ>Q3BNM@SGN<*--)NuTc8gi>htwTrie}|r;n0rc@`YSU z0-<($8?>%$U(DDtcv1A(cxa6g?lB?gj)A2y&$sIimZb=&s_FyyM=HB){`MJpJxq^S zt$ql#g&bxkf;+l;KB{7j)p>IAq*RhFeM1Z`^pXT+WzCBAr3~$YfLR98&GgPPAxd{^ zZvW~!+4SK=Q$b?ZSasYPG4qbhmY=+!zl;0-UEO`dNatk{kr39fw%TB|@(MrViQ;Zp z&R??_%45W?M<+?HI{o0~-&T$C#|;6;9H$(cAFU+z(^92_u&U`KYVJ1a`@`<`x)0s@ z{etm(65I*TMn{{q*wh|YmzkDE?BR-ghUbo8)&DPHPB`)lyzAtK(O@<2K&KssNA}-=a>Y2 zV9h}l-&y{*Y=wW8kOGgMu)YZd=F`tN8YhNPq%Mz9-nX9yJL5oaKz7Js%k^3~%kB}L zuFeyUo1T&`7bPU_@P_S3EQf6dCB1z4(p83Dv6Tcl9No4cZY?0F+I3=6C9==KGPHHkSWhnF;ZS? zYGqP*8c{*mMT5(wf91wGnU&+9$tb$7HZ2;327oLdUw_$bjx2ijHZFe>?jsj46|oC zL85LvlhpMzah;g+{}J}yQB7`J_ps87*btB+MJdviD$-SYQ$Uc8QUin_Rl0z55$U~1 z?+Andp-U(9AT2Ys7R3WDvfNMsVp5(1648NzZf8@8I}F@5;=!}dqOT0p98T7Rz_~5CzL!Rv zi1_mFkZSU9CyyI@@W!D~PEO9s1I&^mD(%7IVDmD9eDJeFu}9k(59W+8d?{LX+=45c z+Ptl^U*NE74STqCq@^atlt+FYL-N@FufzV|Z+>gMvSMPe8k>uVqNLbKBM6}KGFRy8nxd?y#)8>PU&=&aM9%*ZBvA<@QniGZ32 z67mtGg=P>Mq-;OjhI`lA&A^S)-F-eAWj#A_6gWs$Y0M3$=3bA$eYwUUF-=6kVBGvA z^}W7=5>NC)w9iohkN#PWk=@xRjm6bvwZ-1nb1z+TkVMVWmhW1%ac0NKifdfc%F)+7 z%gel^E73JwzO3Zbd{O+(={$qY2g%c}h-#L&h`9e=FaJp@nV+|a-egH_B`4rDze^MU zSl{p=kHY;B#}cFFR)h5dc?CrPfIE`PkFr#wclRT=9k*DFL3)VwOXpb#4vzyN#nX>` zsW&d}?Q`N4XwjJzj=$~#j#&C)5bTbabsJaP+axdVojH=U&!2I@WREn>gpNR!9zc>_ z$~$V!y6@At17nBMMvUbpFAHiw{rOgr1CD#3l`t5?H`!~VXa}{jFQEyv5B?v4l6g*- zdHVOiaBRW16S|wF#&_IA)}VNY`D@G5jF0#fFS^xi)~n7=59yt%Y}(_uCYq|zI%Gk{ z-i6L$8+YnwfJA&T-^3^44Q(ajc(9JVVbWz|bgy$pF`})gXWm`9r}L+i#q4Ge0q>K$ zLI01>^68aK0L|}^-~`;Ti?NNEr|=S2`u9E=KE_A4fQ+EGVk0ya)_S%>3J_bzJP*>5 zP2RXha4gsB5&9dJIods+mtu~#$SvbS_>s7??b}RD7&me6fek(rFX5hnlnqLmIk#UV zY7#IDC;pY1PH$!ky3rVN+(9g$@B4tH{af5*{wkw6;-gpZQEoR?s~hc_(>>cr%qlDl z6W<6A5081*F`uiQL{O+*m#AI-N>w>-esDl$g#`J3b`0|eKL=>TBePT0dRc#Jf49MM zwz_~=laaR*>OZ;S8Vr~FO*SKl1+!)tYqd*lEJXD)+t?%MiKcxPIu$(jFOqA9=m!U* zf)p6}W(K5;*nKWaH`UbRQQHhGM~QqqUnF65(5JuNh~;XDgT|LXeQc#U(bIti{&h}Y zejpGseY^G}ttdZZCzr&5ij@W?EdFf>PN`V zj|TVsTn)63z0S+F2zrr4k2JF{AeIa-36_F0y@wFI3)I@6fpH1dTfgiSQ7r7c3(8fm z+N1RM$*z+srDm8ZQBn_IL7ZLcl#i zdf?HJ|57-A;>v6#2cxR53)7GBzrcgmz6`l8uPz4~{qARdL>QjHQx)DMyp3PC1oS8A ztL3Sl%Nc%^@$za&omqmaZX^Z~HpIq45%fp*CcnSW#-P4`9yIy>=8KKg zE#KHOd3mjCNOCp_M+>ZnpXeKRr-#-B%FMOi(wNi~vVN&?irv;DQGRi2@44w@rSD<| zhe>RfTv)f7s4;J~jirQQg&W4$eYy`hnxpjmx4*s5olr3I*K$0Mbd3xtm5XDiCZ0F7 zZ^G^<#UhA|czBcZB?)qmSka!BS_XLoR%u*aj7SL+L|5m3_O)LL-a=O+3*e=#lgtoT z$M<-{@zkemjXf)AjqiSWVeT52{~f)nl(k>is|eBWGkQK#)A{WWtZ@OO{66zWUOe`m zu24XL@}W20G*NNu_GEI~?<~6kiAa%l*=pl>l*i$E_YLX(@5l?I-3$g_!*JF8!+wT+ zVwLZ}ty`O4Aa%LtDVCpqDSgm<=22Nwx7;saVnh|eT!lpVRi$}N$2$#+{q(u zyIfwCYjsrRMPtVBS3)^=^QNNm6r?`*34yCHPkn(ANV~*PTRHCj7b%`h_81LzA2#2< zB&(|Wy-FX=QjedRRq2oS-A>k1pv}!5iOp8}j59*3E@tknE5>)t+%StVC@Sl@XAiqX z;v+S3uv>n?^1TTr8he$#9*g+1$LW$i^8?}AGXwV>T4O@L+>%leW6B3=1eNBi@0sr3Tfx2@ee&+#Ph8rRrMAZ!BRH;|o!pH`sGypHjpI2z5f0^mQyaE}XILPod zud|1h#(1A5 zSg$_fWfgT-++c@3PjXsIj*@iGrz7c#@KjW>Z5bZT@|l>1G2J2D=%_%Rg2b@yU&hlYL{gp0W*BkV;?Z#F7CnT6)e^4Jv9DyHexAM8N5GzCsv#`Y zTx`Z;Qy`u#5;KBw15Zk`!9Lq4jPF-S6Ry?3c_)`f2{qQ`iE&|V?nRw%3YL7c-|sZo zjsbVVpW{Rv7jGTf&2^J!&wgDK^ckP*Jbwh5Iej8N;QJ@%2>$XB2Kx@&gwL&l+o1V2 zuI;aIAQu+Zbn}3gZx4r#vJe&voobqOj%+8k*x2tkr+rWkDH_9BdBq_c{^m?0}qGYsxj(c&*MtO`AKV}J+$bJ9SG)Kxnw_( zEf43bQ??vP-2ykLZ|Q4(dncw>YZ?mNR?+3Gq=A|t`J;$jf7NvRT=H_1q|h)odZ6+~Xyg7sup`ds0V^Au9HaXt zEy!H|!MfKnr>oTEpThFR{~&RmIRyGOPj&LVj{FRre#&r~l$D_S@9=8A7!c1d_QEaI zUk#w14x_7e*r(7%{5ssIRdSsuc#H4udxij{g`$hGLB^7bj6OTAVp+1@{4ZIgq>Sh1 z=g-QDynlHg{j49^+C<7FI4R*@IW_TWYLHsy9L^;7<&^F%USd3%klY(c;qM;qr)Rp8 zm|3dy8#qxtS@s5vL8F@A2~hkMy_q`+MZl~MEaky>>l=D282{&@{6+N!cE-ftHpaoY z5z#djB6W5+lf$%WUu`$3I_q&x$ZsvnvEDeUa(Wb1Z{IwNIuu2x&qWCSsl{&UU1fxX zmOx%OmA`)@Tz9#hvWPVZ>do-w{R$)`QNV!Tl)V04R2g})kp06rE*%p1waa=?$f_++ z<5k*CO2blu*MAm!Y(R{~(ey{6S+Yb4H{jh(P_+J5XO=e5^r6t)yyT)UiPV^-H%pI~ z^u%^Y=U#@0biJujR~zPg?5KS5dR9sqI*E0(2wr4*hF8nmc+~mOnKEy$z&eg+T$)2 zJbD=x_mD9fon%(m6AGE8EzHF!bQc><; zSEIZXmR0^Tde*MsWs~8M-YPJI%2j&^f#XXwSyEF}{9dYbY@hP}FQm`!xq&HW_A~u? zFzm(l5o7&y3e^Ff^x30+=iH;RvtxwnUd0GAIi(|8NQs$5te)cahz+iX_qxPoe+RLANgUy#pX>eil z>4}6hzL=R8U^4F?pES(-Y!}Se&XwiP@JYpJOF`rpj@{3ZhXu%cL7u&v8U{heK43 zF@ zqkVNtVs%ZJ_<=E#(ZKyVb#}n;JL1=^e4z)w422jEN*qr~mQOxn)sa!{gnq#Cj2D#1@}Pj3LTj}h%u|GJCuVdcJ5;jSTK{#o`~>-1n7 zl>P*hmQS{+q5~C6ChcMI`^fN`mP+^8OX6 z(m<|rF9uX)-Qk+!7>L-&>Hc}zw;R@ymz!#E1nV7e`XwyW>XPV@&JB+Ojr&LR4iVNJ)sPYDD^`OSD$tQ?gKf zbhoaFM)WYhN^l_hPUwS*TFIM~0!XFKR-I0KMk4p7xHVK#fXt}M<(`{VUFg(a00w$UFH)=Lx>~OW zmfOv`s*AvaL4Kl1)Ity#cxHQP$sj7lMa;WAu4%^OpsH)i?Sc`x=Px2xUJe`%dHcIQ zxfna~CbO>V5OIL-mauNZe7cwSY;p_jy0EEf%;P*G=G&j(lVG?&I8}QlwE8TvBRf)> z+rz&3u#>#br{zU}C;%)sO_6n=#gS!KpZ23KJpdgDE)h1r@Vua(kQdDEzdEgM=PHV({w-bq;rZ{aE;cV-Pye<;&8f1bsNe$JsFar@J<`ue&N*bE`SWsh`JbfvKMliRh~MsDSc6i7KR&|WdL&{ z#?1bV(v`8sV|QTTgEG9K|LaEo4~XziXKvlrK7O$IY+&02s7aREb-H?c?oBBRBa2!h zrPUJ(rPZtA%mLh%cV=*nAMJad?!EU$_etSaDC{*+sdkFUjPIPkjw#6DlZsZ}#ippk z+s;08V;HM9Tv}9#+k(Go(I!dQ_KT5Py`!~7`nvSbMXdoSbwS*s^qG(vdvbmOaIE9Z z#-`r2-E)ihjsTI9_a}?Q$B4t?miy@uCFsjL-pa=KPoe%hTnqUcRc@lPw+N%k?)lVH zJRAbs(nNBkJCu0et~YLcx`&bGwmAC~*{`+d8?N&){bz2u*U97)+$R`BueuU<))dgN zki#qNyg4C11rw8v=QrWh@;#o^9=!l@YnTA_jrCFv?9I)Gz)HU66S+#TA!;96rACei zMltaJEYhhkQv4!Z>R~+>O!R!(9M6*7_vqVrYCRpJd;2dD6pqnD(>0k-MLB_!*KH<# zn8~~CibjyF+@*|G65I@@4*Fn@FLrSp4=Yxd^r=%r!5}qMRr&*M8{^gK$!I30<=)>_ zS5}7#I6hMPqydC&jy3erYn}!w(53x%-%9BYo zH2w8Xuh}Qy;HmFN)e9^>itPE9KqV8?2^ZaNYA3t#QuITO&#Ja{SslY_OIhRthn3co zSxKU04~7r)M)qbu0QF)n>E3WoS5tty&1IrlGAe&BA(`)G^=rD)+HoBvZ2o4#N`{gx zZ(G^drRF-Pm6UT|gWeR|A#?c>Y8ZNi* z;zToCPaMwP^MZ$dI8)Zn@vEipRi%~qKCrPRjN!;{9E6t;Nm-9s80WVZBpVsYPH}xGAx|OW!z>Zs9Z}p*%>4cq zbn^m9W=ip9*m7^{aj*R^hGo!Fah`4PwRi(a-I#%X0O>aToCsxid459*lrOz^?8I)p zbZs~f*OugH`>j=c9POL{Y?anKN3-5lx;a2zI;Aw(-pe z03ednM9O@6&{mP8uRXNU6S(Z;YMCGyR?PF38*}=TfxaS@@e0KFhy$ZSFASLwKauS(7Rt zBMHKqm3h}Ca2j-~?TLH+gu*g;$*k#wc76cgY~nU_S-OHc{G^UtUh2w~?%%9e&FRVz zpz`OFJl!!O26ROdV2WoM@UoZR8jQ3JB!;$WfX8&>fYVFu^uQ}K{tnPI-Q;OsfdF0U zb>eTb>B2uh>JAaVL8d=sQGNe7kG_0Y2N~AyklUr!B3B?wUdD6pDKyH!o^F2DlFrzB zNk*)GALKe!mSeQHjAAlRHn|DOQ%_qa#H6~&a{v*B{+xQDLSY*VUm0S)Pw^~7I}FH8 z={C{LXxH<-(U>EIIHcM6<&ZyL_IO@vf>B8}_UYp;sQJx@Y^e@+&_vuM*YXU)^CihKgLGJygu;oN!{X?G|!CjZ>}-71~~E+Bpm7~PD!-W zi81v*Qw|SBV;Xk-=}tBgpZ7H~2F5>9`6?L@*AC^|1`kSI&Z6J3XoLd`jG6?Psi}Ap zsIWg>@N2i28+43O7qmmPQ-R8vIi(`jHQat9p;8$EOKangYD(&_ui;W4baXo(*1afl zhV5DIr!@)js@7)awxT=ltnHX}j!wqG2RGjo z;jWZ?DpxT!F!gjU+VcFDd@d*^NE1LyakDN*bCz)X`_O4BRg=~Hv}o$ZIelOS`_Eip z)>=o&>f0ZpQy4}a#xS(FVW^V6=?hnG5!>VnCcOltOr&t$rH2|oAJ(*z>m}@Zo8;P9 zlzWCWtNLO+V`99m6r9h-(E?v&_w$nKgLi7)N_I~1z?-}bpovRPj6&DvC9J296;m2T zqApib-7iEexP=Z2H)NCs3AaX`BlFY@@Oa~k*XZtK&*%m{0M&5PEk+v^=`j%9M@%_{9 ze1e5-8JE@2=KA1WwJC5QJB5%~(eSONs%E;g0GtoJ;ZKDeij{>tYO`sq;?c@I@ryx~VDu|Xk0>u5mXuz8KLv$p z-pSVuR=i!Sy0ZWg=qv?Vh}p`S8Y52+_A_mMa*5Qk=6eCu zSPm%eera5gi`2?jj7RW2o&KXz^zQABaKyGz{rLa_(H_nA<7m-2JBY%rhFvV~d1Rw& zS{7&_uOIMuiAdE6oj9vrTL~b#;~Wpf~Qa2fL-TTx|qP8N-JnKACE|mWr&Np3?3l930nzt&1tPpRPglM7LI{ z)s}EQ((syFv~b%%%h@L(8`;L(hI@_1OGj>?FCel)8ES0uNaZTN|L(dgmQxGVGE zbP-ajFKkzHEd^#?R*T%eC*<(9XT&0J&!#Ho>|9G-$yQF*!1y5~9fr1n z-%Wh%9q+t4)M>w+um*~2rn~YjPQOmc0A}v2`?A?*0QW5p!FT1shO42)H}!H8X&lG) z4E#`4CYaoC!d!Kq+o9F1d1H*CtfZ{ZzQ9PnHXd(%ym*VG)R=pA0ZHZkUs};cwYl%n(n{e|S~-eo2sXZNuRThG z3RhKx`=gkK$fWOSkiQxFR=O@6M@pJYucWunWwuVf4mp+6;W;sk-(*a#dG=jLl{}W$ z*57mlS@g4b#=7O3R8Qm6M*2WUi(Yg6GBcbAEY!ou^0ZIyH*U4J0jaXk9pOVoyl_H( zZqEDki2(WZx%kO(48M7$JDCnXO?01t(+c1B{b~X3n!?W-dj6A<6dS-~kOybre8b7l z=lX|eI^S>xA@I-j&w${C*L&zpQSG6L)WY!^<*)n8PoogpSufu6hnW2=s+KKnw22$M zh(|np{*qgv=UEdj(J0D0(tA?i#BH-GzVJ=OJDAGV@#r5_8j;=bZduG>RZ&KlK(5L? zA$|r*AfH{t9(6J0BU%u_N+ScT;)Q{rj=4nY{#^B~WcInDl33yKV8^B2o(6aF#dI8# zTXCRwf$TdfRb6hnvx*P9nx2g#rp22hsbWr5Dfi;tmqw&9bPg4kTl$4Y#g;H&?)lS& zWKEc1XZ35{-a*V~$+c46RafrU*QNs_1~~psO#C;|>rGd`PAYWVDMfKgCsmn{d%mJg zuR3LpX);#I)VL6*n(7Y%vj}(eA>ZoXd|p)eX=F7}n{qVs?X|+f_t9^PzKnw3yih*( zZ04B|d4tWm+=ymBLmCvuN=HF-Pvg}v`o5*n>{JK;}4EYY|cli1n14tFy zw{yEiSNmvkgMB_nwe(@ChcXV@64)c%GvhYR+i3#OwixwO3B0aI(*hYP)v7j(B$Taq-0^6363=3@(z^?YHu#ddgyOiO3Ex*$FJaV zN^mQ4v!=>EYpn{9$~tFX4W8m{2jsb6T}HZx^P2mX3X`wA!#sxPQ}N$W=K_OKEZmWu z6h2!YpmAem`6=C$;tg|bZbcL7|ZRH^W)jI8<54buJ;wza<#A0R)&;O6Q;55qlbQ-!+ko zwL~%InA1u29n*9Q%_rYI3mG1@lF*hznFB{95q)0XNisyK-Zt01qGk_bHKF;9W{AwT)ZypB{-B^8g4mBN4QNP`IQnrH;(AmyxYIe) z&6!uJ5u;-bB0N4j3E$L0>lwT%&@Rkk@OGxG-@Jq5Y6Dc8)eB{}5luZEzP!nzQNKZS zVP|Q}zB9?Wsi}ig?((L44ox}^X)XYL*`#CMBy<|_5wZR`Kb>}~A2WMsN(r$fkOx4p zS|N!_zkc^TQ1yHYB%fe9Y+Gfej7G64{vJTV8?lLrO&Y*##{~fcy>vzkecNFj!?XPI zrX(J|orU8C1Lf-V*XR6qg9=Ya>+|ltwT@!u?{II|rnX8*XE@0c#q}LHb*k-@&ZRXo zFBCe7qA9dAH5XBsJb2C3;MOtgbr zjXv9KklfoCT6>XlUQ4g=5KxjV7A(jwINhu^--oL`PhlH?!oI@YVi*)>?LFcqIHbZ43A#~=sw(r&Zo-_I^^8Lq|)*>uV%7zYD%`f-;K zP1_<_^?$qowz>?tgSTrpSi~i^C#Yd2$0g($Q-uL(LKlsZYDc%7wm#%v2Uqb?k9w9W zZnzDfxaxtGOdUR+4=K-c2T$A8%XRZDTunHj(tUL{)TV*ZkRCj!Kjxrpj()Y~N713C zLQZqAwd7W(2n?9oyAbgdW_o%iaO2yaA z`V3+!JvL1kW2i~;s19hbk{n3K*J`4SQ-r~JKwee?SM!x6ar+$ zZJT^&2gqx~)WVhQrDsjJS%oT!yC9<+ZxFu^zmwlxR{AU`Nd zogF*T?sf}0S|&6(PA;{9xgW1&j7yfMkax4c>y|GfW+7kGfu-bMSrP$+7@9ys|YcxLD*LE%fbEU2TV@viPJO|5eaA?*H24f^6M zP=RzOSsld*4z99tWK63UCH0Oo`KGeRs1=ix;fPCzm`)bYjXRq7BL_By%BsDv9W}-l zmxX%pPzOYYs|~T1?1g_{su)Urx=B$&2eZQBN;o2gMCf9%%R~ z=f~uD)m84D$7U?jBlTM(kYw$3E6#B@`jE?h(O5R$!#Mn<$rY1|I7fWGdL4D?>g?Ze zv^5QF^QDx+Z&jgJ2E1u2ej^9axA;|lo;V;^4LniE@Bw{6I#1fCXJMum-g%x4JUKTX zmRbTztsqt5u9qveTyOEH`RG5q&D*o4A&!)Gj5M6MR2Dz)$v2MG%j5K-U5%lUsUM$+CcUIjI8L^4Obz`MO(hwilX(YBBmMB;Fu)_x zP>`*UY&`?ik}M-xa)O-34T)R5zl&q&gl<-Df3w;Cdzd)dMQ zBcUt#&9dei)$5ED{d^w{73^`%6*yh0SwvHTuJWZltrpBHHHr#gq~@4kgs@IsSJ6I)W@E$ah^Nof?>t#mn7I|+f6xJu$;e6}h zP*e+G`tztB#t7YA1k~s_UNs*tAU1bM-jJ{_kJJyrZTmihCs7AL>+k>ZA&|NF-G9vP zucs%r@07OVcT4N$dP2;POD(?yKRpd{Cn z@bk-Mxl+P=*Zc^XNO9%@L@?j09y;@nNSIyP*{m!QaZy+c{XTV1W z^*cie&Cc z`?;I)csdQ@H>Xlwf>^~lc_eYnL1>pD@e&6u;L0BaBxly?v*=2T;xi1E__}^sIBD6M z#oo}Mi7V$D@=_U}UIOYFFN8Pj_K7XhJEZ9>7t2u{t*d~;__Uz+^zvuyq#iskJI_dK zFkcgJKiIX}Iu0L{269d}EH!_~U^FcLmK~krAv3?jFW99Khf4ef7{3TQe_p|nUd4}Y zfV+vSoTfPKG)M(_aVXd|n03MSPTJiTI}(gVufC9;{CIUH(KXWP6m)Mf@0YGhTv6OU zuY+tk6Q&tgWcUuxT&G-*dw-c1%D-jFZu>N=^_Kwl&`K`A1}|69*J^XBQ31O-wE*@} z(2OQ!pIW)+1R?rc)5FRAn;MeV_GvRl%}_wbfSkpko26@LDh4=z&m%(Sopw|w8-YV-cd z{t-o`S;|_oxUd}XPGM9c*az3}rdUq^!Uz>M7PQQHRHBrzx`i&U@!IdG$M)=(?0cg( zC=q<14*i%;iW!vZ^U@uRxj%#9`eIdjN<8YD$l=9FKBQ+U02dxVDGCa|?lvuAI7=@r zAC?%e;;2mb;yq?Y6p>Oc4arb+JBQaF3e7#o+4)}1JQg^EBW4!yXyYGWWrH+f8$iOp z>;Y^rDycVf$Ap^`Df`jls_+Tn+IdH2T)??!vkX`j~uemXa1 zeTyZR^^S&lDGR^B40q?9BD;UoNh7k{o4ZE>1)7`KLjqzpond!2LvJv6DZ=YtCF<-UyBz&uc>@)#01r;G)wjAZX+4JSN zcgbN=%t}f)bHs9ErHe|X`)#p~v&QJLX#bN*YafNq6#D($jS$7=ruVVt+(=Y3IwW}ww*@oq1US`ZO8cvUuDC+ zPjpnNE9Xyn2WA(|_n|m0y_x~%8qNG5@R(F=b1^K*{_cfAwY*3Q$7OZacb)#WO7E}< z$hSSvd?!VUc`m1InERFN3Q~sQGG@mV?B=8y?z>5&N2B$S0|TjkkdX8d>)9qZhnQk*oNx#En~f=YTs9F-G3&nRc-r|q%bhbl-D&SzhAf1 znAdj9?vW9PwoqJm^>Z>ElEspvVG;1uebT&lZ@9y%Q~)eizs9xktntjG@b$){{iO0J z%!-lg7rhmVx^10uwj`5$UoaxYB}uVCLrJN^$oA|AO{ero`iTu)@%qmq>Zjb`!2A$U zVUc5;a+E3aUxVwIHSj7NB1e9XyKRiM-8Gl^bZ-@t`+~A~j(0`w(PAiONMA|zFn73? zt~N8Shb@eXV!h|{bCs}0iiD3?&%%`?c1g^%*xjX>kh+RXs>+(a273g;o^2j`xH*BYcL`{zMD*XV^F z0v()N3G*GdH!F87Jy{9xNUb{>Ji|nX1OmO`MEVTwFT8PN3VMj7UQchi=ObZtFS%C^ zl)S)&vL=CSxhFJzk00ukB(7>Le`BR!7}9;B`JI|g`3?=Z%)}&0_4NGCW)o017U~}s zWtICY{!Tt`d{Nx!U1(o0n2I;Yi!%e_`(9fla?5UOL;>G+j~k>yL^t{kkbUkUa~_Gm z6!}j*n3+j9G9`ULYW#2&PY#8pM5f$E0S;I&JC$g%ODl}jmFxl-(U%O?6ufUo#&Th$jW_&5>r$ZAGrPpqJlJXE02ll~PY5d?CY6mP8gRltHP6M;Pi_>1o^IFVCGg?=66U7ag*<$ku>P zSCIoH{J#7%Y_E$tr(}pxeoX(?z`f)mbPfxAT|CxX*?bAKC!VR>{4C?7Ndc*Bu3XJ{ zU|i!9aII-yYO={YxU{iMH}aju{tj)j+<%@GAW!n=GsUB+%%ZML_iqXokjT7voEcd= zVXY)!a-5rVV1=T@PJtc>;rzQ69-|PCuH;i|UOj&&)}OPjs;vHAkoSe0+|*IZ{w(?0 z)kl9?TV*(JhX`d*^qWA~1AgR1;Bw`-)dI_WBSTmdK`gf^wZK=Nb@WzfR=GCF3w(&2 zk*N2LPP~zbs@Y69$7%L0tHyLn0Ua};k7*v=&v};n1`~VR@=Qq3Uj9>%^vi!^KbcUn zYmCm}(_swQbnwrri#*OOBXHN#tF6&ROyzQ;C%HVrW zj5gNS2wwP8#>vPu(9(DX(8%=YwupL6)_nxJ*?Kq&UDfr}RxmjSgKm%Lm|x0VRl{eX zrvx{dV~P5XrDz;TlKoT46R0ibHkX~g_eXA0^~T<>c$^YJqCm;rJ1 zkq6bjcg^0f{?AIszV{2~d!kUJTg>%5XqJCN)GoHs6WarTwwn)jMu{mJ^n%cmLq7R; zY9n0!wz|sUGCFhqj9>B$GwKcAev`KFm_=;rB}@|NYNxz0q4!%J5-)}&?vL9kH(5taFFR+?trJ7`XO zlKcEgw|l_@;eY>!_x)njH}9i;4x3anc0+kCt#Z%m-{qDV*6G-c7jl9Dy9ZaWzH+|$ zR<02$K6kZ1?C(Abj?_EHgEwV&o(-r5j}aL^arLL!477Cen-q^M8Q}1=HnF++Fyy1C zNUL%q9np<}Vd#(=Y@&1upj zHZh}UuGISwjTFw(r|Fyt6p1|iYU{il!bXs7=;tGror~%k{>RTna$VwcifH#HV)NO4 z6|xE78f7&F7x+`&w|ecw9*kZq)DhFWoqZAOO`GQ3Y5HG1LHveD6ASM*M3EEl-yzh) zc!>Jwy=6LG`UV;D7u|UFsx$Wnp7B+04bXdks>+0|=!?w11;wj)6~t0;6Jem}TK=DB zr1>%8Avtp6@e{p=i_L;Qamh|&%CRS##|y!NOAQ>v;S8y61g@W(HPMAvV$Tb`Z!hv8(sXon{m z`v(@0CisWmgoG!Qs*OHdmLTKuROc;i6RuHfmNj}jd>VmV%`}~nN_UE+8tcaPWDvVY zs=i9mYfgTuV$qn-TlB1LtWHmW;G1QZ#p>cq#UUkb*z?5xZ-@6kD7W9E+udY_JC;VK zO(9v$j$%ft1BGR)o|!9Ad@Z;&MPFivi+^7S4y@#xkxvH9^**48s1g$iQ`UH&T1321 zVB}c9)IFp2*$Yf{(BxfnJoLUDm26tz)iweqe*BAMuUSJXs$$%TE5cSmaev{dN&tH` zt3}&2wRz?w+9b`g1_e#65jNhe?Wn%~xSeQc_W=ktL!95wp4UYm2S4D?3i@ z=7)2z>ttayVxW@5UKicS!T4p!tr&Jb@0FU{6*wzeu~Tg&sShuEJCc|KU63zSTb{|w z2f6nie95rEqsg&(Q|s{c-%sQpJ_HueTg)Ks72`^E-x;S8V#9~O9a{W-bX{+yOb&x; zIs2Yya!j!-kLSnhwiY6uYj9p}bsS z61Jk}t7-JZ#3z9yG51&mM%uHjl7mj|!qjm)D;ROrmp{}Cjoe~b+4Ck?o;nvoEI&Wm za#p3xG-VHY6iEWuXo5Nsv5T>)lXUKZIWN-qZ_R#F6-SMJLHu{e=4Wg-Z`OWw$yYDH zcGmvmXbhTrj)Gf{@Hzc&-{RQN?+Rf(2-qC$|; z($}|nNkdy}YioICIZ(-Et}3PrufF?B|5v^Q1g>s8ul+mbFN6MR-xkK5nRIJpLOzZ|CJ&9tKO6uCJ?%i zsp6VA#@l~@B)GF07V}uP?WVJy8C_+#TYZ_hADJIw5?tkf*O{2zzm--VpS=O+pl_o? z9J9vqL)<7(3nBQ=zxeM);MO}NB!&)6Wn{~IcmJ1pPNoCiEz7WwH>eJAs!v3BkBM1V z;g*U+GWg!EVO7pRWUuN#X$CN+(&d+8Og@R^wL*7ZbR?REz7JaYuQpYFndAfnd<5QJ zM1N#2|8qY4W$c{YQ7ZT(saNpDEk5ZDU%}`2-crxYt>us1vF~2rC>^KbsBHySSY#kk z-Kq3wY;w5jlw6iv$N#_XtZ#QhMj;Jem?F}pfxG{!V<6KMZxT}`nDT3T**k&q<#>v zn?u~hr(T9^Ry6pMuj}Lw(3Ah#D%O(wPd5JNX8qS&<;vuk)cT{9AG#qX{_$Q{@Z3q; zJ9S1MeJWuesG?BozW)EQ_m)vru3P`GAdN^0N+aFfU1E?@(jZ7mO7{Xm1*E%CLb^K^ zNOyOvg>-k<|K^;t-Rj13_I|&;V?1N!{GJgFZASlW4l* z{~yx%_uFx_McA1tW>Kg@>)XA8OLddjWK`g(p8+PY@!6e0`87J_EQ*f=+>t<7*1vU* zm&38)ZuG&svInARv^UeF2x5ZD*T6iPnpv!}7!$mO55rIY)XaaJB^ma%p(YFD6=n$rn?AzN zaVZo=jC=RYE@j_bKHo#YUna%3(!DZzi2AxhbflOYT2Ju4uR?(ws5f>-K|wL*K11Ad zzsit}-uU)jP9Z9O8x-wDL4-P4NC>MMy}+NA&!6(26aydh_#(37gpPruT36{;PKiX3 zk=mY7%r)^E313N<#6nkeq{>jS0EA%gjV1<=o#8<~_$o3y9LFI_rYjt?ELWB>3-7ADA}&+AGZ>9F-z!GD6}dNs(Wc5D>OVg8bh zQG!Xz2+yVBcUm-mb^JXj)TV#wGiDS6d|&dyQ87|EVzspeC8Fln#L zGN*_lm&uLD@uw0sy2#rzR2!E?U%BmUaE(`6ezfJ!%PfZxzWKxzc~ZLwY^kb_uQB|x zYT+gIS)BayXHJt89g3rH1dc{WdkEOk;PL%lu8&kKm?-LadWq~si5oh$_+7~%$mu!i zwG%@5FABew4VKyapM>Z|vaxr|nXe7Du9)!~UbM9_FzdL3MXT&BUc!>C!yH=}-pt-! zqB?@%_uS7S4k%v~wi?{}Wvd>dxE>ASW2<1$6U*_ox4mck?C6cj@r9J0N|cSAW4Zoy zedQ!r`lhByPTYdO z_$)JrD*YIQY-r_$ZQD&?pzDnboLB@FgICX4`0c$g;*HFs?gi<#boL}B>rX@@4z_A+ znHzZ+#_E3v2i}3~y|}c;h!uuseHwn{0}aFUyHXQDIr= za})MGBUpU8_6am(S@Fc1X(m==L>dw@1a1_{}8HuI~?Iyu58v@*!4y(>xnocYR?9O94K1A_TA4e1+%E37C@zf zfB@VNej${dTrS*u*f%Z#DT<>l11zo=O^5tXYaoINhlL$xASIU7)Z{EJ0*dwoDLs)J z&3wov1NA)0=hDLMmqx)f#@s(Bl`1_r*$%zQ4q z-qUBDQPw}lor7R@j=ekhi!@~ZXRK=f;*}rT_;Mq_y7MusSZ`$?0 zeCJ02TpcpD{4)){mynRCmzRK9_d}B6{_6~q?*L6AZ4r|uiL#0D|Z>@0`8D8=mUik&+G=ZZW=>7+J zTyKn36RJ`^rb`n6&b?dJpE~-{|1v!c8W-Tc@Y>OE_8;7Vw?J4}UlfDteLg+cS5@LY z{e^E|kM)%tu;xWau{J+32zfEsogLy#RpGq1hbs2=pAAi=eyA4q=U#{atx=$EKkp}w zIP^>8J&K19KiwxMRMQ%M+D-H0T)tn-0}Pl4OWdVX(?!uMH*Wc7M4}unCDy59+^tsIO=*;&nJ>@oG*UXD*R~r zY9wo#nk3o=gpZyW8X96s(Z)^NIwN(Li1dk#ySniL1wMYUGewdsuD44y_z$1Ozh@^B z>8Tx^uR{Jv#?|snG z<9GVm(f$V}MXwZ#)~7-k&W_Ta+1Naa>1|4mx%X0^oU-m^I6xlscB{=;1@gz`7=nL& z0f<}{*k|%h%B8nI9_nNYI1bMgCsenlsHV*^#2Zhk9zDi`GN~TW&l`2)mI9UN$F5Nk zhszZ0e`|8%nmB&Fyc1Y}9nEhE zl8!ys1ob!r0M0V4xkqTb=8%oIbMs9Wt&>u9A5DIu(q>#o-7Yw%EAL(d5%7%78YA~S z?+g%>NWCH=Pkq(-dA`;pe||jj<6mD15b4{0H3~TNGl6;up(t`$OvPKiA$l`&?gKQB zqrVr6u(I-?$Zm~myiPx3=!>?D>1ZA$v7C~zean|WAD1Qulss`O(l_#=*p%xyatu{` z{(4fY`fz?S65-FQe)#nLrB&7BxZ}0`mORZ0BjZ z(3lw2FwJtw82=+h2+a%M51NRyX#{r(ABUm~C(>Hh9V9Yn??wSm2E|XG9;Vr?>Cac0 zId{B@vX44G-tD2fS;PC0AA;B@0T~-z7w;1@B09OKio$mx;XXHC;?{${Cp{(B4>*Sf z)8-gYSIsOtzxw!34OVYXBz_t+!zn#KJWCo_S|lrKHc)HJG{$KB*4$|@)>gPXmTEM= zfJYL=)auZaY0|gqe!OGk-UzNw!6G^t0!!v`xa1dM8oqu{|n zW#11}@@1cabOmnSl_sX=b*`1-rvWa@*5hSv?*i^~$pbxt!jFWHrQKtX{7Z~yq!Z)M zp=2AGKW@bLnIerS{Y!#((yE8eIhF>)tEE7L^WqI7 zMKsqwEaeuV;xp00KkGsLd4lC1!V;4$hv{T{fy(D!_W}K$F8!@035k!mg^o z;|c~`9}JwdPdWl;xSV~LvL6BhY_~os_Htm~x9*D%vwZSQ=1s2xIDko&smEf(gdsGv zsC9Qb9q7QU7xtPZXrk2g=^Pc>8&@q`Qch{kGpnbXn(>YT?+~)!5_Nn~cFOz_z!cOO z#|cpueI`%hM`cD64yy=X>zPC{3?$BwLFWb&aqt_SglIm8iV)J=rG|&85e{bZE(a%4Rt{*wn z!^Oq=(I?9f$ZsFklj7(j5J+UGIL`Oe?jG`!j4>O!wdN~)jy(x2%eX@{(Cb48$GIi3DL*ZGi33F#VwOs@kk*pvEzt>%^mqXr% zDV>d*_@v?p(^>vbk#=j`9S)GI`O(FqXFb9c#tkM`=J~`xUYJK)iG#3h)_g`KxGhWB zEKRMr#bUZWLyJbE%yBDxumghU&InZXvngNuy6d6R@xVxHab!iyR;N4GV$^b#e>r$= z0FBT5ExX-Y^)DYHPlTDniB%5^J5L+O(_2s4j;YO0b&WnFz}{IN)v(xfNl;u6f|z)* zaMTtkCOWMuC+9~B} zOQ}c2q^%wxOxSi45f`%am)d6BE=4JZvy>w?my&4pH%S%|Opomh;lFS7E7-jy=8~k3 zlcnb7w=v=y%|=QJ1vnQloi$2z#uovy;FWAiR8nt1EwNxI&f^xMc zRc!jxMkhVr$q8RQXR6!QGL@z0dY{(jSO{rYlB=lii2+UDY4y9qC*tSqNo!rWO`9GCnGL4 z7Dw5yJ>TmXsr*5lpyxDDgXW0>>#)}oHO*T{*-Cj7)1D zYn-o^J}*|*avM&wuQt?e%LI-Gt0*dOgZvG4BdNRr=rJT1UMrnc9v|K}h>)Hgd^{n@ zk%0T{ZC-1~6KeaA=;-_9mmY&NQLJ-RRcoh`o8;&-b9rlD{h7gJlMd@8c6_-FW|lQ` z7NcEgpSQr1TFg3i@d?ixxc$8?hTQljQTSxu8a~@*B;qf#%P`x{J<=L6VdQf#-O_kf z%yg`b^M$@8;4S7RfH9 zwBqp`yps)^B`g;@i*zBmZ<$eKwaRC2Oz*u_q0CV&DV}sI%HvXtc8(;`{Hh<>2ZQx1`%5_aaWlt!Rt5|yGC!r`Klt?37dht6wmMvXGfbnw**8G6FgXPrqN zOr^abVf9i0z5>4=VIhBP2@IScCA6>|*N+n}0TU^=e&|XjD$}yp%Hb1UwD5&v)-ng2 z`u?*CRHn+2T5;`Sw&fu_ql6O=`?HuUUS*~l=Y-Ep9x}7B7IDD45QbZPfCweAC_qfJ43jjKtQPD#8( z{fj!TH?+cR?tbgf_GO!cVDT!W@L1=EJzmpz6@UtVu2rGB@@ z(v(T5_|y$+&in$ZwlHHj*9cCMPNs6u(H4g?Nu0IbRK^5mSGye3tL9oq*{$Z)bU-?5 zll*s08^2@I{&WKXpS;MRJF?ibcO-k@rM#8~$hUi3NKS~lI+V^D0md`myhJrl zdn?{|5OUQ7goCO8nb>v&>9xy1bTnIaG30yCw0ns-jyKQ?q)k-rf7?qS^SZ3Do4gBV z)wsuEm7?5<>wZyYj%ES%f!M!kL z6JMU{kuG2?P3%354#-Zp$!HZADUWQt2-IKuR{YajcQLEk?AuLPczxG@uFq| zI07S~Vz}$@Njqw<5LNZjdW2=&g{b@G0#G$(ogfAZ@yfCsw+GH^4QKoC!R4L zXpkuN*x)@)-z_qWREIq@uvtBs3-478`*n^+(U_~kCXNh$j>9EU;6RESfy+{gJ7)fZ z|2U-MW9?ROCv&w(mF1am#ZGEaXf96^;hy5+`VQFZ(5dKg;^|j(_*iA6GpowU3 z`$pFS;1Dy(pIxyNSW*z4XAKQ=3r5je_J$^wU99Jb-Wco4BFxDx!!%fBpniBlz}w`6g+hciy>Vi z4X8f}N;nC9w!J;2Wnvfz0MA;rMt#(D-091wgp~M*U3>{A4;UWUF4gXCI0!#gSFh6H z|C7zjBgMN|d(2!Qi z;j=TH>>bP=&2c!h1G4s+%v5~iI|7N2*^GJwPV{$lc+J!A{vmXK6pTQuHhL;)=Dm;f zUe1*Q28|3XaUOTkfJUF z5}L=zHDfx}Wmi1#56HvK@nh?Krk*x>>IMVK%;HFi#A;F^o3^v2dkO>xvnP-n!2NE; znmoy?+_YbD9;hrjCt0+$f9?1mj~J*Asf0`Mot^L%1HWTF!D+h#t~GZY{pAm8(mzpbPor3stVJJ_2>2JwX2h(C>{4GfOq@JQuedbzYyhzI9@0( zvKL6T2=OS?ojM0X949U(2+rCgYAr%4g)hF9|HgYPMhPWTAyX;|Ah-iEU1U0`-vt7D zAZ2?&US74A`ufx6AVr2{-zaVO!RbwgWt_V~GR`gOgLbQ8J5y!m^fBBXDg682(#92O zDk69p7}UN&^33B@cuRIOJIF2{-{uul9?9vhb78h3F&j1C&NdyW070rCPe*X>y4x92 zMz?P6NVF@;2{3&2MGsxs@-Qu?Ki^q;4)h*rw=BnRvT9!dv_u^b-HhPv$+qvu9YX@N zl$c0*8!;#}NGOq3RmUN2=!=3@pm3RYIQN5GcTUB0-lWorQgg<^bRp)2j^>k%i;l#o zw$6O%2<7b2r{#)OlO~n1oaPMl(zx%&b=;U06cnf&k5taqZ3RwJnb=ke3vJ$wZ`pAl zmJdo2njOXj2a}?9387OFg)7SPiaJAVO9y?7{_3d&c(fQDbjMKB>M*47o}3YOFA^aF zOg9q-Cg!XxodXnsbJ#=Ui`7 ztK__3WUk$foSIsi(3BdPJ9VkNO1Q$)nfHiFaDT9&5qViUl?s=)pg|eOZF!)9zS!Z5 z7Pmg_b~*tU3GOO9#)V{(+wg66GHq;5Y94M0TeT&4yQBG4JTJE}e_*`mH1bZCwx|g% zMA~IZJm&Q9PQM5)<8`|opscqg1W$4bZTb&^4|0X)*lQ@3`xuojgYPFhojmxcD?UQd zN8J1L;M&6zM>;thI=GbE5kcRSxPjw^qSs$M;XZ4Vo-kaIkwn6_Qju#4WSk9O`i;n|=(W1})hW9YHBp zh6)o1jW(@N8Nkfy44>Ts)ymhb9eC@)bOwR$EA1^G4g?pl|;;sFv^H7sqxh5@Z zN$Gufr38CgsRIuPRBlVcW>gvv7x_#+3YsimwnmJUE3R`y&*?RDi;IEqvRZ?czF=&P zN_%s2V0@)T>*Bx#Y~RC!5zl+n#tVSL%qw#j8Q+?_;Jf_|ry!ESLEwHQayC}Ztbog? z{_rd;bpFL2Z=qo>{>kPO;Uj6+eVDT`3nA1EuB4cQHyH?2^U6%M$FBWS&dyaiFDf4a zfM8QLA*IgJPPsQi-F5^wdde|q0!302=)`X0BB|2^lDmo1ST!%;oqU`*iXLHU33jsjv_%+aQ7pZC5C@q^h$g~k3W#hAaLcWN%hnZ@{ zRfEGq9=e;-XNT1!8#uRt1_thvHX8k1nAj~4OZLY+=FbNQ=1=1g+V+_1nD}zN0@He# zYxaFLUBo?(Ha#-jbUkt{2dmPG$A!%5>!YX`3uHZ#VbJEN1t_;P@t*Fhk>`Q$#iniy;v@)x7z;n2uA= zqAtzZpD(Yaj^Evn-ty3`nG`Dbsh=xT^bokr$>EM6b-jJh*7UuiEV#{WYGR8CY(lf| zh7%nl78LW{O%k3e0yMN(=RjLZbaMuI;lc*V+$K^d9Oi%k-OAi!k=LR>$1Oc5flemA zx{-BwF=F)RiK}vtdogt-9#l?C)lO7GOt9Czk(wRj%BaTlvQ@JQ{bn0qc2%KGj?Yci zxLarPYuB<&XHB=ew;uEsIsMDe!l%`*bQyJ6(O{^)Jv~g}uif~|KPR{Uy_S@d<I==v%-fx8@o*p*^G~4tD$S!9q(GRgp@VLeRwk zG3E7ml}w=U>}vq#*_&CJJIH@|xIROV51kDM407U7s>(s@D@-Ehg5_y{g3(L8Y=_M$ z%7p586L0Z&d$jJgsqR$mJY6=IE^gXTH+Bi*;AZAGU>*Yr}1oHFQ{4+6%n1Pa~pHq;c`v*E$b0vBk;5SskZbe z1N`SrmoY$^YPyg6EcTQd_LvqXO2u6S;j_Nj|Ku#{S4N*pv|M+%%i zp1DYL{-*ZQl2f4jzUH0t@4B?{l^c@B^k=*~VonJ*sSY~-ba@R?%=O0pxk?l#2P z9Q9p32fI&;%L47@RQA6e*N_N>vCH=M%(L`MKS)+&=2;lCJYN+4T8eWq_U+bRy3IE}$nS)o?u|4KqHY!9qqYXz zt)b}YSE>kTHN34{>X{AqgW~Gp1U+hbwlo4arnCVAENduBd9a*sbU})wQm#eVHNV7i zRGkCbKpPuEns3uCxzv6&<0>0y(La?RW0>c7+@Js`0j%zd20S10Dp%PE9uK5ii)VBQ zjRJ03ZMPL<-i<5S-RxfT1r%(nofeOz$SeM|xS=eyMl=*;0gD9U`8Z~yHeRCyrr|Ea z9*`tEi>8CQT#VqJmdWIZusl@(Tyu>RyO~P=jnW>~ zCm51u+RV(w3j!E;S;??0j%4^3b3VhpU@RH~2f8iu)uwh@3p~cl< z$kLUOJFS+m?fA}9{GoLGsJjR9fQq(>()KP4M1fI^eE|ZjX-sj{u4~<+ovWN{(_v?m zns6fn1De5hPY08`R88`bwNeAe=#_3-1U{un9fA-IITHP2c@99QFS zhS2^%pKnD-&&pOX?)3Z$mHXkEA8A-b8^6O_z?%z?1%$Cv(e#g9LT7{f=?JuImU_&f1$0B(u|Cw(s@MoN+E1|-K# z6K=StoAn;*%!YrX`Tgr1IAWfe4^cppiZ`kNe_5J5k$NS}2BP@>Uw^rovOqO(Q<)DR z?wU5=>_Pg=Q%K=p4K$Hp=)`}nSM}?t|FfPV4RBKdsPJa8H=s0bB3x2OSmN~eNW@g+ ze`_s8X5r2={7C&$tei`J#*O@C-2Z+X=p}N6q9jJKJcAV9--AwI!bQ`4LNd0!5wr5^ z6hKgisQdPU-<5t9H3R!T&9u@%Aw=NsIuo%sIq zD+uGdgz>`{zCV}3`puL<=KvP14e}oM4?_5_s}6*lVDZG@It%{R)xlt3-%kkoVSirN zU(e)!eigfh8ot+ka3do3FHhLT1NQy@i2KLg`u{C)Loq+Jf$#mjLwO5?fdsHMxG#5Z zL4bpa2PaSL;y&K#G^-#m6XCA_c4hm z`-$B*@P>ly|NDWXB(J}h6Kc(L&*h0+Z}9v)&J)=uoFJ43Y2TuGkN|Zo!4rWzEn|&b z{5gd(#S>{#@zkakiDv-d0@;{!MRs}r!S@j3jZ*~xF#udsi7sH$gv%#2)!U{IjuFWE zfwtlHC8wo&w;y5}dEs?L_!p}^2z-67=Vx%~uTO+p0q8|5o`Yw)kXSvvE0DMJZ3Wm7 zAg*JD-KR^{U5}+B)MKcNR6e)l_}>|ChcCchUd`Ec?JxlO^A9`40@;)vdU}#44?dxY z1&V5!tYDGo^kgpn_qhRJUu<2kJ*>}6<3t&7wEtx_Q!)Zv z>xq9<{pJ2QeZMDHve#+|3VAY^8%dic;J*2PpTd8@*w6a!^9cgIuhW*{XXP=F*kLX% zQovF)|9#Jq!oz|2Q&MWdo;~5poZ+12zgB5z0zEH@`ytdfBSZcmbQrj&V)cqx{CXrQ zcx`QM;TMQ^ech$jQ@T(BlD1QGUKDmD>Hr|6G!L*)v(RWjz@6*j5ftkajKkT=5kQ3R ziIS31-JH5Cxpl(Ah=xU5xtz)C?WJ#EgAPUJig#QVT{M{*~{K-K)C zC$_dF0A+_SHqMXzIgXn?b$DKHEL3tx@$pkWnwXdvQQ^44IpVMb0`7Z`Q^rA3iEgKb zu;m$gE0`~;_AO7``d_+;?CdP~yXt0UX0n+bmIE-CE&srn$jHUOdjtgJ8HqNZH2e3k zR_wo8Tev~L0?o)?>*VHZR@y)p3)CRBF6CWUC#pw|VWD4*P!KNMK7m!g&2?6`_WprK z`<*_Kf^nS}nnfvK=}Hx8Jn`C>fjAd4uS#C&LcA z!=sQ+Pj|OQt}wAcYE=Y!yN>r26)(alz14g=pq-txL0%5trE);qNLs3UNM6CtFPF?# zrI6u$-)V~n41KG@7*r-orB!9i<*+W*e(k78K^6l#z&?5Mc388s95W9{{-NGPVUvd+N^;G4eQkkSy1;ZhS}xX3>rtVxDGYXuR!9RY+EWnl{+|+WYVfsNrWLxVQl{ zEIc&lPqm)&1^AE9s6DTFU-dw_`J_d<`xrgo!(g(#if`%4WwO3G%Mm(Bg=L2*cf8!>gPvrB4&L7HZB>s%1RD%UdzVZ}I@nfmG*-U1IgJe6CY^`|CV)Vq|+* zl1(9!wiWG*U%B~rWv)%qlU|{+{_Qh6byMd|!J&l3Z#KQzr)}|$YZ51#awq!EVq|MpI@@oZN0z0vdUz;EkWEO z%Kf(QI1`_Fld6tKk|p%3h9V>kUHDWp@~T*@M9v50UaI~(E;if8!Y2J+g_rdpbrQUL z@tyJFp)OKr5va^SAl?C2DCs03-~o4oS_HF@N3Y-}5NHoI%LjK)b1i(3N?l-Olz=Gi zd0Z;*U*t+=R023ypT)dylN3yO+lq7oybJIrkdgk{6r%Zt;;QFHv&7vhDw(qx^}}Fi-=h? z18Jj^Bj#gF<>`8gB=<|8a4Z-#7+lO`h`%#c32{M<4%NGQywgSHgC+X|1QqhN&YYD8 zi)%8_uP|pX3T;Z46He-0bw--+?$TRUnpZgpYwUlm#m&&E>g8R9H_OmYa`U%z%c>m9 z25?Hp+w25D7^X)p@%WhCrcvf%V;^3&&&y)a&Da;A8_sH&)9uwl7N;y8cB`7{Ggi6!mt|v+InRH1|XzI$E691wps8?$6>Cpobek~K`;&h zJQT*F<=Jb?h1e3eMQrE?XMiXaiQo)S63*V4`r;vWh4ltnxj%v=PU-UHfosCR#d-1k zSPxPBFkzA$Z)My$B$N8-+DPkIYhsRP7$HI2Q?#l+TB=L!%lw03`wt&J?0!amT6u7o zQe-`72+jj-VN-u;$`4W7u`A!AP8y|PZ@j8ahvD$vB&1AoyG#Sz`*W1k)SW}+8J!<% z5vxSuL1*peT4%NU9dVmxkn*EacTrRVZlJ7julX)y^wJ3Ou5MhJgGb!^#pw*&i$tfx zh$(x_@Y8{F7b+U+Hc})Uc@b}1DjD}Y5m8h=1MLPhkSHp=z}x53UEIccZNZ@3o)Yej z9n<%(PTd=3tJGSUmMM)zpkR{u+ut;DzjEpgthE5SM4iE zN+Rtsy^)O?TPngFz1I9D1BgE~8JZk-Yf9S};V zOx}suxv?U<>hrU$rw*EE@+Zr4G43G5%@#sjLywbO0X{vy>NL46ZJRebSEw%7RI(x9 zOLdD$AVuq0zM1pWH5IAJqtSB6g)tFFw5Yd=tYB$e`|d2-sWl?nfSAdZAa?4Y!F{;h zdwtTV>b|i#tPa!T%#g!MP97{T-1s{{IM`}Id9?l9Nq7?KmE`goTlmb&@~&$Ucs4IKF_t`1Slvue9ytd|9$6sx#=S!TPgA z&=bYuGxgfb7JduW?z_o~?8`oS8OB@))CHorzrB(oDSfy3yKB|N)SJ|dRsfELr?5#9BOMk`Y4chk)~QJ$ZmQ1XmZYq z?@ra6%8H#GIxT=Jb(0xVVdpwF^t775op)-zyA_TsJBcgB`3Bc}x2C&hYv1b}kUJI` z@A^bJ6{R2=2<@?@Ya2q5Kux~xtYnx6DRf-#o29c;27{N+)cq0K?vU`dOfTe&LvU!U z^k%znBVA?|}vZ9_U#>H@vf z068(-3h0?-tKcnM3?5kc_&X?YjK|<(Pz-K-GQ9b4t_EJ5liqHa9Ci(~x8=7!anB%N ztA*~*R=gPU@0R3MO%Nj6?zyP9-v5@Jes#nsgU=m4X}QKICvZ}eJ5q9`s^yd^a5{!_ z^zx(`FM*mmjsdoTE;eSin>(>M1}C1?t(aZ<{*`C7C0Zm>4Kx=oG@%}TBVP@@hxhCb z{}7C&bUBYoP@$`evLl}H-l~YtxZvxcT;LI^ zdS8k!dbKzJM^ptWcWCR5kRnrCiQeYf{|Z(FP^^UDxjt5A@VeM|fnHcbQN4+3v=Lg~ zHlq}$;_j&BJ9K5bnnkoyu2m>;Z`T5w@ae_2}B*caqC zUw!sXI_(>r;&B=Bh|QDBMC1`x_PelY3duP}>V4}d_+Kzyl;mlYbH8qZ@2=_lvct+1 z4aAB;Zfd^`O!2V6Jq!vMoM%8Uua{Z$%73Gv#+-Ll`>No4rxnZP1*fS}*sKEtb4YxB zs4!QjPYeo;pjQp0qgnt9!2(N~D@!!1frVvXoekjIt)lEinYEXcd}BGj?Je~b1(j#i zMJtB6uDPF^)J>*0D|Dv;osWPFk7T?;o%@G2(DEyF$=13sDnB6cwVaAD~3?${#9KmRBYpDuz< zxvNk|fnKBBLM=IOZN$7lQN^{?=|`Wp%@&tpHHtO+1LH6?z@7e*1(YY`4n{@2# zTly6XW&G1+RaRSH_&1cu-6PcK@dK<5l%uL+g!kQ!>Z7GL#Dmg4$8gOD49bNl$_kOS zLgV6F7)-Tjig|GkqL<%^@F3#=now^BkD`2d$vau}lyU45;F|_sAvEniPsEMv2Gq3? zCI_yafWP?T{v#=@;I0#17n$p{1MHtSzdKbj9nK+B-LFY)tL_g#T}n73IoSu$2lo%w zMkCm-_B=M73vfRLJkzG6q*Nv*79LMO>CM)XodlY{FR6^?s0pSzRBat1KkiF7MWCrb z#4IQ<+R`q6belc?dA14~nEyDzd8tyN5kV3~^9%9)ih_p~Ak?&lPfi8~Z^iGGEU^O4 z1zI_Q&^1Ru)!?MS&c>H7p{SZPOvCBj z8uM|M9@_+lb1mIm7Z(drTFa^=s}XhOcS0fVSA)|ZWznn$K4_)dZ>S%NSpk?NgQhQq zoAwa+1jDbiljU3CB_$=n@XW?ket`KoG2PtK(k4iLu{Gup*m!i`m6?s(SiaZfp>qy? z0VX!~#>ffNYnFUTg$~wM!i7=uW3waVOcvm#NR7)B2EW}x+YZ>~w(>N7fxCl=Jn zSH$U;TY@WgGQCr=ZS|Mjo!xGEVfl5J+V02Jb=Tm|Yo0l&ecR+(2BxN`FT`OsZz#3F zUkHke-U59^4PQw1A@fFT3;r5bA?P;=A$kx0yGRg-?YcZcG&q2mU0KvG)wfv<_#_Hs zTNbru;bmbTxn$@^Uu*cQfF|9IKm2T7U?fLt3$KL5rU@#(sUjyU+s1)1C_dIbbqzDw>rL%%@7!(&esR%y7iqze_A&d{(=+iAaX3*#}_<>~NZR5m7JP>x8^hqzu}JC>bI* zr1bw`fum5>o0q`9p)1W5=%2L~RZyJhO<0ma&J{)7s@=$B`vK!MBbpDtT4Pex9vsc= z*>PIxc}uufeX?$Lvg;w4YeR>R@dwc`Z+f~0V9}K>$Hwh#ZB}crc-qbESoO}0KXjlVJeHA(NNL=3xa|}_*C&EKogP%bqRS!PmdtMvk)2mF zWWuyIYT0#gG0R2wO|0TPk@nk4KNBr}S~(S@ebu+UobRlD4xJ6R^+b@;{)-{`;i@Z8G> zeD*OV1})L$QaR2?gn2&6dICUD+BF~5xT|ef#}(F>&sHv7wkAxF0rtQhLV>T^ZHMNc zMbTqxp#kj7g+WG%F2mEB`PxK4A??`e%f!lOI^H<8rpSz^>OHX+xdMAr^cHcS7=YBc z)_6Jlmmu8J(-j;-MM&c2<|7E|QoNgQHF1tlBx7;0OxO80dbPtN zVR!L0R=|tbm!Fra!e{rI`u3?2VzF@_$dF=((X!?w(3Wr0_H21z1L#M+ZwcwPKk?kL z^)r0+MV@R%4Q-0onTPm~n$Gl~OvF)SI&tH~{o ziNlFJvnc(vm(3{d7jZE{b!iY!y@9NS{^x_z;59ji~2TK>yP zA3;Cb2DoQ0V3~osW;E!5M3k{7569BXCr1E;nCz4OwJMEVOF&gII1#2_FL?mK2g9a{ zwBXJhVO!TG&(!<7i1)hSWf^t4PABTFTn;PR^43a7<%G}t+NDEY7c1@)@JR1N0_vpp zT>&AGc=OHlS3@%1oL&uj8@u~XT-Cf&bsTm0}n{R+!#+CWFrLn(x!YkZm=Y89?e4#vN z5a|xSWA>zU@h#&K&<8^ZUz!gBqX6%To`Z`lD&R>__MPVJ6SS{=0lw}_v6t)cs{d2- zrnL#K7haObR03|JL(UBM!ESLM1CleDO9-;_HsclVoYDigE0%Iopdlw0jYyCxI}MK- z8pk#?le%^CHLitzG0=xRVSY151Svzi*XgnsJdq5aOR!guWMT?S=BL;rxCC_GZnFO5 zaLG>zIC@?5w3!Rm%+en)#RDy4-Z&j?sQ$|{l$9(5ao#()PB3!l0{WD=^x%^wKVStQ z#?lD;ojuM_E`}6%G`9O!eQxd#SX<;ApI=@$qzS?%JpXp-vQ;EXsh$FZ8|$ODop98) z9io5kh09cV?D~Lh`7oH!$>j0^D-_#M9?p+88H5THOTrG>{Jo_f|F576WssjA2cG{k zoo%m~_NzYfFs)g3S>fi?p3QH0Yhs=H>W_muYaOE3POsYo2?K6YrYgx|B%n(PPUWZ8 z=1+qHKr!%fbLS{`g)NpVkHa3=dcQ3Hxp$$Pp-d~Ao8g=C_^CLUa1uE3>M$n3i{kjH z;^CW*st6>WKQ%etysAqWcd~@IoN>(*Ri6h5E%r=B^Mhk5+4+~I-b|ESzVM|lm!XOD#%3&QlC#1cp4P^q(jN?MAojq}y7@2pjp~&_(x}U~lKJ z=uf;*21nQHgRB|0cz1+6$B!C4&b5nPb*^VH-e>Tfjg8pT+{|8SMN4(a&x=heg>kHp zX4#a=Jk^6=TNKHlSD_(CU6i>;GoVFVqu=zNX`7DaDC&tl88>XLBHlec5mxv0pi_bR z7tMeH5E=0VTdHFHb7>CuV1=yjomDe!;qAQbSH13D1*AZ>xUf>*qS30^9p5`DAO~zs zadE_>ere+YaO3>*c>nADhdv&7Ycr~z^m98>C zE3hmyB-p``&r(6~i5Qy@51?0cMhFF6fTRfg43c(@Bdz>;b=aiCW(QF0U;+3olu!BT ztAOA!4reP>bSGV)Q2|lqo1?tc$03^E=z}n3uF+83~IN<~M(!a#2zN z*UudL2b`uu&ym~?WLgX?r1I*7&WPSr5T_%FRNiNQ#Nl+l6~;2WRd0*iG4X;`A0a(! zkk7a?hWd7fkJjq|BL2uj;@O9jpS!n7K}jB=JPKkB%q+0>Ti_&#D_BKgQadPFvQ^4C zOy;-JA|4CJL8P@%8U@(uKCBr5;s9z6^=&G>G8tG3k^l9li?KaptEG>w>3bih>m~X} zGIFsyw;Uv3DKHq|SOVXcs0Qe+@DPywZmvIkj}!)H3^ZJli(8XzRnkM4ap}EMJImA1 zy^9=NUoCxW4zUIE@6p>^92k72w>T>pQ*!GsSdD8iylN`xv5=VIbW1#Uyv1NCpz$Jw zpWy9Uwv(uMm@zza9}zr?gZa|&>3_@?V-rc@u7gz5?E$!C*YhJV_3r-48?1j#%>$WK z08Wtc*#86kj5RFK0VX&BXmj&E1p9!Q$0}Loe~r6l?Rx5g`L}4u$ff*J@7z!90CKCo z?u6|2J@$lyeMTzw7O6v*ELP&%27;*W#go(Iy>k|sg z)?_p|YEf{&UBCS!t-(m16?5bbV+y?8(MF^2sVyu+ZpEzup4@^8Yx$W4FU#(kN<}CH(P~69rwEdK1CHqxm}T zl5Wq30PMn1n)GGUd#r<6nu$iS)W<;Kl~%9+`Q+;hpp38_n%lVJ@?%Wl;jH1$9M83D zTxpqgYC@y(wcE2*^GnHYH$Hj$HLQgxL<9qg^bXvedsbWIuchZ{LMWaZ+&vQ&>B#y! zZ_*|eL5svo_VuAksY!)pXNadg4Eg$r*M5G@^<|{4*uXv>3xNgre#1z9I9%VE4bt#6sb$Hb^Z%0p&c*=){Cae<&>!+Q z82*2Rg2)#tkwzbRH|H_le=QUjAts79~$0`1|0Q^%(dKv+fgFc{+e0bB|eBY#BK5WARlXHZj zi=+5QcLe}@CNS6Z{O{2G_iF&+Z-i$Sc@_5ko4@lR5i@z#%P9VZ-#^&0$G{Q-ivj=T zb?863i~X7n1Yke=2OAA=9T2b>HMb&ULjOMf0(U*~^hHgyeo6Ze=$90R8Q`y8c*#Xi z{?T2%NC5L>mt~Or2YiD93V*#Auu5D{{?T0zuIZ`eL)t&!HlA=bBEVv3dv^S@gCal< z&{Ho@A*0Fnk|Oh0!q^f3QRi!SZWu8yT<$IH&JPnfU7nT# zshV|#67NZOwE@{I_#E!T(TqzdkEuaKdadiR(Aw`r3=$teNpJ~d8ozKXQkbw?cW{}6 z-Ra5`Ygx)`>5=an3MjT-tw+#!f26iqDSRCIMS(&l$CyLcQI!dnnEGbwfb#-QEiBAO z3J^<2yi2nI#fB z5wQLFfP$dpRtw;zj>h^hs2K}kDV*FLBVxgjCDRx_gpYV%`!g3({^aC8vJsI24Bdi$ z-G;VDzl?L{73_A2$Y=Pg{97!r^uN~vUtB9rPrXfk9uEu_66y6`t!-n#o0*YIKnc>}vBGAfZwVkyIUhbG zBuR0&i`F$jW8Y8SkDTm)RIL2#l>SX9NE&b@t?)}pag8IOw@EYqkF2i@iUaDh4DJ>J z!5f0Ry9NmE?i$?P-4bZrt%2a~?(P!YH9&Buaklf-%zl2 zI=$~?K*9l#hOR3?v)XXc9RbsV~+KJl0_GNIdB;k}(t)ou9S8e2Xl= zm@)4bArHTFYx3gIfNsv|Y^Y)*{s3*1$~WW#Rnq&5;_@7;#qsJFgo(v-XB+*+(EWsg zR;7T2Ou*+}P9lb=c&XleoT1TLgZn0pH0V0!>>BqImdq5t*%i3WZU`xg4) zyP}7&rEPtWz;N$U0PzO2{vZMsH{c+@>ed=Vbi zA(RAf^ZapVvr}>#a=ABc1hSe@-8u9SSEa+_pJxE!2$fjs?ZzSA3AA$vU+p8%V1{oHxw*)Hbk6e5t z!JRJ`-PE&nZu~2qHq{#jvdMJD1WY|G!z~ypMRE%LaQrHINDi<}bYfxQXc?oEy3MEP zm6>d|D3D*hgP7OcPZN&j-ix1=y1$-zY&!M|8@N+P(f?1UVUHw^tFY^VLQ}womLFC; z4H^%47v%IHWLA*-Nx&JI(TnHHq*i~x#K`TinbNi8n#{}>U~)d5!7}DMS03g2_|3;A zC4I9Voa?JqUuv+`>{9t%Draay?3c)II_I5T9IN%36gfQh0jBA;UBlL5#T=RIhDX6PgNdt?wc_Tn;qCuMgSd zbust=&UZEcXTQV-`xUKljI)z8Mr?l&?Up|{Klh@&x$-*EuvuAmrNgXPjloa`cj9qH zQHX2%sYI>vClQaQ_+gGf$F~G3dD|35wT_G|{s3hal+Eap zCOhDGL_<1(B7VG1V(5$?Okq={B7=0V6ZvV1dK`B;4*W};weIfvcmD7bfq>IB(7@q$ zMIMmoK3jX}oM59?g6+GM%>miYR$~NPj_WB|HD zw!;dhUM>uSaI{xUax<T(B+dQ{-^H*#L* z@5!^2QGcB`y#1-!Ef|x;$Likx_M%x=L>@Q10pA(pn7f}04vCjL6=nO!{Eq>AzH(!l_9e{@TMcq`W|M!4ClbtT3hW}zy`K$J(PbJSJ9@UajU2crKbk{k zy%Y&F>#>2_E>o(UjpZ#V<1faCN}o_i%4a;e9+cfeLNhjV4r$iXYK7&9 z#vjwHelIL9l!+HmqgjE3g3?8OW?t|sQ!U0t`<#_EKb75{E`jnBn>q!;D?>c5Zm?3} zr=66i!0bZW_K97vBvUN{jww+$V{C2h{I?eX8(x6oFUeSvE{r!uVtq?rP$%W5Jojb+ z$-Mjd8qO zt%}C2>Ga$5cLVuydh2jJ}v$68D#_`I*Da(3IP8A$k|xhs8GItsk79h=?oL6^yN-}pY>v~evr zIq?kMdWRiGE@V!cLLypiSPRNb4%G9p&v432rnk_@?l#EY`po>&mJr_Cd;31=u@)ZB zYcfy4>w6noYu)^E8|BdO8=4E3A#RNcgT4hl?}JCu5SsOoJOl_${+VdIcpYPw`x5Tl zF%9mYcl+2oG2{l@nlA+Hzf#}bx{(ohrSjg}^vo2{rC0PjxDnVq3tG<^Vuh4I9YfWr zC+FvT{ZhSGa$5DSm>#JwEdz;f(ImeO2}1*&_KJw%z*nyb7>)50n|=|0qRwA$1#=j* zRf;!)SreVIJ>GV8{oZ-#f3U(2YqtB-e@**Rj(1mU*Dbu)+DI}-u?-BYKa8q(UYCG2 z{@LSlCnSYL1XYJZ#BIaqS^xD1iKeiPcIc&(`qYE&hz{r|5Ua)eECXV?1YtTn^geE7 zL)rY+Xj{_UDAa46RcTd$J6b%e@8Q7Ob?X@XLW59ee#Uq6LMo5+3VR8@NvT|OliVxq ze&lv|k{^n}XL@}G$NN5>c0Y!`R)nCt zgtx>saKf;ndp8q`)LU0*0+JUGa6SEyJ`*t&HfbkV-Ka+dNg6u*cOUz{71RzH=}+vT z1$dOrW64bcUbnfl(NlR=^Lx=9L8ohmplggOIpV=N=aN)C+Cz!hOgdpy0CVv)#JBbJ z70mc(Hf8eIAnVYHJ`I2Q$vAl;oo$54%qXz!LD2JZWFow-YdqEO&v|D+16#MoB%L|Q zN63>JFG^V^ogHph-~sTN#-dgLEy#!`(Q6cZz;zG4X}4*ftm)MjLJs)dT6vEdC!{WUaA}hw?&U@Rvq2hEIA;WpAq^R z8T~FVenqJE^>WFOfM)p;$o9zqdgdL{AB-M15*8G)y#=~)n=drmy~eL#;297p8{oO0 zu2KV<|1u0KW;L<it4siW?}ehCP{b&l7^$9#mpN%R>^@m2 zFT3V`o2L-6n82ipC7o0FgTrc3`od+sBq)K>WqW-U{?95qKTeOhf6hb3()*JxpU3M^ zhe2+`o9ZBWg?e?efU<<_8%Q9!g zbD{UyLGa2m%Vn)hF*;*`_X4uFYByBB*=gvJ^VO_+XN=Hvdb7BfYz;o;pQ&_t8C+&t zjbTnSX3V%&l$0^U>{bp?g5r@;14%EtU_z4KLL|m& z_lgT!t~;O#!_`qS@RzyFp7itq9YknE6>e!%P@1qTLfevLL6_ozsjl18R4Z_xY-Q|v z2Ief`oomfp5uyANBL225v(`wQvGn~kM19!0@1qp#7IG=Hszb6*u1BJphs%T?FTVt_ zTTGW?mNj+jjwLfz3W|F>dDv#aiV6nhOZs*1X;i=E@j}thdt?#+U%)Ep1Llt(io=VB zACBuRF_G{9=Xo!W7o+SO1VG$hCHU-{Np#6$#|Jx|A0jOsq*0>UUmTv$lP7p(Wk#JF zUr(nXH)XllLz7mAr<+TUMyD+N`-FyG-9BwTD#jCX(zesyPzvump~DmlmplA7{-hgB zPyLa&#uAXeUWKdtBdIRy*%+}gVmSISBdsb0d)d+cJ+Y5GBvvN5DRM_1%9yPpj}XYF z#39;?>a-sZ75<^#0=N*V-_m^icqcNdpBpUH6g*gd{B|&!tq+g!uxhzD{gJ)cTmioj zXHkNX1#u)vf6#Bj&>(^!Fg3VBn{DhgeUGB-spp7><>TMwuCPs1G0ae&z+jG$Cr%qP zcB#ORt_Sn+t9G5rfHio!X~gXaM;yxWh2M9%YJ+ctzVix%l}1f|)g<@u*b(S}r9(8k zARM415!~UQ6HvCiBH86cVESiXm+$eEC`B@zd<#V7o*g7{Hq(0&#K>G$YP!}M)dkH= zdL1gW7EHgYSJd#4rCMds8WMa5F#L$EAN8X@(f(q{;MO)&bbO7q0URP2e=3@8@UksY z%WGg;t;PSSrMp}vppI9kkH4!0SARmK_@InT3-bvN_wGbk@A`9T#WZnWvFrI$rH~}P zuoN@m;WiDT{_nDHEmMC9Y*9Dp7UOKO^e)fb0q<|m zUpO#3@GB5V@;X54{KOjUw1#A!5QqWQzdh)Q@CEPx8BZN0wjsXt2M2v&FAASn+0#jb zJVJZIqEaWx83%m&zW2iZH%cM$@CEbtlr*TyNx74SMb;iU;pX~0xyS+^bH<~KG17Qg(M7#xgvTO{ z56|)3(&hDX`4O5KrEsCM#rfzxi=dOoh7dga)QHmHfu`3Vu8b<`w7r_mhLuP3<*9VF zR7{o_;nN|`tK+Bn9Pl`-)mBp}Z`5Fm`}R?OX~tx%OAeWs&TyIc>u~Ru%$7r2hJ^5t zTS(WxSuBMqi%MbywHVFQD&Oh7wM{sBV|UX)z#;NpFYxMv^YfIT-`U=#)ka2k;V zEzo2h<#=}P%~+VlV7b*SEK8_Ke+!2CZJnWbUNER@hosjN{U=`U#pCcjl{HbwFv^}l zPY)6qHR(#d*`gQr5UP{+tI;~B>i8ELo+I9_tpN9R3k9SoUrvQwjZ+QHs$2aRX63mC z`I+P1MR)SfB}%mi9BA`g*b}qh71kr*T{$3;7X^%4pwLzd^l0mTdy;*v#1z0rotesB z^H@J+bv5sm0xwSL9`M^+{-van32hQ;-3zu^y42XN$_nuEbm-^&^Za&Ti1zF|-|lzP zw7rR1(sA|354igxd4IQ#H{-6C-0gE%wXV6vKr@B3tvj>D?O>hnbx0|?rJ-lhvKjmZ zFW^!D86D}|;>VST@Dna&AXwZ{7y#2x&0wG!#H(Q8Mk3&gR{%!J@(~CL=7Yl81F<`d zOg)|25^f@}GI>6CvXs2KE_!IL1>a=D93CB1>VD;0@^rsh`EzXR#Q$&GD@rPQ?mNg} z7`-);!C8J=ORbneD#!kCQY3Gj$@29t@G4Ar^Ri!dtzYszjK`&AWq3lDCQB0idFtel zVA$&-2SMftXZ*-EARlIG%sAZ7nezre7=O#nMsvX`sk1-Ue}H)Ew~3?)l;&n_4`++4Y}#(quR>?q#3@dD`!x=VAif z-rAg0I|nvXP>1XJR zT327XLjV-0I(^*Js^2KOLuo@63_O8{XJ~0gB`0Xc>5MxXeLb>mM$8NJIgEKSWeU6Q z3clpnRGL9(3YdBV+9A5s+73Fb!XTk)ts@OFWbKW_e<^3Batpi=^lk7f9ol-h52>rsv}#Qi#R7kJSRkHxfswd_rA8L8o6 z*Nx&;m~iQ}J9(qmY=FJe{hqryIEo!{%byYO%wPVdka0IobZ58iaR&~ShYG!VdM%JH zG_SOtt+2wD&gM%FnDk8QwmBq8XTAAscG;;*@<argP4R<4ZV-9$J1}iB& z`Rx9oeQZ$G+*rb86i!KD%osb@_c6Pw9{)bQ>F4}-jnnzgQ938pc&z^CW{MbYhqvN- zlsadO_s-z$WzeP7`z~XukKb{YLVD7~@98$dd0*zl&Ei?F&NZw;`!(})vtE&QfKO+FBAPUv1p8Kf$Ay5 zC`Q8fu!70}BHTd?zp0_g`yHZI! z@dMFk&mL0=hKDk~)DpLAO=oe2{^=GTekN?+o^Fo{mHWMCm0p9dx%HcweMWZ&W$%n3 zOg}yRPZn1fae4=P7cJ6>#iRGc{QI|7`;$tn;)d-0amsavBXkhRG*zWAlD|^eVN*0+ zz$<);koOv4G?6-$L90cJ%YONb&;41d&+!F*Ga%zdJUO0m0q@tGF)TdjY-Tsof^ zI=^Rt6@9Wr>nhT9jMUc zfuGpr9#V$n$I^*IGE{e+P<7|vyI>m(HqRN4S+!{8DcG@G9D0rMQ{J2XhpWUQR=60( zX5`Ykq^<};*jrDWRAp0yfv+#-RcBRkn2WudeypGBKvht_yvRb?K7HPirwbX35 zy>NBMs>8Aqu zkENGQWzZzEnjVAv=kFeSU6>^AZLKF5zf5NM{b^{czY@ru#w_hUhi^| z6eh0;e*5;5=$k_<7I{X6fgPdjEqqQu@U^e&y>D&P>jpT)?CJLXNS=_pN_kHV-li!X zeS$O0Z>e-nYqP_j96}jRt?oXzZ?cdl;&T;mb9azlq&G zHE;P-?vJOk-sn+6KMA-Doy?cAvss+`uGCv}6QoZ6y>M^6^iLGdAwbZT=@UoNKQnL` zZs{@^q)RW|OjIaqLN($Esqr;Latnw$PApzG9CXEy!C z&{Y}xWwwATl3#zbJHSvFmx+e|9W`=CFoD1^SwE1!ceJQ`Wq5wTN9S9;n z@ejG4`h8RGV79dh)7C1Vxp+(o@-iJ#NK&O%Jh4Eb!t=ZQ3U9ShmOfu?IJ^b^tVcg* zF`;6-5p(2(ct|oW7>ZJ^Rh!kIbn!LsZtZ6>{Tu}4+9bmy=~5q$j z8o@1xlXa>m!8V|}e0h}ZMDWx_l(za^5yYjZm6vp!#uzPZ*-7hZM6K}W4Fm3UYtC6h zTa&%#l^>U8^yXk{$B>mBz#X?>355>flwtR9>9igbix6yM4MtIQqa8i%X zl-Vg)-%UlT1Ql0Z)Zrr?UxMjaP!UJmc5{qFeglATL7ncG5wb?rgr@JkjkkZ^T$`9Z zxq{dL!VZzeug|}Hgzuo90}mqO*my2t{z2(0HCFALdR?|i!?waFmm(pCMsOr_G!&Sh zpgqAqNd#4tGK};gO?CjHxaX^i$tFLgGRTDLh|mk4v*{(1w7etc(?U+hg#QxKLyuZ^2+!!xek839%M#aX$j%79kOwR@KF47L}GX(9f#X+b- znRa+aP0Vn^fFq^^+nElDAzk7QD@0@E+DS@-i3fWXodfGQT zUdH|5lTS;PCx_MnT$I&~sHl>@;Jr0N8+`ItDcYpyy4a-P(YU}mmSaYp261n{jp1q3 zZxeq*f9;Q-8;*B8Mty&p|H)Jh_Ya_5uvu%Zw-+NIfvo`17<4uGrLvA0cXxK3)BjD) z-(C%aE_)9oW3zi=C~V0r5oI%XXTbe+LamscQf25%2|;!m)|j6n?H(AFWmceGpLx`e zx1J9HH@-rC*J`vI#p69+g_j${Z2m&@-?N3X7~0@9?{prg23g86t-=m`uJs~IPJ*Cc zC%c8RY_5M1wcA_^P55!|yhck$$}i{r!;{bTN>oCiC^>89?aT&4Nzlv$dH>vAWjo(VeAo2o<~+`fGYM zd`juP2lLPR$}nAr_Wb>HJ_)`D&vrn@Kc@1pm8Ihi1a z2_F7K=rrSyolsFg6fR?OsVX%Md1!?MrwdXnVo9vivNFUAgYKbHyIleO)l1y}#W)U- zk2`!t6dnxa7tV9OmnHc#ln;MRC z!fng3QlVG7Sh&;o4^QOvtq%PfMg4L4F#R{zlwxA6?&^kOT3SRcw6IHAu-F3V-yq0pc9)h(G2(V3x zCl8lND7fFus?E9R0#I~UzKYRlmXdA-fGZa(wVwMp{tdpN-=O2&N)U5Ey3u%jyS<^w zLVNibLZl`?waep5lxfLl2nnaqGeX#rcoBkH4uY3!>jdA*BcE1n4fN^ zI=He_aUYu<*32V6FVf-Q4Jm~<$*ftf5~Q(2w4!jbc3%HJlt#)^PazsBS_ z>jUmPDA}w}KW)UnJUXZ6A$P2?H<92XK6nIlota)X1gMuMB|;#wBcEKaOs3hLMDqk@ z2L)n{{oW8s?-!DnemuKvm=I`1)X$suwJz@zfgXSkn9>Ug>mvc+Ct3)N2sT zw%B%~O)MaEFakU+bW${Q^~1X9JVHU|IsjYfS`-RC2pVk@XDpeP(JEQ9ZhY){U9^xz z$mc$*hg@vo`0o2cSNM!KJ9?uTH6dY8kg z@fm>sY&hYNvin;{zVp#@?0TD3nxnX)j-1ELY@yIlU=6;(YTQP7`<6?1VV$ypAqF=+c|cNsbl?j4rd@T z#%I;l2CLGgkei&In!sTwJSvgfMkUgmBsy(T{PQm6_M|Ufv0*_Ul zq|5q*?YFvQn@WA4{M!6q+vZgb=0H1f}@uFW1h zK^Z$+uhq@q=yhva&e~Qja+OZ!vMZ`;_W>IelThd4al#^Z+Q}&Y{X6;L5t4Q=H<)|N ztoy+o9He%yM3*WlaM{oHxxS-Mb8o9Q zSdz6Cpzb%@uT|y1u!IL0qkv#w5N=(XGBMZS2N_X;sJ)!JU3&PViQK8~rLp)kO6dK$ zDBz=tclqSLlxLDV78e3|XG~xwr7Vsr*%udCj={^mM-=ZA-g7sgYKy@zkfdmw@0q%0 z8q>l~yBUWjZMuUx1v2|4Z;o87in zzBh{=^I}W-E%6oug)L54abE4JP$^RxK!=jQfzRds{Y6iLh<3ZnJ68oI*IBOe__Fp8 ze0d)nGG6y7a4H~p!WR@n?=2h zrL64wwp^8-@Y7sAtzQrcM-vt2q6&rorJfpUh^5*KPaoImBiD^+~=>2>7|pe?|6S0%Wfl&_6V} znu|wxRTb&ft}=M-Zq@?fsEa@w#|L`X2YuYYv{_vqD&$7o784X&?S@z*aRa1Ze}9~1 z`!2#vtK8Id3*bt}zt)4?T3Z1zDm=`b#gg%no{%=-< zyxzA3wku7#RPx!C0S{?7(ycAS2n1quG>Ry5RM9LNtrSrEQw#3zy$_TekcO{Zt1GF& z=B8FIT}YG5ZZj`{hs4uBqy*ZmX?p|VLd0Q{R873(jEWz! z$xG>ZK1`Lq=Fy~(NM@2bvUafo6nabkbau@b;N_FAI&xvGKE7@C>(XR*M_Hro20opqD0ve|pj;w1eINB5EfosZ-N)XK z>GFG?(#eB0BiBm}xYtIg|H1u)LaDjRVFhapQ$d2$lLv{fq*D{uudL85_|y)G31rcy zCp7-Z61B>rC-u(<%VTT#w7MJ?6*)I9tx`yw(EdU{`ObkKRhBfzZ`Hv2{?r_|TKQG% zvB*R5@$s;f&GU!+5&WPtXX8ftmyrs*AL1g~BBQV#dzduN)N*)?>U5eMVAMgLq|v)1 z8@~y3!J_qNMG%`jM3iWe;*=W5Z@VY3z0uF2N25mrS-aK>CEbMohTd$|q=UOh06a_q zCDULV7K-F0|HVF@8-hWdX1yKS{+~X^*!h_Hn;|LfdPf+v@Mt0!a9Zj>1+57H0n>iNksR>7&pQphJH(^$Y!(ggOi!h66pt%!n2VB z808BKLo`Y$F~s0{{NoQ}_CWOqc&L6Di#)bm(g+dSuoIY*p(}#tUgzm^L2n#*;wb?( zt#R*+D$VMY>o_MFLdG7?Uc74JlfAZ~Q$0k~uc$%S_3bKpqP_67;bp92zE!9V=tMje zXoQ>#V=AFarT4}-l~SBzp?^Le&Ruc@y`mE=Pb=~ugnFd$xfR{VK=)^}no^Hs^>xVz z)0pi@!z8foA<(G}_zJWC(rvV6QZHYOmrZ3JZ*vRyYwEFI%LOTG8&KTuJ%!y^;ZUZe z<|ks1oZfRa>C@=L{LFLSN#q!tvIdo&m>d@AW(-OnJ2OXf9M6S7C)k0O3nP*5olWr` zhF&N^ngobR?;shG9E(MFW6Ow32%Tc`chy^^7h?uj{IRt__*XR1qisHMo)6_f0?thi zoxrPQ=>4P7<8L@%@*(R`!r5O6B^lH}?n|=xO$HWqO`ye0Jr%z8iN)roq^=4Ij3l zfm!H6lRUjuE>Lva3uXv~CAYCFvFBlmZW<)mT*dYu4Uln)h`3#IZt~xIDpce9AAMTG zSI(DB6nh9qg{sdf*VDpav)(Vd0=>-(pFN%jQ7j>=gS+Wt(HZ^hxDkH8gRFDaql9nS z=jY2;b9}-yJ1ALPFX(om{Lhpq#iKs}Pe`t{2>2@+KbT%06?<7sQ@S- zO{DRzxhk)fnX&Wd!<~>pm_kFhbsv_xZg3gu%zctbxEJr^al<0ek1mESq1N(l2jslS z&99m34>OUu|M=v0KUfM_Ou0h7dy0|(kz=W*M;@l-!Pf4>zZssoj3%^x<2WZ7j8+#9$FK4%GD7vAXCv&hCq-7lBF7_PORV5C;+bKMuRAtl6cT<4)_{zLk-WXRlCjLE zK-`Lb$EsHpDObf(O+~>I3kHwe>DTAz%_f7bK<7a{7xs; zu2SbFa|#Aw&$}l)I+H8Ym}#34UgEDk8Wh1}$i8r&d?Aawtls$~qz@7&v5?j5|HP3LKlPGRb z?9~09y{@C4>SHpP_%Z?yBvbLc{;MN!n{OgcsI#XAxo&0D4-=@QdZ5s4OG*uDS| z0((jr9-l32vm=-;n& ze3&!**Co{A6=EO&Wau35!3N?wRT~|h3XWAlYyP9kk^(W6=3ZF0A74&~yI7nNjT5pEv4=8c4)@A@!9|3ALM``Z>>;cwOK{mM6!A;$Im z_5@MulrAzz%n)0`R~?f@x3Q!uF#gOC0{ZF6y+i&R%u|~DTkRCr-17P*?nfKnDt?-9 zh&9f69l~e=B|FZBqqH53s-6bocX;#SK0j{QNNdTZwMFwi8neOF4PkEXN}c*exrp!3 zJ4D+*KY$b3f07)rF9WmkdMw#4*hdFC6Fj%egKNtg@DDl|}*z3`W`D}}bu^smCcb5?y1Ode0y)AFZ zg;QF_rPmR^7;AB_eC7m(Y-e<5AxFc0mBQ|q>ZL((K*OYQH%7(!7;K?aYtq!kzh;;x z$|XkghwM+V`l7?KrMIxvdP$dVwZ`Q9tK~>WV>h96ryOV1G?HX~fLf@VoA|nWz zkt6-(y~RF(t0w#i#ap0&+oB4&YtRa$+I0oTv10{L)guHHmTw{5GYY&>lTM#`8kB2e2jZNz}FOet{ZP*_Xk&olf&Qf*kIq zOnzyQKx?|6;^ZzmI<2j;0c@jSD5ppXibn#6^v9po9r&WTxe;}bc1Y%>{c&&!lr~f@ zLoMZR-zPIxCisxW7??+TVVYJ7EeXirUa)QOJ=qW^KPr2HS^k6(YR6tjZr?o zg-4H7;X(W{L|0Rtf2%MSEkyYCH3YqH|DH#p3<>V>?oRPcs*}g7m#Bz=1Ov<|UKzHA z*avE{HMlnYLHy@yZ6tb2YDcq_uJuayo2`Ds>u{(XsQtg3#~kxKYk#e7A9P*QoLVB* z3=cczS;qH~;eO$bKn{QltD~=t$zQ78s-bU^^}1xGkc>H%m_1@!dA>jy!baR2t}x+@ z5%Da!=pv-BNIEo9gad_=vT*dLohwvKADW`S{u7r&j$ObR;p3+F;RuMlycQ)@)>Dve z;0XlPUnUA?D^c6xZnI=hF|Jv`CYX!wCZN45p!}bzEr6xuU|6H~BRBSE+ie_AV*$~} zq*jdorl$neh<><`X!7`7Gi!RE2rJ4S)XlaKZz1U}+wkLECTXOpThO2*l62ZYJl;pW zEc~FV-ofE#Po-|xSfE@woA-RwL^}IeRd$os86>d`t6XJEABKB@;k#G`z&Y9u#L&55 z=)rFPyZWy+yqTkHgXKAnJ=BWfkR0HloI%2e$0J;H_k5#00iw4EJf&J5+w3^vw;?vh zEmN!2EaE#KxeN_F^O!$%au}&x>+*x9ey6Zo3 zd>-G2639MEmqf^u0Rtd7yTb#FBYHdIZ&e9x#h##Wr@CY@lDa=VPqw2$pp?BoUHN{o z`6|I#&CuJ6sW@eIFwqt1bD{;4x`lU$`31)Qgf$8m+5sJ6zBzm3Y$ls2+fuv*ah!BL zz5KZu9^n2+qa>S5b6lMlqdnRWtJm6Z_DIfY`g!LIB#F>O(j%y=5cc0q;`$!w^VS!JVx14i&`irrdpQs{ zJp2I#q>9R{Xf_tAmxhSInmOtWY(No#op9Cy!{!A85sgluFgXo9u zPLFEqi2einB0xW>YQTEyAYvRQ4F50D@;{3AWz0v<$Ct3IEoUiE&Z8#Q-%|6Fj)X&I z7WT_%HlrV9>*SJ2Qr+E2X`1LVWxFeXI`O8G6)$MIJf3PQH(?<7)*coLO*d+PSUdRK z$F{}s{SBu6mBUIU^C*x)w61&6-#EOO3=&j-X2(2ND1V~-S!s$zuLV3E(rn)1IL)RD zAZ{k0dhj4!JQ?Y(gBpF8ob==v5Wc{nL4Z@1F?$HY#D0I-OLv~L6y`}i@i%1FZ@*6( zj%9uG(NvpJ-6C#jp=ODi$Nq`;yWSbpuwOQz4=7}RO5#g?H&s}5?J_&xxVfVVy3c#a z;`az*(_6MVN0<15K_U;r29b1BZlBbpUF8PeqPkhqxIIC z*`~ANU`*0Y+!L4n4D_kjuFAvwJG|hVjNk;p&g-(En|g?q?3`oorFpQ@M+r+pPlLdn zz5_Hdz)@Hqk+?Xwr&TKSHbVnNoKLeAR_j;_-T{A&^Fh;``H+QuH?@>_-AV z-__DiF10jXm!?3tKgSC;PtBfJDo3xA9;<|-7CCNl4BEcYO)OMKr)&dj(}z9xbANNF zWgR+Pdc?HHlHMYo>$-AyySjTu%zp2#&=pKh*V#T=+x>uk^Hl72xGiyl?r)`vCj2+C z{`Fc&Oq^tc9G0D6k?#V4s~@3ra2M~Rm`rI`r2i`4|NfAQBXtC0_00``+*v^J3dz~f zoJMrkXtjAWz2+NDBa0Y_#FCsm0Dg&2`UO7-680)F#}I-@BHoh;pP8gLhaV{vNBhd& zA7p2!l#a!f&f~U9ygzcLhtosYf?>sV_}0CYwcl#s(U#dR@!WH?mA*n_wFP$b12e5;PVh@Xu;^;!DFw|Nb#4dmN5dRm~yxINLFT(uoEXX;FdJ@y9fIxQH! zbz}e?u8^JfWwt@&f4A??_zU%)r{zL&^yu`INbY0{KgD0|4la-|?3Vf*LY84{M%zl& zB&v>_Bm|(?UO)Mru8ob$W!m`}+X&$&@5=@0r|J@@mot~A zE9}}3r)`4arcvhiOggWd{lx_%M7VwdPsczA#3IMM@oIWY-n7pPNwPOJFnTsUmZ zoL8gu4!4^W3hCqL7nenZljqR87Xq`Z4!oJ}>f6VrR9h9YaQE}&%1*3o0XLn?iqIgO zA<|HoN2>v)W@9NJ7X%K4bbmDpB4Lr2Sa*|S)Fz>|VY2`ID*unbG^kl>JKDMX>3GNP z=fiD~Mn^{zyVm8|G6KHpSnKZSpMiUr1PXtdpZMfWpkx@c$#PBR{iFK#KU1&Wluju; z3H03=>UXz!4ra-0@_0!mvGw6uN>v~j^2JxL_U@pgt+g_jF=vJKyI$|}kCfMf;6*-Wza*SR zyTw}w5vig)NJe*>yiaew(zIF$O)dXxMH0_X=GZw4-)bk#NrP7J1>m=A3M&)M!HySGJB-GQGFH!8#1)9)7i>s_YBnrNRPD0QSff7BRQ zwA{aD68k&>FYqjht9w4xw_`QGL0neR9F@j2$`KqC3l0oCjFp|;U8a8^3uX|tGG5&oPvnD|Y=s;mp%_>$de*Ru52 z`ay(St-*!E%_Cmcl3J+>rRxtEJXA7U$t3V*A`Alhk*d1JhDCS}PjAaxbNMCXLYYR2 zzK<`<>e26XGSG8d@;=Yq{)s>5K~>Bd(-d%~ z*XB96z$CB<5)IP|^zlP9#|noZ1qrsVM9-1nU1ez?qlnd6j9XKP*|r+eg5F-i!kyjj zIStNM4S~=R=&wf${$xa=R)t2P0^Sc&^kMpEnCwy!==eKy{94VB27S`@B59DOcl~c% z;K#8z+m(7e=}usN$M~P|RLx>=$;uXZ0k}^d5o-k#%~mM8n#_rc-(=h5^?kW}L z((uZ3wl%ul5OUf7mf&1u!MZzHaB4dtTCrPV0?JQ;t~g~Jb+qgR_WBXW_6L{UIbV2tvu0NGVJ8(--xeNw0-;I!D+;Q*WAp8$|9|B(fdpHw}8_i+0(a zvfSCuiEwMJxm2|D5`tgiggf{ag*&@L>gd;JWO-P%@swpg@eq`wB)LDfD!^i^OahB} z3~>R^1b=q$;=LN;H1&Y@Y#J?exKYKLFAev0?*1G3noTGS@!>QCKASeWu=> zdI^c6A)NGwB}GN>Nu@`O>KJ`+fC*zFXZfqkpuRrPg@xm&T!0m?&b0VU+oZzfKduuy z$s*!ujLRnT+NgMaC%>;-{+}oPA0mZ{>6s5i*j(qU?i1}$vo|r7DVk`dsAOaN0T7NK zP#S_;#ub!c_*n$RuL0uF$2hB#DApZJP=*vm$2AEzB_>QpNne?ND}3z1W%FD_95pN` z8HgcNG#LiwpX8#=$Knd6*s~kFgeK6*ON=IP##+-?^*D;oAcU6YhU!A6eT%?1z@%}Z zQUsmfYq9pP#aSzxbx=O zXFC`02Q175dswC4q+Y3GHh0s{+&!_x-lUJy<$jj&()PV|DjfU+d4K$o)*6o{@Q@3~ z`hx^stFw7?6n(4=W#s3%s>M9S(DsXbA>Mq*!2WgIsZKy~=p`_nm^5d$n^eVBB1864g?2Kc}kJc%y1RtOz)ap6N@ z-bBTdF{M62)oBD8V86*9GQ{1wP&mAqIKMnd>)#hSU!aFEP=F|JLpQfCry+6n#7&`_ z3p3Zgs8u$|1;#|$EskH&h~dQ`Hdu33{XA0D4=)f6>Lg4*uKGbwP{?WzRQcbJ;3!=HAY3FCX6$pvRKSxA(XOLR6ib%@3 z*9UEi(7)MXgNy4~TcgU>M^aM4Xfxo2V+8GA1;&I&q=`l0s_jf^^XKIpbNc@cS+@0| z9Y6wV5-7|RGJj|i_}t(NKX^@7vXT7~kE6lLmy$CJjbrdard2BVp;o0TRyJQr7M27} zX;wBrmMO~M#k}i7_emU=!1mD{v2dZ|Ggk&IDQiF?xYIR-U$-9IRIn=`~x1Y zsEG}iR-7vJ8YPP4((~$bp_ZhLP!Nz?g?dQ>F8R(4Vt;d>)5 zY-YK?ncQjWS7DmcM0TmREdwzuE~?MPJe#SFk~I_UzJMRi3u#JUc6>K%ur$_`_qJ6GZ}gUhjhQOjz6D^|0#x!aQ#ba%W(+FM~A4eZ&Q9$(3zpK z+G$UWQ$I$`6> z12y`FudH%{wBPA9WW_!p{z{v*HJ?3Pb8Gp|u2?(ZIZxyZfg;<2_}5I^teY`;Y-~y$ zEY=r#W!BrwE~k}G|M9i3rn>IC+$nwDHid~2-W_wTM0D4ktf`i|`uQ_%H2>qYKA|v$ z{6JvHS9b+{$IvBTeA;dSDA1Na{ zkfrt#u~uytz5>_YG}&9|VxD^fwUQ$_==VY{CiqsxpWX-MWm}C-yKV#0MwEL+76YsF z{hCuRJG%&$2o4Pe-DjN{SK#v19)AzFVHtuHE zR(GM6NjCC-sZF9qG$6j2yKn!asPJDG@BokSH^Sml_h%iF%48Vv?}13gCr*&x8~>eT z1W1QcCW_IKvX_>m6Y)?ao!mUXdgXmZ^!yrFBvHTJMR8S7LmIm>ejjqLzDb#Z@hg=o z-OXxEb3iF2KhfKM$sO?h56cqZ;PJN(3%H#t{i!i;wOg+17rd?Qupmzb-yt^hmiRH5!(y+?c6v)4rz$0xY#Z!Qp<&oV4X^fGZSul>_X))R_3wh zb51}^eS(cW5Cd>N3vnWq7bP~9w?>$4J{v2RBl72Meq}LilWa_6F(TzFszB1(r2D$u z>?*s|z*L`%POF^OXjR(As;ns49`UXg&DTh&>C6hr-2WE~pxGswJGaUGC`r9i z#fTnovO95QNsc8g1HJfK@ETG{QCX*5@6RcIZp7C5`qbEmrq!p?s)#E^((hbYwsaP& z6@GWKo*wR(OP)DiRG8Y{O1d=JkyR~mbH*WhsyNo-h{0phFS&9p)yWEr^&C8Ds-Jd0 znp1shEyJeWs;@aY&z6A|DJAb4of+CHkeer+8#9zcC;qMV`DB#=u`tlN(EG+)wL@H| z9M$*YIRroh7(nh#^SFscX@2~Mv}k!0zH~3dD`(OKSN^4$FsoI_TNj#FlbHX&55s2C z?Ne{iW0)zPmUJkweOqJt1kbe#_eHI;|F)^78d>6V@tr@rY4=sTQ-zM2?8ru0e!j}nhIO$-xw@?Q-O1{fEuY6} zTY~DzJH_wH%mz)2dW|RFUdPg?ye_w01VZsonsvpy7k93d5>=wcmY`9ylb8(X7DNVO zM9@j*_Pm44m!Im?d|G#9OZSLSX@6{2l#Yv)>&_OG5%T0oMlb@xK|(!%(_T^so17ct z)BWKB$!dxBUa|33(iw-+zM9F#KePrvEWL2VSQGlJZ0vMc7*%9Buj9BXI9d z4z3u~Y)n4}DOr?jen8GGsCCQqP^M!>FLp262N z>Qr>RST7Ta$CA5%mjEVvWnf(oq)3~D@2NF=HqveyYGZQD){%ZSIL5<-p>uC!c>WfI6Qdkk0Zq#O$R`y=tJ_ zp^;VcM7WSJ7()5tYWF7c51?z>?$nqX0#TFmTE*NX4ef7ok2dtw%{*`% zXb9+!hKDou`8ZbtjIx8ia}@?^9fuDETNdqTa4gs$0RX=91mGwfJ6=|m`1%4XHCjWn zb`EH!Yr55N+dB>`3``~fFFu15_{BYSeNSHasji)uo-8xbwc+hWxd~^G?OW)O*qm#= zD#zC1s%}pK)5VFY3RBBW^n&+~q1k!H@J|bDA_vM)Fv#H$;QI+13t5H=Ss`xBx2d_*y`;Gk=Vm46qwk5R|VzQt5y-b zG~Q0@S>qRuW{b#0>yW_Kn#N}H7K2R(*R7l?Y_E~e{F(il3ZyYw%B2W5(G`U`$gsVfp$>}3eMcbDLSyn1yky2yn z2P=(Ev*O6PF(^eqT@eE$srQIRu)Q?F{aq6(#?Rb#3m|)P%dw}&QkEOu=qjmmPqxj% z$wx~jwLEVP>k^BPJT{y2t-K&%-^GHF zLUxDc31}r|Dvg!664(J&{Bwf98>IvqM$0oe)^oxf)GMG;LCY)JDHOuCWBpuZiLA1O|V_i44yIEl#RuF!-D=^GTnG(ebw)Svuu$@JV@xizY>e z_p&|av&zm-L&*9r1UGy=pYK&HcuDgz^@dA>G>GTRz2yJyA5m>eP!)@@$-%D$t^YHP zh8P4(N!trYJ3&b|ffSb~dEp9sp8|J=ti8EMyRdn@SC~=o*78JjG8lw|L0Qz%=5?T* zd9)GrX56E*!)PSxApSavZ_pNc{@pSjOA3#iuh|KHeqLA)-cvW@+Gy&@%IYT(f~mq} z>9R~!zm zBh|ii`CJ!~!R1h9e8lEjmCs}ss|{mtFEze3pU7HCz}%)evPia8()qyxxN)c9>7_FI zC}jKqncA%XQp)?4*<)W!`V}bX1xlzY1WohnuD-2%`fc{d(zyDiQouakX=Kp}pHH(} zVDZ>5N@`Xb<_hWE(}4nsTxerS88n%vqCO2q*f&}(>%FG)Nu?EkBc`AO@+1!^c%w-i zh3F&M2p$JJyJMXn2hlpD@hT15=T=;{&!RglCX%G)${sb0pP^%s0J|I+z8RBVLs#sl zU)79lj`*r2W=JA;X>kbV45${UbOt|z<2aK6{t@T&c>)G;-~~>W9BQ#aYs<=wgPn)| zW|l$or|K@#AdX(lDBIpJ^tn6wQz)%V^Tvq+nLCzi-f-tdP}B+jd@@TWi}R-?qf+Tq ze@5pOV-Z&iB`s1F*?TWCaX~M^+9YO!^%()!(evv?0?gW$B|G>bU zFRWf$*9}ejXDh6$%4V8M3@0&}12XT1{V&k+d=q*QeU|V)pJN+4MmD=6##A&az_@9^fM`v^dAZ-g+>`X99``WgN3BP;WY3b{S5r`<%(N z9e@9*Kz^$E;PtL}W6%`!G#YR!AKqm(yINRHAdD|MH8M3l9vtu?pL(FR9Wfd5%6Q*A zs&>uLv!>Zh|12oeZuot`C$7`BRiQcYUXbV_3!W5|L6d(W9Ca66Z<~Zvfh1F0At>B6 z0yhqqq+R$I-Y4ow4x;d>5O+LR8L_a%6Z3mr!M&sPQuUE*uligCUTG_A&0rN0%aEAZdxK11?1$*X_MZtWrgzNYEENZ-X^(<6~y1cZiG z0l{{q_0G=Oq4)7gXWy3$ZEpHzj%dky#8H2n+~ctG3G?E@-aT9LTU4q`>X?p5mdxct z)s5_nf=T!V+myCP{R|Y<7YBj5pl!Lr6UlF1@f7zL_AB#BV}Dlr8vJUp5%{qrM~!3; zu7tZr>~VZRuo><2dtnKX3GSm0mWae2G8h*}qYn{iJp08}U#V4T_!0L8V?I-LbhZOf z^(r2XS7M$pjw$K-ecC+z64B;rRzH}+voE8H09iU;RwcSK2Dlh^)C;q0r!esCvDe3> zXI~Qd-jd+!{0^1(`YkExUeauO(cFI|jmM9-(~t(XiJjNnS1 zzT%FG9!)`&TFv+ZPowXp1QnXS30=o)MDAUHWQlUv@+31=D8~?yPtc_r`UZTCoJrqe%x-9 z8v457!`9V0tRN@D8&}+3T_32qkG)cZ*P4p4vz*_VUz+(@xV4tpuEeCS4#sBxMsBaO zRukX~uS!Cfeas;|swhsKKtB_i$#KdcC~C4L%VJ^9>dYS`5jcwgc1R7q8N}kT$O-@&5 zdf!=1#Jh!}S>JXuiJe%Aj;k22@}+S(ntJCqyFAo+-7lQEbHN(`RDCaGxiX=BUJhsu z2HubB!hCtFt%jw0>bs)^)PVCsQTAaam{pin_b-4lSP6P#gQ(!bw?;Zz_we0=AI#^Q zJ8LuBgz0lHT`%?jUZMZ~0`wVCwD?liH$SQjo1Qzs5>AB_pK`c)1U&K`20YZM@@d%i zCV=s=7F^&G6Rb*ZtLs%TcQJ`7@+1OZJvIjqVGV8!jo+&ru6dEgz%v;0j>7-=spAVJ zPHkWE7ai55s4@+#1)9Tl^%t)^zmBW-y=Zc`oaeBc^yWBz6cox;@ESve-(PNmkxuLV z>Bj}F=cn24wPSR4#W1c#cw;EY8ULc4XhY;hW3g(P*-U4##Fiaxj~$f`+oIXmqm&VH zAz-3Qpuo*+sB+|{LgcY1E`fe$G3d?m6_LXlhb7u$)V@DZf9bT2)P4Atg8U|^ma&Ik zG*>dBY;yu{?%)RmW@j^v>&T4*Fw!7bO+wR)6GWtT+`~z+ZZ#QqKZ{xSY_&Ki493|x zLyPR12%fvipEs%HzeE#{D#!!#cdukT zdT$MsD0BVA>C9B>t(b?1#1bbP?J~~IeTV5hI;heAU;!LKSM5(|v!@;KH)qrlSa7k0 zIDHeu{G+%&<*tQu!z&sk-vrB8TUq)Vk9mxnPQd`~h&m+gkK_gQ8x}6#jwcnxEMXeo z4v6^W?uC0iZc;@vz&ks9qB2_5pSnx0=s@`OUr^wCkmuE7Vw>NC>Yp5$Bp!?}U$%;4 zO>8}~vU{-%7F)y^Tsor@2`iey_@-~utK}{ z@)?xq3453yN|VL}%LiQk*OCX(BT6>-bs^&jeWC&Em>Am4kLY|(=izCow*%!HJ(oB~ zW&^LdA0j@5h>u|?W^v0TRo3ZjTB_6%x42v5G5Y%4ujdGBa?Vv5z6CJNAKWKaCDMp2 zWZsgV*N4@wW`0WNK1+y*w@gK7GwW98AOXfzc9^SAo9)qwLcLxG5(j)k*3@p@i0@T_gzXIIPYDlwjr8P6g85^ zYj%6>o2bqG&3l+Y+z(Dnr>Ccek+^hHk#ac&%J=@_bj%^D`EZe~YLPe|$(yIAgwT>m zYflsAG3_IU*Wxfr;$H0f9C6CN1cvV0SN6t*`6M_*g0Qd}WQy#4*jtrECV#g`l( ztrGp_z#v=^$R+A z*#F;uEg<||S23mW>5ulo*C(6)5E8e)972nbezOM%DF+ zuHj-*bO=MA>S8&X)PrOqrhjANP_S^$23Lr4UYrqK>pkXYe1d-MsC{W9QHAaKIP+TR zn$V$Q9qF-6u3)X5&g<1?W2rtT&uO_Q+>$^g!eoFKguLzj(Rr)scjY*Z++0YMoxW8knhKNc!V-$ix#^%ELdU~#YKz>@@sZ_VhZX%uy zO9wj;Ln4(uTlDj5?lPuzW`$uZP(i2P%)ZeA$$C91g=Cfy4W-lIjio%$NbO;(efnoH z{P$d~OHg)!3)n}y*~xl%UuCKrcc9vo-PMIvBz8l4do!^m=H-GU0gu zr^WS!zS#oBhtzt7MF;txiRv1ZdedpE+h8XR=v;+h$RANaiZA$@%rg1XicX958Z(^9 zK(jNR`4uQ)5eE`@kS1o~1g#)9G^t4JTwdZEMDd_=ZGaeuC>{>1WHrE^T5LMVO|M|> zxtL%Y^3T>HXAN*MA5p&C9)dahhWW2qbRvYpgYbl;09y}3e*L_2kZ&T7tUr<!i3P0XMYP3Aiaqrhu} zzk7llmNH!QI@kd_&r`~KXR8txX3|u$5Rdo)=u?U##9x;vxOuNK>`*@RI%}Iw`Yw_v zHtSS))E#~5tF9ESp&Jh_b6d_lBd_Pyi2~C1cN;p%lfPEBxP*iof(#8}KN57~<^$M$_iyF~hxX+Mqh=ii4I1xR## zT4`FfQ1K*K1_Zmjylk}*s3SIm_)tM2z#ZIHGlLENcYz16Vp*+qxTnM>!u)&S%wTyf zQqsV^^*8Kh2(nDTe<-dfI+4$!Ope|Ucto}lWXEVF-V`g5I{;F8NF)wW?opw~tp2aT z09Kx-Oc#g47nh;LSVQSpF;Yf)(Yheu6`@+!==kfXo8Md)H9%H9>>L$XoTf0EO;hZKSDOi&4~53gYnhfxo1$9)9+UYCshF(hAmZ_H^%+g>YNZHWdS7v1%&9!KG}Pqu8^dAHe( zs`gpxUv#2}XQ~ZckA%yNckd+?83Kq;0hoq*Z5{Bs7kjwe$%VhMQOybTvOhHK9h^@l z1kZ{k-tDhOAn#5{fECkad~QkK@w(Ywdi_)&RbbKu4}t}KhjQSVyxyFx`h2({>`>z$ z&*Tfhd@pZ24Pk)fowbF4Cogeq4<2vywvYB?vVSTlaFuBMxV2AH0Rkes!zIV(k-b;b zOUA6X;51SZFWFR%f6H3-P4u&Y z=0*6sYN4#jN}<;C%L~$8ssNZE2QqCrK_{@M%KVEm>e5_R`9#-b;MoGaTRzb(fy;s6G^v_fZz(k*c>J2UxvojNn>OaX8N zvtf%YfK)65h@h$_q}eB)`l6!7j>c7=cKBt}-*dgN`Qe`|x++JPuC%p*Un%UD>Y^&D zu*mBsP{(T>JI$lECz8`8_~CIIjfq+GFL|=h$Xfiia3AjPi>^uG?sbZL@4Akgr(VEU zyKl?&IyHn4@R$uL+F-uB;2)M{jI`*)KYsb*K7G`mLdNM9Wn*z0bwO{rTgE4ccpO72 zP%uTj{VOZP4?xig)jodFhFl&=E>7H#3VVNIa+t10=-;h-$GYt5OLj7GwLQdqFK;J?|Kb$R!LBcJEhYxxSmKS;cc^A zgyuVTfI5nQB)nyCKOMUwpDuMj_884L@%wJAVJiWrK%@P4lvvx>-75h)=S@jY*F(p- ztA$PkIagf*L7LW-UPzD(FTE$~&GAMS*K=;t4R0+@RNRo-?o^Dy)4^?Kt6)bw#(<{d zZp@y?YT(ZG{MxH>+Dx(4X7GlE0<2!BtJ~2h2&Z7&hKZ@eRA|DRU39v=(QUw^o;Y{jo$^IbLHJIFNfwn&!Unk9_R;>mN`c*WafT zHUwOmA!wlZ&ZF!mrwDzKof(kb4zgvTDNpuf8_BCGF64BN@D(e!QF66InA7h>6QT%8 z{!VS-EATq*)7=v>|GcvL^=WhCK%t|}Z*3$@Zv&?9KOYdm{#Zz`p1ZjOHzz0i%k>0LE)S(w^wG=4h%aPZo!PCQO7&ubq}o_ zEUnVdH#-j+ejeWBaJ~JM#&4Z4eCDuxHUU--!NLzEJ}~Gwle2~Vu`Ay^I4GW@c;k5r z>Crvy2hYq7=73^E^1A=%)jGKHyFa#7Ya`K3AXyeP zOj|O8gi-hkpB58c-K%>GcwX5EdSLO1<8B-Lwm#de9_ppL{^-2#QfYVC5#;Zt#Nz$B zVaBCvsbk}p^^D-aaWv_}I%YysGr4XxfN)p)N6YAUiVBQ6 zA*yNSkGYMy<3E;FCD4U+Ds}5)XuANCnJy=|I(my{0wnx3xjffltv;`#z18KHDI||y z&uRc};MWfd(*)K5Pa~GjHtFO_eYKuo1-;LhlB}R;{FB4_^hhmST$L{8SM%u@#=~y1 zGp5}^4h)H>(S6gqlUJ?sv}lZ|E!~@rpIC+Chle&1K4BBv#jaL;-#TV~YG9?mc<1R& zKrwRb=J3p7zVulRj{C}{u)j}l)~su_pr_xH_2MrmvY?j0h5U`12{8Rp4cH3wYLjCPmU zQ^BuNV*^Y-dQ!iu>ErSo^Z8_M`u5~5YmqV%GWX<$%zyEt%phB9&aMJ&cEwS--K_e` z;^R1k>gWBZ7jkfy4|P`$9K;s;mF4yVtE;T^F?tD;_`vIG`-e%;lQL9Rz>_~oh|e8K z?na(ppRyG&)Ho9^jb;1dtk-*YhZxRtdA@nEVy)P5bvolD=gaMn?i zVS>oZaT2`}TC^cgi@ScgdBixv^<$~ba-!stKbvzwZy8K!gO++{kV7i>$T#vn`4V5mKA3m6_7<@6GDW;tO&EC(!sx5=;d(h-EKJq6s;M=yi(> z>!DvUTED0L0iXY7>jy8zv=39DLBSHgP_Xg7r_c=_03(qJc>lmG!H*@nIeJH}>#x?V z70W#H1G1MOsDsJ>eCDiM^M#8^ry;q2e>P=P*{{SsDfJ9jg9tZp^=lc7L9HN(c&FfkH)xKI+?dMZEv zw;)H0SQNS>Za^ZvjwD_w^+3l#^j7&+!*lUJBa!|Uh^iSV|J zj6!gWAg3woyJ)2hLA?kOkV%1l>SjXdnwTfe+t>cfEW_J*-4d-mj{fBZ(%hc)On8-u zQd{W98WR$nVrl{r36S8rA9z9q^LR~afLpvJi_X;h=2X&m89;8>sFxN6OVQRUeRTzB zur__4$gbb2ID)uxKZU3st~6y1A_cz(X%%@~E{0%wL4o>#_f@zHY{jKV6ipcV^mKyt zueGmK%;$I1N@R{Px#vmK9BnzO5A45FNAC6ulF3L~p(!r)ytfV{DyoHwog#?0$Jg#K z3Ia}73j`g74lraslCv1eeotEx@Cj|JG21!IluT?oy>R6@IEi(K1dhfK&ZE_n$9M~fj z$geXWPY8&_sdw)(T`S=t+9#M8R@~l|{kp4Ilgjq>7b-wL%HK2>)*5FTy&TWxNp_gB zK(d6KZG{$tZn*_KCBk~cu+VU66z!%vjMu(xY$e2F&I?#R^5TRN?^I#-qZAjRXU|$! zNMfeM#SrW*vgWnwj4)?R+$G8iRl7Ve64B^-b>Q-T6DeKMXPX^NWxA1n{Nm-Z7)~`h z9`N*|{L3HA;REenIjM(!lu~VEXwr zfQo)bIAf~nTMSCDViucE9A-~fcjPsd6QWg6&{FiEV`sJu{RQ-C+)LS)8L1g`K^8eY z#hiDPVa^z(&;giWsPd$L%+2Ol0w)c&gpjr-yfdLm*Bq zt z=DMlK9JgjA$7Lg|I2#ySvRNL_63#j&oeaI0sy09=8QOx2>ah*K&IRMG8=&^K>Le2^ zg?%f-D1_-b!{nI{t~;#Mu{l2AZ^A3@fPAM{xBiiJA#GG&=-WEyWD}>|63O^axJtoQM9W0NY|SErz<~^ zOV5+an2#>kZ-hQ(W_@WEN|DRmz8->7oQ$V0UyQwVF;|e%nWiojK+h^^h_{qisNNcQ zC*rVI9xL)tZABq{jlVrqOwp$Eygq^P+t9FC5>jbY%)Jx#A77OIAgA{M`$3s37}UB|Yh=sZ789Eb410G=;keh%*@Ow%GYKCz}QX+AQXL%UHL}Acuv|}AI?IclJgoztrz=t{9akeWd-0MC4BR0D% zpL=vNA~I)gL#=Qm5N>K%(CVVG397z-<~VRh%O~}ZesceY8C&$W7o9gm2F-o7%t>Op zy86ug)2L z@4W#Y0lW6zblorvV0ve*u!cfbz}&_BTl3Un9r{=UhqU+z8o5 zyC(9AUwlY@+0$@>+Z{vyjqIO{3$1up^4g9eDd~3qWC}U{`StD2FM}lXDT4CRdC0k;B*XCnAcJv+k=rdr*8YJjGU*EB@xb{?iHV#2v7& z*&eu$n=!^cRj*YfYB*ac6Pt}`;Y{V;_r%SV(uDU7X65+VVw}6yTP(5L3t^B${www9 zAr-a|YR=mh$ z2aXAEh1OaG6D^@SkmS6glM4SV(b%bjjj<5weQ35?eYg0_WJRyR>bOd0wC@!X2Ek^q zkWb?)joD7o(P;* zmZ+8_oZ$bd-}C2MlrB$;86?alB40r|g|V3JW&Ig945b;-FKQ7-RfWD)iCh@#4-{&} zkP3R{&z*qDxx%QXd$RNz&-hC)H(exW5i2#iQ+BGYEj}12SL@T&kI-JSmOdFJ;q1DR z#xPP9TKQAl1gbc>pFUF`0Ubd{4 zgzl`+ctm8ZJ~u4aH zc)9u#qmV$Ws{CN;756F;+s90@cwpEsR~k~geS9xiv?2oZT_KrN(ve^&U)Is^n% zHa-|Mn&?&SiKe`qFDgiQKJr~9O+_Xi$){g$5ZEm$W(b-_mpRds^TS!ZEbUp(-&9K) zVbQqc6;6Okc&c&~M$=^Y1HV%vFR3FQ@R8qk$(zY2x}{5J);XU+U`k%Or%!{UZ3fUa<#4#@z9LTLF0AOp~5--oznROj>!y)KL&hSfOr73Dmpp{=(eO2`|Yx z8DDv_(Lb_pAH^l7om?6yuVs83Mzgt+c}@es0jnZ%$3-N15uBtdc=jqx=y z*X=U>EIdXufqh!7=;89*XRSf9`6hn=ahTkxTVQb&t@<}|u}C0$KAyN+*6)RrH!5;Y zXX=ump(L(6%+D(wFAmRJ`UkbRwH?XCnLbauJBm0seEhKq|3rM0k#At3?(b63!6N78 z-Ovp}d{cq5O>fL6n^ieArd9pfpB1}k92VWKtCp0mlll>HCB8mC1%gHTHZ`(&{0==3 z{J_TOe&UfoV&)%Nj=O{_uF}9-xh!lCcVFz}*qZwyh^pSB{Ob<)e?2?aiJ_Utt)+Dz zKmecuFFA=NO;$oCD(|n{G=6(S)QBZqWv9cTqBf55st}fh&0(<+Isjy(iqw)2i9oM-#jjMm9MCQgjc( zC!*0l$aC%Rwf)|li6YG#8TU%Eu&GZm&;jB2uk{opa2DUwBlNNay?(ZYS@M_*tj~Cms^E^C@_6dLvX?YK| zeua@ZvSB4O;Wg)8?Ue_#GCEx;{)m*|j^zY?cjO*?sqAxv$Hg1H(2|vN_0`rjc4_im z(QCB4X83ReP(6%_(D5D7(PAY{IN6%6+be`B_jztilwn|oXb!E&|abhQadeo`(wWW+CaW_v)SUCA^T=9+K*#sXn5S!iLvjAy&gNtYJ^5n28UnLbsCnZ zj{AAGES*lRLvG%AcUh`rOa;_q(;N2u;caJ;6u?y~2vt~QU=x3G^q$&$h!0X|^soLa z+uU4i{|Wn=T%n2q5MDeAvwY#F<6wv+W|j zgDFz`f5=X0qr&Y+>WUCH-=vk@wn()Gum8pflU%>9Y1}(yDMQ_r! zxAP6?;(KY@Lzq%!iZ7;U#BT4ybiQ8h3>DACX}-xtlL`HD9&^kokVawWpCfW>;S*DP z+giSafKH~hiDVmKLM`#AG>aRI9!uIT7i&@^-efdivBr)I*P6xo@l)x7guomLNnN-a zvwVi&*UzWI#<~T@U5w|K=5oLN{X~lR^%_oo0=XvE^0Oik+U#Ei#+p(YVgCAj!*u#E zW}ttL#7E<0dnjHtk7YE3Z=5ubH|GyWkPC0hO|52$**cqQWIrmu?g!;NsN5JpK`DB2 z+8K7|RA?GtgrdWO2)T$S@;&Cp=~%UR0ITt#VjT+IFO=wI@Ei9 zIGdfA&Lqz*!dDyK-x^Jd8Tg@NV3|nqB5`Y%s^J zLLW-IJ(GH6p`re#U_?v9499NYlvp!~OgVbft61ggy?T?|$C#e;B;-W;j|HWgxlE|)xhMKo`?KImCun04$RBk(R#W(~1>v zjl)u<)dkG(yyLP%r=Go1CU^Gh!m%fO^MRQDLcWSYJxa_M-u^MWhsgSw0$Za)5vw}t zwkjQJi9d~*dee9}HYMNJ29yf8Y4QXXOrZPI96qVqd#sljtS=&W`b_htZqk zsrnW1kY^q5(R}n>j9pxxZUKe>l`#>|89Ac-s2$fDOuknD1$$`BrimsGqdCO}DCu($ zKRjg`K`maYW-7mFfUHnpW`87hRdHSjs#fKyaUw#j$~=$w`cJUs zQDhw21rOa%#UHO65%2JN*u&G&oMBTOp2vH%KlGn{uuSVX?M0Jh2T1Ex(v4jLy~ml6 zcj|-V?HY~e0tN32T`;izMw5~n(2n=5k=dBc_up75pTtGqut9xxlVEvV4UYsN%9D2V*xJYc312UjATQNiqn+hEQ zIl!ZO-)^x%0E@B8Xxzo;#7wQbe)Z_}@SW`IyH76a@NEB&ODRYNR{f_9BCcc|NF|&~ zsWl~{^>rPC@O9Ab#@VA$5=InVNYHTVPUvwuzHlO8tHvRdkefuQt9c;)onrp*oa3@I zgO(%t=w&DeDz1PgHHshRN_4=P*7&GcA7(mcw+87gS+ILA^cjD`8E6{$*m81L zXSydWo`B#RW5Lu}&?@+(CjfUc5u|gILX9o~8&tk@t4*+;6_d%D7#jO1B)=@+Ve=8_ zsH0+!j(^GUB5eJW%cU2P|E#-nac1)FjO)oL4kgkC)&Wr$Dfg}R-r19GZ;xp!(A3uL z@|tgPnMa#bzMtfqCiea3B$$27RIwSD;#>?H$Ao(qmp9 z?fm6=o1kQ=Dq6Rs#|eUXnkshHq^J#OS?a;C^(J>)u@}8F3w;Z=L#Ad!HM6i{Kq}`x zYW+#T1H$e;Ge1V8li5qVzgiEYQDKH5{CwUi#_2mJ-r{`KP=Ye}nBgT?jIsuUuc~o< za8s`9v5USXl*;Xz6WJ1IiIW{(Vg)~-u0|Zs(I-B|E znr%iYU~3f;)~6R&PaPf&%;Z|b6lUqjl=}0&&A@h~S_-68b-&T{gFECz*ng)CE(9C!zOg`uAPoi4FgKnthl z5w}a|d1nQAEeD|=o%3fu{s_dXF6YxV3CS%9L&@bAbv;yFo16S0!e#D@u*Zn?6U8qm z{m*AN83;>LUn+iIEd#n)pNKZY zL<+~$mNp(#8a3SsgH_YQ6CRi)7Mi7^T z=4lL``+(g9F9}}oSU2+h5S|p?!Is!hc0*XN!BLNZ3Q0VNGUA2QQ{?tti-2d-yP4VI zy;sYS)SJCcaVk2bj?Sz`LJNYe5S?zfyaC1X=c&#g*&B_=?|@Ye!=n4>3YR${_VJme zDqg6`IZnig8Aszy93?LEgPt$z)pDj~z9~HK0!tcC#38p8$+3HIzPQuGD8%0fdeWZ? z<_zeLt{SbYkQly`e)d>&je(S!$hHg~BTOt(nqcN0YjUbM`ZGPClF6bwS&da#JRd7D z>-Xf7!XcxXCh~+%Em~vUg+v6B$6?V7|JDJ;0hz?ZC!Pjeo?1ua5Vp_PqK~PA^tsCG zL3e1Ya*OAF=|ZN&e^89b4G94)3=pt4h64=SazABU9MH9RSf}2*qt6cX-4(8zDOcy zkDlN56UnL+y?Y=C?)-wO!9vKAyM^$2ws%lGPBQTk+RRqQOzOYYs{iAn3+xtr#D)Aw z)`XEmnGbKqhu_-bsycpl_^Fhv`2vMG3BSG&*o&)J5PgKJ^29wRU)iBGF@Cs^Ko`#- zgGEo!JB+teb(9X#k)-~Lr-`OKnj2yTHNKzicP!l*OJuR=ppA@y27cJIE}5t{9c zIYvjOkiGXgKow7M;oaQmng#^a3;5f!oX4`fkJ?1Y+5xW5dwwhB#iZ-cK~@w%4($4_ zCiS{GNO{+|q#v~)&`EZS^LEc420a&UIgbuYMrBX29NOEoPHd-O1vxP%?f%gXCG?J`7z!f1Q&tuesZ~w{q%z{_A=^S}?V>6ra0< z#3EyE*RIv?;JI`gtmO50m^Cnn$*}`^@zEU5N5At?y`1|Z=r-DPa832KYJM#Eh-jm4 z#WoPz-cd^mjz+7t^$9L8@lvtrw%OuE0)X~Jys07I@#_VYh0NzxpePL;d> zeFXR3BN-h9e^p$p>*%?YUZVK|CZv0b$8US0nDqJO3rv!?z&WNng=$sZ#c8I!HCbVd zGz6q@e)rHw{AYvdb@juQ^c98a_Abu4^x-x78|*o}pu`ox90G zxA(dWFqiiH-d7PH_dj+ z4~ROJ{QS=C_uyzsdpKm?60uthe7!DhKn#HPn|$|}g?6n#AUIL&oN~?fN{v2PUND>K zpE!y!*d{7(s8hO(<#G09wS2rcL5w==C9b?G_31MI#R4d`mpSQbu57xpdm#Q(10p`j zsa_xG4?>7l#|}cx@O~Gk*Vn;toK28VPN!4R(2}7h)2I`I-EBaYwUpj?`VCJci0@Cc z1NJGb2V(|0P*1zZ3W=pdLP?$asenVFf*W{tC%6JQCjmy{%t91|NRLqr06oF_ACqS{y2sRFezWZU>~zGP4N(Ef^w*m0Na6?mbDu zKsLXd7AWDoH(@VX{3!Os`yD>h_zC5D;fCAKr%1y2c0gvr7gB~ zDVVUvq$WK_UM(G zD^V=O0xE#G$Nyqn7BX<3brz$79*&Xr*t zxUX3$RxCpdjlzvYp9)g(YGQ zgaei!EbOCvi zPG&91MO5a6HiHx&5@0%8~lewmtIM|NP4D9=9L%b_XmV~Pp%W_3L$ zPZ!ADV_+uBVg4G=-!o7C&siQJ4=vt;o^}>?vzt%qc+zKu{lxEeRj?)dXdDt4e+yq4 z>x%o9L@*Et`+dl%&S@!Zsc_9WnuzxK~=Udyi7`dTg-*8WiG@IPn&g z9#tpmCBm%IF z_=1VV$grm$NGK%Csb?E)QhtWnH{X^yyx;QcBVk9IYfc5#PJZD%TE@@grj(Bl@J2h4 zN@KNbTA|DMr``cw?fwp(hfS~g+E^Bqz+cX0p-R(ICX4*x=j`}-?6q$D<7TNfz0CH| zUTW>A?bUvK^+Wqb&1e94(u?nWTt@C+AG|3KIk9FmS#NokC}=>CEkK8#m-&^Gwkh-g zu?Em{FQG;vGYL3A0usJdG>p7;^H?e6(UoGPqGh5c*lTv!Dea`xv)(8%1Vy8PA9cQg z1&LHV&bq8T7J9oOUs>Mwt*m5J0af`1%cw?dDYs>xc@NA!WX~oaz|ZCfI3AA z)5F?E01Lv*DCKq#J~qv7hy`F87YXQ&E(+2Q5eN{L7{UcG1!3@|pBQ5khLFgpUf+fY z8$;IeFo;*Rd(G}MNNHc(U1?6aws&+44Gw1P?wd5X)b7N~RcOn$1l%yjK5gOMu?;2s zmsuh8gapVr*$K1%#~6(v0cgAEkSr)TxB&y%s{GeXD2CO=#EpPmM)4f&TgP zXV0p;XDrIK%&zc1?yM01`pW|;e1zjxaErpU%%9%+^B#J=6GXVD7_z^}oTHBV-%#ma z?F>W<3V_EIj98(}`d@GT_j7-rm*>QUTSDBGTVf{(wlv-wPs@@`q8IIt!Xekvy7tp= z@zl9p=$8mV;(XCtd$|{rbNiiIBQF9Tx95v0DmD<(Izkuz7Ep1yGcAEOQQ|VS)uLMS z;T_V}3+nKHaRmSFzHCxZlJm?d=EMpYng95^x;7M!wtM@NFpg z+|TN(j*|eemD&VK9P3xuk$9PNrp=57nmqaic{=^0O{I00N8Grg{{VT#&U6hBFni_+ zOms3$K$FsMc~b2|5?PBzrq_Kz_ur6gW1!P86ev1z?9hPFkKVj|CN24^@P~<4RzE^x zZC7ej_87Dk0oJKYt0S3C9p#BxwPXbM#Ypu_jr3?~w@VUf%U?_-Z{0>`o^(#H8@TD? zc(;1vFZ@`1?zUHZ2Sn&Nn*>=_wQmOs@Pd1o&Mtv>Ue&*X$aOvbly6&3*R z6ZsW61GF~Oa{PLSHa2p28y!s4lsH2I>JjwYJ(FI8dGt6|Li1y}^@zTmJjwb1`<^%> zD+^;BCgRy=`8F#6wGJSNl~s)_DT0Sy(76NWv38B+2HA4+vr#b; zu49b!#EY$-PN?V36gkQCh;!a%7J&uuBibQ=olTCf!Id~XW6;LP0JZNaB~-fZ17{^F`nODUY0~Cwg4FV^AOkn*V^Cr+JEog2`R!iLn|DI zY3LE@(8Ea#GBO`2Uki0{HJBe)l^~E2X`SwziaD&et1tjMoj9?{L?OKijfyQ76?SRPtwv9N73zIW)lV4*blkoYa!=e!9SJ?vWwnSzT zU)`E_Fbw*29~ceWMOohVzyDr7)qYURBB z(fFQt**rdhKfwH|jcmW7#|h+VjS3w>7nkpF_W{WlobNxrPZe9Ksl`}hmw+-XiUto% zYujD!1-~G)ru9QK+iw&q2}Vl6T<;e_e!o^$JJUN-r-_~`1t8d=-W@7~c3*|0jgI^H zBMw`;N;Z!@XxUWeKsQ3V@&)@mg$$2r03baC^6wHkTqK8+*a$hmWr9hxCQgDYMBRj& zhDEL{0C5q@Zm}Vlz)xkQQ#O7jI6S5>e^3z<8ePbDgG_l1AcLt4GIpqYRc9N>Kh|20 zNv3mHvQQ~zMp!6<$BIyxyHme#w*Z7gHZKV))net<zNtbH8!281awG z%r&7Hbb;S%zVRBPJ@NxGZ{Fj$ypQ2>_*ofFx;8Mngd^o4v$vK}%~gQ2TpPs>tI%~O z3iyq)0A+9n3kgv3`?T?9%(z&BJw4cR(!M>{p{1(#`IU#~vvRTe*F5cb92_7oOUsVX ze^KbXC0oZOxr7=~x-cO+r((^()#c?U zphT52xHU&5BUvGcPyZC{^co{i^799<4`de-4wK&4lmzMwmEXOEbWSoN_NWxd2PF0N z;~Td{TkRj=_x*mctXCIPFKycFc<*u-Yu}dHNdbJkUFy1^d))O76BZ)6*U)(c5ZuQJ zf{-NtZHp#_CVB~f!s4#4b?3VYoy`v_3W04w=Dq^Le1@UHT!!;NMEbD%OMVFR%}YPR zx2uKo)rM`Q%R@b}eB44^w#y0aONWIhDv;6hmHRKKVwsagm;)wavmW2Ah1s$HVzN;z zXb*xz!yBu!PvD!lZn}W1Mpq!!Hp2iQ9aH+^&_87~RT%Zeb|!K@-VS_6N;$0O9UEF( z6T_WC65Q|bK~v9(FEU}|OOC>&Gh6EdKpSs>Y1oPa#}Pufyjd^{`x;PUQB&kL2-|ha z{t`Q}ZC+lo;&EEya9)Ka;JvwI34`=ar6;s<#iM)($$}iyv~A!P8bMG6-0B6$3ptt` z#|q5*^*Y(T&JB16xd1CwG)1agqVaqzyjl$$91no-yAZp#nZNbQ5#5f7wLpXE8)Ya6 z7(5S@^ad?OV|ZI#e>>5Ck)7bueP?c^ZmU?EDsy(ckdoCF z811aOm4u+Z!?z5k%RnA({?UWvU|2!9w4F--D;Fz>vF`qMZ6d|H@DO*RR!f zWzD18#M;;WC*P&>o5w1E;MFg5T0CJYwRw9ja+W0D<)GDbjt)nkN789ksjb0Q9v;^3 z&zBWX=#%8F0R#HCLpE!c`UrB*q#q_tb(=#ih4qfn-}AbH`=yVlZIxVRT0yz};-*)i( zPj$IC3NHb@d24_IMi%YE;NFQtlc>alIaA>E1`F?L1iJj)Cjcc;Pr9D&{R&-7V!_nQ z^K@T!TNVRQxiYc`E6~}jR@{zCGxrg=t)VlEk~}3nS6iH{_RqlV;ly2zseVfpFYUDJ z0{~aHuLz$Ti||t3DFSEmS#mU2ckW7-w8rWhmE$FT4(Mt%{^-b^SIW0zpMgrBy^&iqp47W+2_m;*A-5q1>wEU2ot1Fc0biQTv~uU zM((}=M8|J%ct0X^ZbQ=?q${2K>)3&4CpO9!qft5NTZA1@h$UmW6%^;T)&e<5J9>Z@ z%DiLKxsM)2$}5o%+vqvqg)f`K$Z)#k6R-JPufx+ywkVyzk3Y994R3+-q1M!$Xc+x7 zAfLNJGbK91bUYJMD^`JevZp|(Eb$6X+Ae^%#t+n4Tu0OanM^&^_Lz?t^nfv6t5^6I z{}=R@PHexyZ$a&_Vl}dE*y0Ez0Z{37*Gk^q+4aYa^aMeACFSGa56ib0^B38Lzq;An zq99o83V$EH*`uNen7AZ`q=K?(#dEI8jn3`+Bd^K9q&-(G$K|sX2YjT~Ra-!F(KcuX zSMjH_`Fk~jSjrbplNUyQ`#M)zR!c@UrG{A(vpl1*XfpWOR;h$Y%A&No@aJuLOj4l0 zZp5i~t&UhRKz{a1alQL9q0N1t&+qS8O}3G-*LDeGgN)f3bcL5ww#0rYd&LF>J#0o0 zF-J;3dE&aBtjbAD2;U&(e*y#$9_mzxZ({+?;9$%ohFuT1?BIFg*7AEo@|KVR^fd7( zoD2K%iF=qSdO$fqB%}ExZ`Z%N(4EMflp5*y8bdwf?lHS=vWl#$n9W>P37p}Y|5gI2 zthUu1jPnDyBvFwcFZnRrE!9v?dcxa0|F}Pu-0+)8Z@OgTw;rXOEBs#nyg4fnIqRKF zkAK>RPu0BBA2oR2BOt#JYx;|H_t%y37w0b(xMT<6Cs8XmnXlOI&YpfT*={8B^?Kw~ zDD}&4qTLqVc%mqQpEzNRpV$^(xUCWY78s2`Gc_HmMvYMXvW5$gns7VGDQhup+hc$G z&d3Hki8e569JqMO0<=^O#ReiG)lMLmG|wwi*-g`x00WB-Gnyti{yG{Ixg9!7e>ZW& zu9bkxe2jxZ-0&q~DI#B7IQ7N;O>P=Z_INWxB5Z4)10+b_zSak#S;c}OSp_)Z zm5rpS*dg&!BqUBPF5EIPCO=rzh-0-!OFY~ZaxGRVR3ZA{mI2myZOt&f{3NUhWFB<) zYXv-$mkclV`x@u%CS?(fnA`m6_^`$@%f7@Ag9IO`pqY%=?aRqcNqM`gDg2v&0`La} z4}kvZu=hJnclMqwd;+A2#mdp`Og|{UPd1sY(2!~BVXhRGAP#%69792V0tv}CyS^`PTR9O=`7~a3O6qbA_L+JjBBlLqA3LBa~hdPdtk(wr`{5XBOsK9 z?i)Z@cq);jz(JEpVrW^o7p2f>MDq&>Xz+&H5%u>`>jxOaAIcl=@HnH0lP$;VLfV$k z+vcr9NjqE-7spICS&b+v9-7Kb1kJu4xOv@TDP0?UPZ&b3knS%gg=)*L(44=*#z+<| zLJ5bretfJsvCj^lJh_WrHdn3|Okwv8DENk|;Wp|Qvj3ggW9_p>2_06I@9W+bt^;f->FOa1c&nD0&DdR$t+qwrfzwrN3Q*eZ(0e{r%(giP)vtIiMfTZvHB4VtBz6*&RQ6x{e#ppcFQa_{B4(f*DU%Q%W8 zXxo#6K;Um6{!Dep_r3UGI_uI17y$XgJA^OXeDuO9SByo^cd4iJ7qd;5+v9C6nEJ(Y zDnH$;u*ru{EZ@+p`|feWjyaYuUs|d!x`~qsW5MI)8R6NT3y!d$*A+-7$e;Fbm=tkV z01*w~IT}Mkq?Bo6qL}dHjydsFy$LWJ?xV3hUPnZrFF^$2xdFkRqfAf$AI@Shq)|Su zx+dBn!g$)b0V37C;n=VHGm6bj8N#lq$?z%PJ$$TLJ{clng)F@4i(fFpoB*UrAeliF zZNuZ#ZiXiCw2n5j%N|XquSs-VuC=#&5 z*CEhxh=tm98tt$cHa#N>FUEtId#H6M?I?mq0fh>{&d{enh0He9zeCVRuQeSXy#zuF zm!A6NOC7UrJ=eYm056$Huq7_$oe0T7ER6dyqftkd*4!27Zep)bGVsmJ7 zcB93etkRH$Z#EW3+__ucf3XE&M%~jxY9FC&b!==K&%4ixN7N=Mjc?SCQ!s?6rc7hF z^x|530oARdx8a(|inQT$PaWOSv!_g}GB?>mh}j+S+eE%Q4`v56U`o?<|4(6^a9U=_nfr+LVNoDC+hI!MbB5qa@H-vGQ1B3)=-uU%f zqgXAE!j$n&2m8*oR9z~EA8&!QxNR3}#Dwxa-+1AXgGgh-ISbfoEX(hgm@pX3n2JvV zlMtkx-WtKJL?8$3!-uJ}k~PjioL>XEurt7gnU8-|B^}q2p9EFOx*4jcvYiN~XB6|Y zO~vTBQty1=^zkG|rz=lY2T;e-QO9KJONnmfmi#R-?XM{G|2_ODAd_jsyPk<(yrG+|CR_6Ef}tgCU-ez%A$ zQn@ z#+EBbzuX;3q8t@R8wWsMH5x)uLMMn*@;ul+d_YblABbYs_fnVgX1OPdF@H#(p%pf( zwV4pPy1lKJ^qd^O9uCuacI35TTW2${(BIqkX$2g6Y?W^9s)b+zzSda7DzIh!uw|S& z)Mg;j4Tcpk-RLo+0NP7Dd7fv`T?@LHRKbpcC`BbT6sE;qMaz1-IXp)w+a8>VY%Z&l zM+5Cv3E+iV352m(++#E%Pa38pDqvd(QG$9fd>h*J^)*sM8~gnZP@O(={@Yq3bXgya zZi#7=Qga+Tl_wAbj_By{JC)(E=Bj6ET6!vT5=duukLbORRWM%%+^n9(R|6YU`Nap{ z4(o5e9lFH+ybLn*Y%lngc3iHr@R3SEK5Mx-_g6w)0v94ysuIfLNZ|%# zHWAzb67sd~Umzh+5Vfhvsw*gwj=4Y?!74rLBScTA@y0VzN`E^kce zlAjiieLx_~bpJ0y$;s2zNoTiuxF6{?o{=P-4vN6ZTRwVJ+tW`szowL}{Ue!24c10SyaK>-V{pc@jOUW69g##uM4>Q%WiDz>B zHPbpzS9N#OJY4;8E!KXorZ+oTKnV+diDz_J%NCqxG zibtf+d$0s+@_Ig$AS%RR;Y!Crh=^Uj4Xqfnwnz6VkjKBN&>6#_;RL{%iZ{sGJWfXy zjqp6@2~~MA@PJ%48gl=8C*&}}zKP#j(HVtpr|W&*gli#U$Z1z#@hv^4vPYqUeO4t`-)?AX zuW&U5-@r%)cawS5706-*`o!MAeBx2^+`v9SBHB9TyDfmC=bd^>Z%PuZOY$o@FEQ(! zjmHjEoJRUhAR4{Zhd$a+N#Is$*QYxmC^p35a<`qU`037|<>CyCqrV%4%TOv)2YvnI z!hV-^=?lFe)gh$YFd4UWza+FaQPLSgN@mg%akCp<6T)YU8K;qsQ2?+XuD%0UMF=dJArQ?IQU43z!+NZ1ACNL&j`_=*bIIM?DeTWvC)q(pXr&xVV1k8gl zazM>JI{Gi_mu0bci8RK)sb5-C7^BOer&ZQ`UaJq{7Hz={y`%o4$>AIGRH6>K_RJMuXE`Ac12wG@(x@Och(BnoJ;=C-MU!d7Q|dIa<>;UCI3nwwEq&E8W-N|thwV}3v7{cCcrrv9@V6_)#?a1~233_{^Lp!eWRV zTnu+$^Q<<5AL~K;g3JCF5tt?Xepl*+Ulwbu_$u`UN79=h_NQP?)GqVR`@~xHnQk8$ zoZfO7V4bkK9bwVBjdwgI-?!yMks7kH0SAV~DQ`J_-Tj2l0{+r+AhSpxLc(d4wEzFO z1d+Ugz-0~7hbQ{-*xN>a=oA5;3E;Zd3;T}R_p9IKtc|iskGOfc&EK2N|AMRv0NPXo zz`iigE zCj~FGQ9ohK>uj8VNP}VW0#?dO8@UIjfMOEWDeH9}ZE@tJW@so<4S-e6On_VUjtOSO z0kvMffiM;Vs5?T1jTy5{#Xfq5fLeRURKFXf(gRb4RBqcM)LNBq4qU^qOyOnY zF=2ubEYk_YcP5h9=&}S|L}FqhFd4b)Ct4YHQc*_QASVvz^xq86+t_GcM-55ix1qe?9XOhS|0tTddDlYQL?`D`Es$7^$9 zy#*&u5z!L(hJ4H5WqnN%{$D5uXe`@kFo_p>svl3*r?9d$ZRgal*~7=4U^~jo5;-VMB5|)akBq~B8YQ9((4E4 zetC$rhR@r(9oMVLY_eUk^S*?FjVl6j7fV3i$u(B}q=gvseT^5or8-twFC5*G!B_+z^C_M z^;xJ6C8my!j#BeB`4RTN&@iJBG2$j@0-kD7Gil!T08NgmkIj z<9O@$7|HZsl8c*3JMgs;jnCIXh=yR~Kj&WKGOjdy;`$Z-;n}QRJBV6tU8ETSkeg{B z%}QMl9ePtA!vyfgzAuSn0_48_Utp9vS2>J$^CU=;AXyaV8dDXMUZ+VHo8l^{gY0Uc z6=j8pH~scHSK`gxV7P}~Gg|FS)fiuD9AHxO6sUJBdq*$MbejF5mKd=WAkG7-S6r#Y zby(_KAgt6IltmW4w4pco_6vpF7pIAssRPPBw|;uH&RIIxGj%|#O0M20pf>lnj(&v4-e=gU8y%#%3TJlM z{fA#}rQgmM~w(mAKcpWnaX+yBtY@weo7IGcB!VR%GI1DT;^rqsH z6Lfz<+83(e=34|@w&G>$`71tAUDOV=$7cH#u^qphFb$3jJ|L*xX#dmcX9!g~bRQi2 z`76zG%uRR_4vP=gd9qY;*6^l28s*x zpbQVO@C#r6#>Q;pcp+-<^SSPK65LB(rT-^QUcPsOu^bnW~Rb$*vC@ zJFffVpfb$&v*hNo*!ie-8Kq6}h)~-(06n_Y>3s=3`eeh|WY$JCjolBkRmTBfE1y_8 z2ABbt#BmL;fCLlO`yDaNGwuukd-?Am4S-RS<{`9jr^*vd?I+zmn?hb&fE5+eJ@U?5 zp9{!|yT8Qgv@HM9pWPWmp3nGX*s~?*v&>y~EkVaSp!o0$RI)S1;UzL#cHSG3y|#SD zphgT>cW4TEXL8s>qyEv7-Kf)9Vayt+UBoM;>XEH<9Y?5P zy9CjZ@yx+JB)$it$Wp5Ja<$D8x6H6Hh?eWAM6a9|1xV3|q$2&<4d;G2`if&jP$cMq z-PM@sXw4(_$OvG`AS7VdS&WGTl*JlDf8dNLnRp(BAvA`iQ>kFqvGgndFbSSyduSBX zi^7Vo#A47FE=+XvxL5Aib$nY9>?UrY4XF0bZKkbjJ@9U-!+6}FsX#P;sEpx0D-m~xv` zV=;fMg7rriWJ#=0G@%zh$ecFI+GTnxcYdYBS7QIudjN8lxFBL%j9tun|#C8P_d z&(c@{geUc`GfUZ)TnQw{bPg+hEeWa!pzJ|Q)z(L)?Wqr;{;DgQMhU1Ll@dtkh`wv> z7~uX`N3DfPp7lwZ2+Su#UNHouP5$s+g(#f(eP83}R}F_b5`mfRKZ4L@-aegdAZ$b6 zK_fln8liL2r(VO|9!)K=gCv0TGs!qamxz&lLSc_V5^Wx+)-xmm2 zIRE5P{6k=sPPS@XBiw%(1;Qak?`_n}jhp!T%-@kHa^odOq#8Ro-e}Mp0S8G8w1qhz zD|d|+V~zxejd~s)%UkL*-G&z?P<^j}*sb;Om`cVc1}T!Q#eR@*0kXLN0j#CMFlAX~sg*aX$E>jil0A9E;RUtX$Hts)82BXV-M=-HrrP&%Vv?+Hr|Noe}3#{y%v;tyC6LeZayKc z3qcC62SVBAd#8_^9YDOqdbJ^c+v({WV^A;&?EX0*&gpsQ%RZb+mNlnR_@N8t}6WKRqw%sk~5yg5m#FbA=o1qTn=EHNBIe?H)w_b$Qk0yU1 zi+CbK1!Q{aXx>m^aCO& z>vXiw4ID;E4iS*ynkt`aX-N*XXtijWB8s-HGT0m<8&pcoYY3kEwiI5AgcVQhoIdG; zv^Mc28xq6gUX^=@duLg{rZ)wZ^&!4d%9>Ij)erLQ*75oIEz-|py~RmwntBT(Pug=h z@abTRf(MYdxn>Ai}STQ~&WR z04ND_!6mzM{!yb`Q%lX~mdn`34^;?S-*^<}dWH1Jj>1~_On<4J_fnh1lvYKY7wohr zuAPS58eUt+1=i0Bo~Rp=*vFeQjII4%gb=jA zZL%In@mp@^n~*`JblJ+Q@C*1Rr)&4P`w3JTp#1r7U#o8dq9W;^`GUSQh%<#`9lo{>yh@kT)Zc!mI=7?8t}RT&yx#G+M(7 zo@8#`qz}`amWS1>!d&eqN1DRPtSxK!x~0A%S?KV&H~*GO^Wg~qjdwD}U!CU=OWH${ zv>WLPt-ztax*ZlDNoFj11jx$;T0bm{|7g+~Mk zz%)9MUZw9fWy4ps3jxr{&qIOjecWCP0i0iDjsMeEh|r%G=L;h+3b*bBNvN2}Tq$|{ zjJm%lu>}NBe-z?9PEQKg#2>BxRfhZ$VKl8-J6p(~ajqOx03*_9tv>%zbQXr-KR*e0 zyf`#u@^{EoT5@uIw%CM!+v^{5FAr@I29ISu|Dc@$`l;d-NlceauiL8nO3>G=Y!Kxi zC*(o{QnuwqBe0<6Oq})qnAksF%>R;WrwxxI`Y4~qD!snSbF&4=H%foMmm3LwL<2+z zH0BjrlzyL%-zqiz@xQJTPzfWJM=do82ip98C z*bDXNA^h{}PT_za7^4^=f6g*c@&u z;0BZkXzqrU^+Nu=9smB#1q@_zPw2Z&X3E&WzuK2{H%6dDRLaQCU|gYRt*C0ND@&V( z9;XBK&TILPOSHUDp-Ap5m%k6@Ux%Zc@HM(Y4oMKqdz|%)!p*}!_S=8kZ#NGlo9MLo zY}sXPFYLf2kOua3rg(yAeplol8|$eC?6^TN*0}4lRGVIZ`#>*9Af)?|nD0({G}TY_ z^Hn%1Ar5`2)^wo)MYH`{@|?}Hi*^d!U;pj*V?cUS0VCo`wx&BC$>E6nqW#a4@ay#^ zec+M{&T-l9aAG157vZtRVbEnSRq6Op73_-f&!@x%V7<=!40o7NGtVXdS{2%5gK4~> zT}-hHhb#uI-f{~HN9PY{UWy(EweOjB3xmKw&;X3k`Y3!)H09-kjK)X)`+0Mr11TaR zVjpw5-n+?si}14VGaD8WdD5j zCqW&cj=NijAs7V@$<8({M~7H%PzTtt&_xjB(*%`(65Vff>Y;~+ygR9+?6j zBJXh-sNJkJSYmdrcFU)C!Ubvjoa7I|T@I99brB57tO}#nJ3nIdruXl^v^J=PYknXD z@s<;;y4@SD)w!iu=#%=t`o7gx1x*kN-{NyFPNtqo`&YyMizPjy@)}TLlti8tPG6|zM`pii`#&75`^}+v!o6~;XWa@s1Ma>M*W?}U?dz;2?-qc?^ z)bJ7uuV6pU#_9Ixc8HxLZmfUJr*VG*Yz7XiWOcltUTOk04-WLl`sM_*-N&9!#8dpU zJMx=x29}6)Pw>+RCoq#+%L`bKJD)#^vC>h#Ia@GtkB3Isex!%zZfrhZrIP`_lv^0L z1G#4srP@H(S&qE5PCZ>4Ejo>8*czFb0SbW@I6RvWSOUi~rNbGK1N3Qt2*oatR;}7% zY*=d8n5Q)m;A6F41;PY$biM*1aINt#ivKvXf0%Lrbh}hHxkkvTE#^8Oj}NLpu)hqQyoOeCBri+N2?hVa-{&Cs<;W1s9 zLl#9KVKF>hnQt#jlR9Hk7iezHNOv1R`uVXGh<;~1bML+T>$>~f0Rz0jAtFGcFO-WN zHaq!mo7SHO;g6H@-!DktV_ujRgqAq%K0dLib2==M0q8oQKQ>ovRF-+ca_e_rE%*_$ zAMx-MsNwe&h`mtRrO&c{t6s13>(xvHcK)Bmoz?oEU)yMoe`s;qkxpUqpS$Y?JsdVZJSbv-gRiK4012soJu6Fn+0rBn1ID=MS1?yQWt1>R96H*x< zpWcduutdmhz*pdm&2pj~{P^Lu8{*d#u9ODrDPdrxy;Ipp1Gu0$vK?V|ZW^Ysgq(IC zzlaSE1NyO4(phX`KN@I%f~BU5H1d^AMSBZJ7KVnV01c*0ZdTBhV_Px!Y_QY$ViSYr z+0W{5_LBytUW4WDS^y>93sr0J38t?{0M?56MyD7ipF926(w=RKw<5);3~tY#2z0P* zS3328djoC8EXeWul?F|`Q1h=)oi1lJlMMKy_ME$)2cT!g3M6|jb?gVMws^@wvKFSW z7DkQW<}_nJQ%0V;yM8-B_`cV+{^OzM3y9LK46CShd^LEf-kfF5|8hI@7Xm$?kVyvE zXQEy+)a@;kDs@+b&5FG9{;)-vjm^$>Asws5D*JcKTW=o!tq<+Dn*3jLxQaXd2{=lu zSU4NdMy}0{eW{PHAJLcU+=>r*>b1`2Px+=>PjRoVcI6IB&SKDJ1-6H9m<*@@_5o0n zH#@xy1&>{|NIoO~o(`mLC&*XH+RG z5s9w`bKo?6flP1?$KSp4WvIBPU03=zw+NmC@wE zYpK;V?nGk(eI2*O-+9+pi%lWpwMGeNEMmn5%J(^+y>pe1X1xQIbp`@xBy&wEtgxm?UuRy&>8SK+KbWq@rwT0kmh^)%$uWq4SKb<8rznh z^@EK$kLvQ%=6xTWinyr=E@cKG}F%HTYT9^A{sPi7dXgWtJ zUB}~3DllAZ%{vc3^7@PAQ_pVQ+e`IdNKgM|R0`vxnPX9p3S4bOquo-goNm)8 zEr236bGyn!qHQ7roWDrt`MU*C*eFB`zLlijCdsvV$mFm}-RqpqdU2js+;L(iAdiI$ zl?RMs0vqzWWjqXDzDO~HE^1$i{k<3nuFS^v0t6Hf?RT;~6S;;pXaiGzEE?rxnqGLd z;J=qC!3vsoq(Y=IcUoNx49HV$9Kgi$T%ewg)sEm}?oyG3W_B7iQUz*n%v{#+D-}s< z5(1>P6hCnIp(?y7tA(_s28AbXP>|cR9Y%o|o4mnf+;c3|ECf{JZ(COdyCzZ{k!FsSl>G@G@XWTBx)Jq zXbk6;5hApjRt4vD`IvYj2fqs$f&hLI^`}Wn-pEM$* z2TPy@A4c_R1t{O&pZaRB|F7l9?h0j1=5JsO%W zCrkNJuC^Ph^FQ0BzR_p#`$bU75wuSWy6i=Nk_M9N)zZu68UUqK1`S%Rcu|-u>6?Qo zDuwjKR(o*k+-|d9u=&#aM%_hY8xDHSo!(m5a--_jC%-iz$4vpiABRPK#W12(HCMhi zrls;mF>z=XMjToD5@`xj^Xo#Tfy6qKmh5!bN6l(K!;;KM^mo2%`OO8Me4o|7KR~Ii z)Y!^r@EB=UFOdS=r{ppX!P)W*G-AObEx6uKuu`0vDLaxV@N&)7l}IX*W8Rg!wa#~B z*23q{APPVuD6!mH;-@4wcuTAQ`5{tm`qOoDoqbZ_&eFlp2FyHm+hxF?qxl`)m&UT|kRPeG;TY0<{LqNQVBGHw_$s@>SB1M@ciz-t z1|d@61(a+7HC+{NEz75m&qNyV0Z&n;LAlGGqg1&w8XDScQgJY?9;b{N8?NEP^m`u7 z2MQm}sG06k11*WUfOio0UTeA<-+B?v=fL;+nq|~vNVwIr_YSwq4CZOpIe^61+IrId z*X=%QxO?(59qt-jdR;~X-p1Ohy!(9`737MaK817FN7c>5U^OwGO$>%@pvuK`frOMn z<6{c(tc!}OLl@YcHEOTxj@S&7VROAImzF2cOV0B&$9mBN`;xtO3^~M+jPGr#9SSPm!{%Y()mdG;Gn56X{hUEvD-7{& z`dCi=(u6}?xV!De3HlNYhSVsG{DQ`808oa>YD)Aqw#g?GaJp)hywm5Z_3Gn!hh(Rh z7DN8Ds$yDHuS7x!^>ADPof`Y6G=8AQx`c-nJ&B*Pri5o?H93>*_lm{^1YD2sM`--}OVYA-NRq+OBpRf`*cymFQBlwI` z=uJw=7M~CVqjG2rM|s^9-^L)EWWb|c-m(X+&I@K1F;irEW^&iM$wKM5kx6%3yDrv< zbjfH?)i5K+K5{GeBj6ZUazX$UiR+>%J|Q|3N8gK;CcUB^_R6nA^jUye`O2}HnkUXqU_Oc^wb zF&|cQlSJG3=H&qLGhE?)LaQYV`dU;+9aJplk{HgjenXUQZJhqN0K98 zw_@UJu3)aTmOA*^N}CQJ!hw!Hs^$BozoxD*%Bof=(s{0-#^hlrlGRyT2($=T@4>=D zm`hu$>=$OY0e+nt$54f>o>RU+S_!!eaEvSDI9?v=CX`B;2}By}qHh>_4D>xC^8Kkp z*9~*}!G1x4a~(x1qN)Pvt{f*e4Fm?Pp=AVf5IZF^;EC{0NTxB?T*eijYrwz0(C>cw zQJ><68a+ea13A5;{?HN_>&t8q`O&t}isfkKF-#0}(Y^k|u)Zo-nldKcZL*Z?qRN2X zBdDJb_k5I}cCObl%je+n#e_qY#cf5~R4JeRT5IJ71iBKwW{a|*)l@@vVx_WPRXMw` zf}ZOKJHixQ_&4otF)=KjM~@c?JJU^WriU|+d}=A4E;EAkasSnY@#sVB!)>hb}y~lw+g_{ z_CUTfmHCENF?Hr6S{WqHK0X_Py{%~9>IMgwTW)*=at{FozgqFH_Y zr|S~d0oA$kfviTri5xm)+jqO|`tdv=+F*PWIE3Eyb9HUe?fc4<06YuC8CwMNC{SVL zE9r$W0ScbzX)llUq9peAdg^t+hJPJ81D@NaEi4~*M8aM-|6G{LVAeV8ZTazDgty5B z`#G8wKPl!Hu-;{_^IkZAoq)wp_BAx|R~>$J#0pz&4!jxDW_Y&(&dz*Uo>ztfKEg35hFraL<=JWL`njEzOF{w?8z-G`uYxVhVVyFn~vy)w-=Lcvywk7 zmRTC^G5Tn2bW}C5k?=MDk6S1yEv9l0%r|xgRltHfF*ujvURt&}vc_1C9sOzFBAd#o=>>u0#2-%?Rma4Hc2F*eKc|jIp%N zmJD4y6Za2j(d_$!?-``XUfL+J3VNt&H>PK!9GMT}Hx8pOU8?a|J@ih?)SVeP!lzR5 zebA>~#WO+y0@N7!{~u*%9gx+wu6rp->5`BJ0qJg#MjGi3r9-;A1W7>}l0ZHlZ z?(VvSz0W@PtR2UD{b%ukvc7MQImdY8_dKs;u65yzm_TV0&ApF)@WitY0{(~GMg@YM z2FHQkr;t#c)2VSD6ZQulm%8`(>GnwWL{$`h`^=YM3b-_DTC7lq`_etwJPB&JArxU& zv|x9OmsjrJN5oq%_66QN#f!=VWFJzSRZoL>1#st7bsyyhb!*q6J|#N&_7Gek9g5(z<{UazpRcYVAMOJid)m}-Va8}DK? zF8R^$Uz>P5QOlpMdp`P6XgLUth7M(v-SDm2Mq6u&5R42QRswiGZX{mOG|?)EE@D`TEpBI;QXo65O>+fBa}-!9axFsYE> z6)Kf%X~$SS@Oo2+AiE;bfO+Fq-H+VB?$t~z*6wf~ z=yIbYliII4Q)Noy6_H2|Fq2640NUJ5>XsO4W$6%FCUk$Y3uyeo!67un%w}(r^j|f6 zURAT}fnjZs1euqDy|BSW{V&pErC*LF;iy{(Yx&yqHe3=!-hTx3*TybvD2~}*2H&!O z7OGiOBA~s}?{?lO+EqJj=v(+(QdHPI9!RP=&Po|n%iHgPWd86w2yN$axkEgA{8#u)JW=0D>ve>y*yEJg zpqm^#&XRl@pJnFV$*kZ2F66U9a&{FAW97kSF&b%)+v)*|kJ7W;nI^q?+on9}8*nUX zHBEL#DtoBa^P`UUT{22>HrWw`0`ryD)~j2?OJGd=r$KtZva*9A}zq#Jaot?jb1nJZRpCoyTfnP@fD3*>zRtzG|{2S~jcd zWx zw?NWYtvR#+QK;o;6j##7ol5B-C9d4zj)dfOn-z3-XUOrCoLfv)YP08K&Dhuj_XjD@ zopD_-j+q3+95GX69sD(nC=zUp8z%hLZufdvbsR|PFFUv$O{hf?aTpziJzAWP--@Fg zU&>iP$wgY)9|z{mVOjTLI{07jyFPgOPjDB zx^?Lz0&7)X-}+R2(}>0xt&Lj(tO-pQs}s;KSx3K27SECc)bagLzhm8}({D&bTngVx zv}i$ua~i+Y6W?^r$89>Nm%%w!^T}()+r=I+Bc01DqyOgiWPQmzhEj%Rl;qSLYr3S& zbc6&yRqyYo^n~5g|I(@cTkT(j0@5>8dlfhK_ow3LKII=mc7Z-fzU1C1gLua`iZb0b zHbg(%O7HBp-ue`EAM}+bsj>E|xa_au`D3)QS_GXRN@souixaZ9UF)MF6C?QQch#ll z%O7tHO0L!(?@QAJfT+!^TI@aITKVJskbb#HQNM1TSxSg=nIZsu%G&04~`J?6VC5@t_bBAJLmRswoLY{$5C8p*kb1D%5i`Rk0`1v|BoXC-nwt~SI z1;d=)r$X&n!s(7W9=+eg-umz|ej%vEU~b%wx)VExM{ZCSCA@CC< zxlHou_mt?AIF@#}gJO4mUjWJC`EK2zy~j!C1?Rh5g7d&p3s9SL%<;9k1wP6n-S1-G z7}TU@K+P&Y+Wela0HW+IVXkuHGMg1+i8R?bG6o*o$ysJCSWejvGgOo>xHED~m;sj4 z)hvbDwOWfd;iT=)p)oHkl0rzA====PhY|D|F85GQO`o9R*`)`YnBEmIrki>1@R-^D zic=^b&23}w^nHaZ1z{ev0_$KhU&+tcxT?qLFzbY|8?D+EY}GZ3vXlu>%sa(|d;+<8 z1mc-tNZX_JtOUVM?!O{+vW+9?Pju>{UDYH=mQ88Z8zT=+E>Z+NwCA_IcG+)Ng%Oa* z==@1&+UvlT%|WRnA`s02bei%Ff)lQPRuR>-X4>T6cjlo#@62DIUuy+_Q5|nf?(Z*&AOy|bi9p@o64)Y+w0HiBD_0fNu&5t6t5i=ITJ7s-Z; z_rJw~n@)PtWYM~Y2xO+w*1U1#IqKQNN>+i<#oSNV28kXstBmyJrEdPIsq&}{O3+rT zR;8`67zH&2YZ`&alboV#bR|)EZyRXrNT#XJ))nbNh;|#!s*!z!6CiK*wI`eiWW3XE zxf!mX%D4qN`|$lhYJ-T%-D$}{GYM{ z9QG8d!IWilcF$#bC6?K`joAaK@kLqWKrcH&*eAg|jD2`-1&erejJUSF{GlI} z0OHv_sq{^t%xq;wzXB_Sao3U6#4}Jjjw8gM#x{p_Mrw;xgPMQ~ugtG5#jq)smQF~@W_82B^Ut$%0rdiPj z_lu67p{i?sm+z9gAko^#J`2MvZVu|kP!90)3iMthltIn_7G9gnzXh92=504Jos4DJ zi&M9;`OQ52d%Swh;P)y;*K!dBuHzwHdF^*8#6s?084ZC$+s(B1>8oJ@q}`diqV0sM z^x2^sbuPC9Uw))ERA;q!TMVcD`?_zL2vbp{|A<~|9&22&<`0zv{1HpYig zIz>^Za3Lw}1IFlrGkx5!R5}ocP>S0+nY^fdqSBhvG%63$7wdxGLpHdc*Pq>8JKd+Y z-{xncyZ#JD6DDGLgdLh4HI~a#s6gh%>ju75XAX0fAA%}P7iApxk;6Gp+|p73@1b~_ zy|Qnv#pw0QgTHit?40MmKjWGEoI{sj@^TEB!7% zouKua@57ANz0h@;A3nLdqL&3iI(>gCzZAbB?G73};h?z)u|)FgA9M8{;*)Ix=esJS z`pYsf`g2>;83owXg0m6?; zozi#{TDXnBo1VLZAnMG+*V>M@kksf4!GxSfZY~09u!U8l(n{Bh@O-_(-`%{;4?8Sv z2v+8&Yo}+Pb&50F7MYmfTyAW=-U(+jS5yr(EY@!Lk@n(jyk1n;#}9vF6Gyl!0xx$F z%Gt5O>o%0W`!wKoycD<=^{gEW+jApk^iLmdm>~tvJQF^{aIds;x+gVmu&LA8juy>Q zxKCsTm6qYCH}6>yGZ!QhSw9npAV5DW?RsHOz3jV7iY5;AMzz`>Y41_sy3h`V5DR*k z&Y(M-F8IvbDM=sI)nj^H$#8OoN4XdCM6<*?%k!(F#`geY{%SLn<7oY~N(*us{7EK9 znMJU3q0R{&`I+8>};m zzymmbJe)s+Ww(rUr0s5cb!|0bVX`2$Y-AFZuGQyx&gpjnuTQi$Py}l%*>^>R=MqtR z^csTPU${oaL!0DJZNlYVaj1o04wewM1WS0Eyg=nSyD3Y0mBz%eYt4BNMiS=lW_nQ- zQAb0M80Zn`RTylunvUj|IgHv&KW1x+Keh8Ae>_79*9*peYIAK2;L+MNyUi}mf$Suv z(nMt_rg;S*0RRL>ds~40!f3Sxk=(0Ui#C#r-$-q*bp!$;f>l zGW#Ks9KW0mBYqwOWB79iztIxCS>@daWmu2HB`(HP{MFel41=#Pl^!R2pOY2&k!U=F z3MSgf-9)`CpuGS=g9ZU)8RQ0B#VbGBd+ynfJ-SUF+D+g*%Xcm@(#`i4>;zNuDxXUf zFdCQ$yyRWN33d8X;lZPcayZMh(`25h+{$7Qj2-C+(;b)xM=3Ugqj^uN(ZAw?ktO&r z$4wecqTwx3FpIOlu1aB1YP`_cg?kD|@!(_99!wA1C{js8gwwT%s2gtG;B;|HYsq|UMVlFR)0<2LljFmk zJJesqnokm#V2V(m+QSjTyzz&AMG$X|!1Zatiy&RqU4+G5;=-xFsz_z%u- z+X>B64Az`#9!I{Ojj^DM!y0BMn&bR7VcbS*;e38ENIMlB|36`ak%BSAs4pMHOz%9( z&6M9vcsxP9%{-e;gbFLz!LDEJIWU{J%1Ao8O^1EKx&BI>&T4_9diZb`i8i#NDe2l_ ze2zPu;0&TSZ$AWB$SW@t<0U6wpU#96ESaUHn!v)^bRlh@bz|Ju&A?u@zx)zG8|c=b zaNDo5c)%-Ha|qpA3(sOdX{pI^k!u2xLdqv(d;ZBtLTG7VH`us4cyQT-V1fHNY)j1| zN(nxX%G&B`ILQr6`b@3C)Bc9Iyc)WJ{9kvms3!r&ANmN+U!MgaE@a}1-gxG{m9SW- zS9-u>78|O)&lw;T6AdO+Ox5KAk4hs*@|iQ`s8+>MVm4%UU2a(S7<|zM6CoP?(5Yl`g^XME zzy2p~?!Uk9Z3m6}sf|mv@Iz2*@^;2rfD~2~s7LUyky?EMGvC&)euSYpK@!vrVdSd) zD709teXm%sNo6(1$uFRT%;*kp|5)y~B>abP1_V1kJ+j{I0X?1pO}s7d^Aw%0k@ixd zNf{u54Iv?!MHb*~KmI>muO(=R><}AB^n!mr(Ej@a{kt!mgPv}c{(+9h&s_zqUXE-k?)$ zx#}NER)1+oLr}rV*DgVmtC0NfA?RO!dV~z#U}HyY(|_E0{@r!w6arW&6>%BDA0Fku zET*^9(;Fl#-i!VJy6*7capi>gto)bN`0IlH>yH|R!5ciZ`B3uzb=_rAzuUCIOBB8Z zye1(e&+>N%ERyJO zEyvPM+COrN1C2pRa)&BUSg+mXxcNzT7aM4b-xGlD>b1-ZpG}ItuEAfI5v+L{Iaq%= z9c<(fXfVIz3B=h?(kXY@mEG?FQWHu4#IqSMj$cPn80(7;Ntu(@P-J6MmM_?|)6%{q zF$zE69@Q+(IL|~=p2uyo;B47}Ewp2F{?^{h+V%ioBNHo$UMeLudiJ-n-{}vpuAQ*g zs~rJOQ?iSU%gQ{qEUVo-+6`=UFm~cIe96S+wj5C(K!!V_FfQSMbco1n3}}R~_opjH z|9aW~@*M!?Vba&Wi`)kfrxs}>$o?dg*ki4dn1s2XVDoqPQ|6UUk0jR*Ii5Fmz^cM+ zT#J4P^r<^Rf>ty1VD&NX_Bb{W6y-pra|Mo6(qg*0Z?yyXMaYF<_U7EqS5lb4<1DPr z;n1t+{bU0TqRQIrhFDw(*|UaAokxqinokAA=EFWSU=&0Ya1xWh*ykaCkVMx6)QQ)o zY~%rkAsiBt?f=H~{^Kqq6#x$j=_A_)l4L6tJg~%*nJA2>_}ca2+XuuPXZJ7vz$4S# zE)U!qADu?BqEa-!^%drkWlhS>^DTHeJK@rPl&02VEaBhpl9_F?1@{tyOO;m%(u{CQ zb6(xyw4MCjoq+_<<-GY=4km0iJ&_BcwwgR*G%=9Zwt!v9=@c4D6Nqz{J<}hK{1@K* zU-uF{QSb!N63>Bq4Nd?uxE>5{b^*we)m6%vpRup=kGtC}a@Vt-V;VXIUNyC)qF^|R zcbF4rmqeUzE)NBcmST_Yix)cQz)aoO9M<#SENDpK(oN%M5BP4+tsWW&5phm7222+M z_GaveGg10%L#5{aANCz8I1yy)Bn*rXSbyKyx}lMl+ZQ}w*FiNsoVLNHQr?G`o1&+} zc<4g`&WJ)SW2TMy3FSs}H>PqMvmzv=rHEF~CEjv-SW?Z}UBJ6&>Qx?t6f1+F1>gdx zOde?C*NgG5l>c8gA)t!DgY=C0NSPcg3<>5CM+0dQT>EJRA)6qmzZ%te1`RIuX1!C* z)S5;g$x^}(byaKQv1&(Bui6l(vpJ3iXS3pyczUzWWwIEcvnS`OgwnL-a;e<3_cti9+6|X|V0`=&RIFGluj9ec z8S(gS{-u8`ANS3%mls^}+6O6|I0k-{X5`o6CO2tb+YvG^1vVH6!(UwzUg>H5`g*;q zyrye^{a%+vn`ter*$XLlAb+81mqX@f5&yj+SHI!T{ei9rCB<7sY+Nj$IUyHT*7ywO z_5AwL(M`T}p#3YBED88v2%Ak_sUf_6s4jH$V?Vi@X4(E-9N>N>q^=bEUyv=<;@=os zTi_Ixz;FJ;Vy00Ws2Av7j^rqNY(%}9=lL~jO~q1GvEcl#yeNgt4yIzJyr=18wR-N+ zquA}i;sa@Scv?&dQ8U%PauYD=?-3}NL{t>)3?Y1nynj8JYjzy=9!=t<&+W(Ai}{RbR-9_9g2a^KZwmJj!VbWhv#XEd_F#w0dDVCYW`Dy?NEuYlqE0Q$KN-J(}X%+F7T z-L7}Eszsv&zc;e$sVa^~3IH0JiSFNz;4nIK zjB3B8P#ttSudaC%N({-`xsJ~~ILz3&u65iGBv(3oK1Wphn6I37HRD9Nz?LyKB-VI% zY=<&r@!-yt^&Neh)m(9M`F_2ZXJ}S>O5hL2y~umW;S(I1^ONx<-Cl57o?Go;K9q!z zElp$<)STshy_t3T-I8G16cZQ1N$?KHv|b>`9at{l(Cd6_4B(gF^rZHKy(0zA3*}rM zoH+_-ilClI)jA&rF8gi83;$bPK%Lm$_=EYxTyF5|_Dy60k4Lfg zJHLAi#|s7?W7NL8?tiP-I}BHjrnlTth1IQaINxzFErG@X;G$8@$IT&)zKBJyA3yQM zvOrTsat8_Kj2;>RuwyZz?;eSJ!y*ZYm0vX)Y!WT`M=$og#2t4HIfac^bakHpRXV=x_oT^nAJU1GOd z*JQKOAq$vU^z4~tyv=g3iRHT~Q7@?~R3Z(TVWZWA6CwVRH@T(6=dZ1)Dv@+CUzywL zDs2;ed3)|=I^Ed3jVi*7x-(VrNvhV6-oVE@L%X{K=CYa2uft`n)Kjs_Hb6dTQ8q~v zl~1qrP(boD`&_!)OL5W`q_NTJ@W$CP1o?+A=N=~lvG!_p_u$F+A5UPP6b=q7O%Zi+ zX{=f~`K852LRmK&OT+2vd=#WTZx%ft3-Y8ud2X%0tSH-KH%w|gamxfwmqww-Y0=%v zLk-;efXp@Tw$2U7|8BKU!wf1Sp9wI_(6yq+$Ia@amK6QaTQ(1?{ zK_Q70mDhiq+u?p;YG;r2b?0i24Cu1Wa?o^GYk!sH(3IFL`)wad>#4uh~ra!8$Bh;8S5C zgLZka23C{u2A!6bYHg|Buq~fDfZEqP5K2@cg|FmQxuVh7AbcSUGd)YR;G61Q_gnC* z$TmP%P_g9`k9sk|XE@qdsS`jX18QH!2gYXSZpQ{NRijrYu?5V)Huym>v&c728G2F zKgpg~!Y+Hi#U#-{-vK+6vwTw#Xp`9=4R-}1&}v0@+f*`{ks2N-;;*mtVb}@6z)Oe&^Ms+_^bj=SrjeYV|Oe6?wkbR(`TJ`Li zgGxz!UWQye9#7e)-3iOQ3{qDk#Y@GZ=h~Ha*oHcd7O{6l#g{3q#Me8!kH7NQSt_B1 z8sEVYAq~F;EUvxL7jJK*8}9!1!}yK`jQ4c2j#!)?c1A;H3uBc{pde0Y2{DNt#Rk*` z*_#&mdWIQB$8R-iy{k(qz_GP!f{qFkORfBVB=@pEDuZfmve{4B=(EzzLcT&#bThx0 zZfzhc{hmq`3$br-2I;pc7OhRw(M?2x-?6l@leE_iTD5P;-jAX3;-I3RD^J#54(ZPB zw&(OV@m=OfJsU3*e#d9Ll@^Fhlv8ue+l};@)7O`z!?$ml@!)rHUGb?(qcfPeX`Bu` zwd?yE>7h+QJjWhuJyj|LiZ;}YtI1RJTCa(k8?F9}WKGdtz8}#r@n#~~8FW9lvs&=| zaMPr>`{1pYZy5Iq{Hk2`+HTYjTb1aH%N{lM*Le4PajK->36s95i;Ns!@C@x9Isa#6 z;NNqaqo-QS)spD(MC8t7L2&@$V_xI|s3*-x^%WgrIG{IntYcM-D1%)p$>5X+0eD!Sef{G45 z!8PFO3Di6}S{5cW^Bicw-$TGzf+plGtwCn8+95WAqP4|m+x@O2oGBIiR{UFQjXqIc z>AFG*#VBQppgUu;hB^83Y~?B&`7mf-#<6s zWSC0iabJ#kypCI9eAF!%!@j}|WFki5CnXcK8Tl^hHeL52VBj^81jmyI>$+kwLc_@D zY~Tuz@)3ybpa% z1~(M(n&JY9T6d<}>Wzo1mvO%DuJ3KNSjx8>k3dYgCeJ-=sVjZ6C1L!9RGz83!yqfy zE{SW%Wk_h)miv(o-}d1QDu%fuZ$2wIGu*h&yOvZHy1z#Z$AT9i4x(I$|URghuWFods0+B8X5Ndp(>4a zl&VwALA*7X8g@=QKMU2*OU)f5R)9nmBjk+i z4&N(rLVE#&?5P=uiJ*^0_Z`K5FQ|0s_$yVpFgy*xOO@QDoO#Bbl|~5+2p*S{FAwYw z5TlJQwmb8aq7L4;c{MA>fCYt%AuhIIEAlDwY*NQgwOed5Zb=O(8sl?&Uy0o4bh6fa zU{eofV`8{77f29oq{FbzWRZSswKy+9aXu!3Ytln~d3LjHo@9J;kTl3m2#<_+9u_hh z`+Iw#=~g3#MKa4b7@xy_ECNN~b-^f}kcIDMs{ZovAj{y-|11yx`#u#c^+a&IRmGRB z$d9GndP%13U-iEITN%LpD1(0*x;48ci!7NV;omXRPFCB!{yFU!U zQVRFf{C1GSn!VCaqv%i97sJ#TXZ9&VW!C{Usl6-BU zu8^QspDmc*wt(@h8tIvc54!>d;`Qw0^;)g@fFv#X&pML+~c1 z6qjJEPMBb(1j8J&KW)}(@}=;>OE_BMc18|i!Bg&KNP^LeE^95fGjoso<7B^#jEK5t zupa(ZFQDbaZ@QVzOf45u8$LD9yZMcBt_>yiy&hSteI?=Mw?%W6u+$^%k(>KsqM9o6 z(VZqy(iu|UIKnYSC7PJc>TRC3XtqZiZmnU z^q;i4JYRrNX|~AkXo=Ck=COLS#BtYh3U|*&%=vhC(pu_dO>%#t%Hdf-_a)76hip~i z%kXN!^-RBvLC%&U_Q7uyavRna`E^QMj(ckCyPd(uQmaNfi;d+xdjq#+3xj}eb%-)0 z+Q!xcZUZc_b@dQI2gtGYOFhFFH_c2_WRpz=f#cI6)!NATI@ z7nd81GvKK#f#qY|EAh^7htr5G)V6q*rIe+A>BC;mkYXn(bFhNdL(@gtG9l;e90J`d%F( z$gIpHzl~kE{miG0*k8G3To3}nOvfqf3k!AWZnW4A=T}FC9k%QJAGr^D18WvsioXO{ z{-r|rkNVpG{U&ib#!=`N#?n=X*!N0}wiM8@Ak-k-CdK0@%;EuCa3gZii%kO%s=eWE z$^s2}Z(tK#li?)~+a8cqW5tudacpSwvC8x^_NiF7HU<{XDi^CaFbt5YQ}$OLYg6z! z0f=yYi}$m-&?Nm)y=0^bHPeRcl^m9*6DcDH6(zz&GnbuQ8KQ`{QzeVFrrd1FMT2wJ z;t{E=RmYvr(;<;wvdbIEBI0@F; zDyk#f=>$g)8y=j#jc&)2gtSlfp`hk?h@s`h*sS@4WsJZhUS7>=*JrwY0n6gW6o5)7 zF4n7gKH53k%va&t+kakCRLJvY-;zll-GYJvrc}rEk!^Rz?*Ki^hwS!9{4+pbj3@XN zaijMK#}(tm;f1@|*+bq_yH9^qSRz0O==TKV+7_MjE}H=Hb|MlGwQewISfSIuQNtv# zY(r&_7nY1%qHA(n-`N#j$9F)d47OefP^|&fFNLx>+awxtX?q<&d!p&gz0qHgE78ti zNTmD2e^}kvA88oUrH|;~ZQ-#^pJgee=SZ&GDDc=H7w1ZU^S*dkdh?6;SO^#d`EG%i zivn2Ty6(k8L4#k)?ld-l&xQSJ4>U7@ql08axUTsoZ#tR#-SBNRwUXK!g+b4`(=l8ovy08mT^NzY@h-~Ox3v0KPUQ zM&#^NWj)*f`eMe(_o~FRTI-3tof@>t7_v@X_-PX4WZLe3to%Nnb|(B zh`=XQc0Y_=%vdb`3Y0kTMSnC~FCrr;Z%DVDB_LLsK&)!im=zBsuj4S(#nrdRqo@g~ zElJMSnl@n5eIIIhxJzTr*JXKsxp6%$Oz7?hv)s0jG>Xq}n~qIq)O!_f`<4Mspau7b zY#h7Hj{Jv(Hxkzu1u+zyH93bI#$BmuS^7Oue4zxK&hJA#dFixTaZ$&C zQeJ)=btvbSVA3!7T3Y=XpCeoW*;PdBcVfdp zd-h!``ITo*g&@0R)*q3kJM$K16n356{IpI`FfL^}1uB|f>#Oo-_6$0*E!q1P?e(2Y zFFOg+cs=m)lX!fDDBF5+EE8ui>AovCR|NU735t4fy6hD0EmR1M)pis-lQo6IVW-v? zij%eE^_)S^e{2z#i3R~_iwf%c@z<7RWUvZ=#75+2%&dON<`{xRG}ldfjzUT!SQ|;@ zo{f^_zy1t`X8?aTSxapFY4WgS7JdrZ2wj)VOX!x6-TGeRwi2-H$5GPoH3+h z9slrGKg7%R&R?VDhMPJ;o2=nve2UM{S$ay#r7S+3O-Z&5Re)xf<7O!^OyIIvDkYbV z?je62`udR9u=tMhe{Y)k1ivNTgP$Vn?dOyYg2wX~Q4y>U4(JtvDL6TXeTsMARu!oI zNd8rJ3bMYFrM3=vhscAaQDog++rs*Q;MTdN*M3DBO*$nu90Gy+ppnxz1wUF8nljV9 zV`C|1;8>ud#?@#)O;a#Zy6@|Q*50BNcL**P6+6$9x5*Pa3#=LPQp(tA)v@qay^ik! zKp*QS${nc9vBTBaPCsiK?wL{73>-WAHVuTQyk;%N$;U&MKK)oLXV@K{6}pF{`=D^S z`|GQ5e^Nl7V~U3Inajr^ZBp8Y>&XqS65SSRP=_43oCUrTmJ^@e!!dQA#F{%)qHCU` zVm+&76H(JE2cdqE-%toZ4AE%!mkMi2+5 zG(U8UAujgW3u@(d%}Tv56;}I8n@~etl?kU|2BFq>TEaBAxT#cRJ17@X^zeD|2MbM9 zgxp>QWD4Ks=8on#%qE1MaNuMfr(ye^xJ8$2AzQycv~@{|eYR{k61_;52sn*!;GV2| zIzwJ6J!z8#&UZ@OOyoK26X6KF}zm4*(TM&}>1$|dtpHddK^?Kg73cWRgNsm}un zG~2PQuf1C#!#7cAIbvYxFD$=M025SZpp8do$xcH~Sxk4pX+mE_Wo%8DJl$Me_iBRO zQr@9Z?t~YoX8YoKd@s~UX!`75_%#Bx0`RQ84YmwI}49l8$=@^R$+m(s ze;pitu2Bo||N!SYL~v~fyGRPl{S z?XyjKm29_}Xo~YVr;6uWRvea&45T4B-5dK4ja-*Ga%tO6sQx@a7OE!w6P0Xj$ehP4 z+-055%`X7)`b2%gV>~G9b$g?wS`FI$Gc<1k57gmq#!PHr_(9!tD_WEG;jA{#_F@jE z$!mG#!+qnENWUqfhh)+I(1dk-@yQfUN5Eln7NAg3^t$)C870KA&q*2IC`1KoRBq>c z1rn!pQ5E4O%-o*v46#aB{Zk|EpI-_>lP?)ZQIkT-dJ8*-2}XB*&RhvvudKl419hAB zn1VT#2*4`F{_yjRttPBDFN1d|3btA%>H0Zp&spIj2- zdcn}8| z>EKLZRKA>;Yr{aZLCCWg45rbu8Whv=h9cVbBev>GSk*qIm)?GNvU!?pvwX_nRmvGu zlrlmQ+Uv`;dPV{cdS=ft!8VpAP53wUf5T~q(BN8;`cmmarC$k%5G$5fUsxt>r=fL- zOGip7ecVOyq<>ER1KHE6l~@g*t1#`mZioAIit(4I#s64R|9cM`6%GD%NuWz3jKyd= zg3t4Fv-oU{6320QS^Cko$S}|-p*0?U#zdeJ9Qg!{f6#g84 zC8sJAh!q&SQ?X8%(}$FKG4k(#cl|a&hnF~Vg_{n;O9ZlsST3nC!#nBHaqAMI26+A_ z!D^88B0M&XP@%sBXF=Q$Y9>502N*|~5b<^PPwO@eC(@_%-Cu=PWR%Q{`du9Tgl3*n zqlP~2FlE58PCZ`Z4s)ItDG~m|yLEXK*(h&Tcp)c0;n5cO1&K@f3LWzSiBfEqz0s9a#?{MFj} zL~eqZ^jF>9!8K|%kvp@I1eF>Dfx;W$M9~gSjgm^eS;UtOR~GU9wM{Uo0j!F{Z3qbs zq~hBrcaD)vNs2sW5o9}vz=Bm)Qr9W-rw*&>Xmip>$CV?>h-9GiKxJ6(QI*9h(&dx0 zU9Z%dx7Oh(w-jHmbGy-aYvaGU3V74#_oCtw0B{)qyy;-56HYO#;!Bd5Fp}a5)y3DB z=TD_aIWJfkm>gHzszo=HwC!wQ!Zu1O5PTUkD6M{EonCygyY2Xdh0-r}9vY`6hyKlg zQoWqvKh{Ko-JwZ47GH<8$f*=*Xls90^@6J2TxHG*alX#CT5Bjzj*@}&dSFwGYf&vW ziWfmN@yE)$sx`A|Tv;{k2z!MZ*)}>qvxj03R*JxG;b^2B+=EdpmR7n$qvh1`wTTu( z7#d1E@C?bt*4XL&dKjT_u3NC-(Qzipi_c`h6+DvvOY9b^!&*=3xWYLjk#K!HXgaND zqT`d~3%^IF7g?_hx)yVhff5Pm$@SN{sx@$S5-RnUQ|q5xbkR>h-2DS_)|y0lL<3PB z#k3+55xjZH4Ux%#%j8=Ag!S;NUNX$M-6!)xz()#pl06eIUPb~lY#UT5<#|O2mWv*m zm`zX|@M1R)Nc{H#{}7f)5J#f|t+{ZSp1XK-!Y8~RaC7iT(Ta!Tk=}b0YqN)5C^%Hct z+>vy@NjZErhtm2$Yy$1F|CLIPM%TfTiY)LVZ0_sE9>_oDNaaCEF$H^LtL&@QxnapC zFz&?ukwK?12Drk`0#!#}#>pJnI?Q_JKP4;w`cjK>DM#~d6>8WDOdPdXWFR1+`oahL zC_b(D`&$0ZL$opcS$g@>D&4y{_9_B_%3)1_jI}7Z9PoSSb8`O2d+@*DH6I(Q@BWA% z^I<4-zKiNW4yTKL1^&LD8!^`U|Mk86r|*yw_-wV2AxmPmxuc;SK-#wcVbA%W)DvnH zygwWc=?NyM;~(BDFuJ%J#z_C4)LpP1^xa!@(Oi9&xwp^_js*1o4s`IwfIe9CBDQYA z8v2}Al3%D(rBV&%H6YGZn^HeW-s=*6`L5X=kru;cx3N16tQv(*His~TjM13_311$P z=u#44+N(ZCA|N#$OpcW$oR#!}ymoh~C73mb10y#TQ~BNK!5nPqZv9e_t@mXYxlu4~ zrIO1es!3rFP%#;ZJXE2-5Am=W{w}luqGRlB?CKV^%Cw zTb2;GR?3m8YgEen;|ajNgB(PKo3-{F zJnP~9x66Z;+8T<(u(r01cyjgWD1RKZLZbcQ7eY`^XR0lOq?0+7k%_oyaOkyS!0T{e4=bR3ny&O233s*AW;oW(N$&*#Z!Cnv=*@ z`PM!dSvd%}^s>HW`Pg`{x|d)FMi(g7+!(GNQFy0u;V@`_wZkdyX#x?S+ijF!BPyRO z>t_tAYH|=xd?p-Gt(B$i_oM z#1(7BY1TkGT$UMhMHi|se6pvh37@b1q&cYDn1AaW&8!~ZwLS5fOl|cY4nvYBGNn9Z zL@u$`)&8V_(a&DxY}#|n+f7_Dq;3r1z6|Xb7aV$Vt-}h4MGU_7V zze$>8sW$BXVrsE-2yRRDJww>=g4@ei&*KW*$n$QlKMv6sC{Kfxn+*C&DTzrb)LOM$ zvv!scTEDMp{qsEErfuO$T^7=r2=8L;SAk{58)gr;6Jrmfm6blb<1V();7i_zG~2bU zPab(srgn#oUk5inuy_R?yU{^=vZ4oDK;OAvPG0r|CZ7H~P;rscTfmc$=aWh}0Z&ni zXfvNi-|+rSmAFQ=6;+M(JUd}eDqWJ1a`?K@ujt<4jBcaH2S3n3*t2=XW|mCAZ7&jt zLiqagS912MWwAB#-S2)Viwoc1owC^>WCGlga z(nk67b3h=HP%j{-Y-~oOlkV}^NOS!3P|WCco0zvrgC>39W8M59HAIoED}B8Z8Xomg zrzqDm6_!W+$iEeWI{a*#}2Xc7~+FMS*&B1&7s$= z)smkB&{6~?Is;IzA(fHP?p}5ggznRD`KqUQK4@K~N6Ho?3h0kT&bCxX#qaI| zj5EMaAhk+KxBhSsdsA6ww;q|w=Qf1|(d4-Ax_z@gX}h~YH=R2o^j^h_T&vs!`6uGC zOPe!2`Vk}qT;#*msw%@-KYf$v($VlJb~;Qj+z545AvGI)o{~#4s6F543ce8GBvbClB&ThX z`y5fCCLCUiz+*@)@;9~PQxAzlE=vhg2>dW1(fWL9^zS~aA+&5-(`(RmNG`W9SIavpE@)AWfUuL zmn3PpBn-0|_L0Wec>X_5C&Aaij{EzUnE-h`wf}h>{^M(ffY#}XI2hUQ!0q?l;2wmc z6j#JT2#%`Eqq2!uhx(ei^hD7tae->dcn1)3M}5I#dS5i=0iY74#{25K;X~E0P!=8M z9W*LOj?Br^(zxz+gl}yxKFVx$xg%&$rAG4*^h*HB_`&63uWp{36ZO?4QZZC&2Q125 z(o^MReW%KNhi}JO7MW^q*$=lbwm?-To!+UT#p$rQ`=(v(;y?fl0|`rGpa@wT_k|H( zl?Ge)TJJFpTc0*tHmF8$nY9~+JR1>QHXhvPar((CP@l6*yy&Xt`Hh>qrQs5PK{*vK zG~-huk=@1oMqb+E#^%KtyQj+PJsOtR$5msL0|6(b7P9(Vw{(`x%g#gZ)Ccv@7)xgy z|D5H`k{nN*t_G-RSorpTx5uCdb3>z3 zNE3s}H<2Qb#)mYmnVg9x6eJ`hZG^~9fBWOxKwc|s1HOELeg^(C35AaSHo8UUaA0n4 zp>Y0y5Y}t_a$i<%_N;Mxdpp5Z8*8C#M4*xcILuNuNfOS~*iNrQ_4joEQN`&9yq6U6@P<~tByLl>nR?5HV)^Tv-4bfxx%$4vlQ3Vcj37zukz1Z?HrTH@NLdrOyo*@J*FO7j3I)>16SgGxU~v)>74h`(^i)2{9YI&AI%-O^xo>xWn{vMoRQ z$M-K-ER?Y&@_{?!MWV;6-4%4%7e5&Dlq-H9#L?;oaywKW#?3~Qi2g)id%s}t6HzH5 zts(!YQ*zW~ytj(x3(7XC1tJzrR{NEmO3gPkD^b^Tyzh=g0xpH3N`B7=wv$R)6mE|( zu6{Sxv7E8a3YzQ)S6g=Q!|{SsPC?SJ>+bDKmh7B&amBwGI>blI45@mC(un8(WJ!Kaq?AjQy+tAT4&>3aAEu_t$Z~BdcHIWQ^4pzG(3#EUW|_&I zqCC>G$@-{Y@Ba+~H=ZyXWCzi|VxveU=n4YLh`raT6DC$GuTx z_~!@HVd>q$ujHq~P-CbVbe^LYqj!ex$5eh-PUHN6qTS#bxAYeB!k=N@X z1et(8YhUqKx(nO{{`bMD@x5_W^(Zg*p% z^^dL07o8z!Vdcg$1vS$;OC>D}qu1{^wifQi-S;6SY|+{u1%G|*qCyqojkVik7#YiB z**;mPwO{RekyZKyk1l`bwid;P$aBalr@wRd{>8l);6p17uFbNvI+%tpD?X(i&J>Yl zNhP!wzO?!|9sadA+)~KpVJMy{2%ABtcm~|ma?L@f+!nj-0q;yE3a@G8F4MRbexd(- z@7&Qfa7U2#z1{Em`43(f+k}bJopD-?QayM&&E}AU`G%6fE+m#^oKEV>g>zWe5%#)ctts;^a~l~qkT8$+j?$n9id zo;ZZN9cIio=)t|}5#L=8?lk7I1E?(NDBp6U0TDK{_gQDWIJT7WNiu0%n&Usvh<;z% zZS>2^T)8B0SX&t@*Tx)#aeb#6nnA>2P}o%=RMy02E$kSIt+(G=Ler=-qa)v6 z&e-@4ze4q$`NKQKhH5$&r0V{!l^969Y!!qI;Y0$Gq1X(DHP%6xFPTAsyVCm5(E(2N zwsGQBBu4V41Ajnft+{Gt`t%ZJYhIP`k4 z|A(x%ii$JZwsmn$(BK~2-8}?{;Dx(;fZ*;B+})kR-5~@E?(XjHdjECKX>ILx_fzr0 z1Jqx$#_Xf_uiLFIwLd`Io$*VFJ0C5Jb_N=hXx7jFI$Qqi@zHF`6wtEaa#5QO#y^pG zIbLWUwJ%q#l(NaT$xD6C069!e7j)1Pbd{|?yxaR~&fnIGdUy6cxTdl*LNUrAb zWI^Q5AN`Km9t9Mn2rc0vxUxP`HE1lBPW8n9m=F-40{lox|JO?n4U{y-i{dH|Yhr(} z!qJzSe7Bcq-SU6>-gimLU)pBgA>TYz&X%!*n-w}*P$E$9_yUUMGfa~X);m349X_&^ z15ikW!mL!Qt$;sIv(||7?bhi+1Uy-jes!DXG}}5d(O`0flrHG>yUYl}S#)c;eF6ex z!oUuy?0t+4Ckew{@mUj{p^9nNR>V(O;`?rNyx^;t zt9GY|(R&S5lgVw59!1C-G@L?jY~fG&=d?q}&fBZ#E9FKA4U zuhjuU@*coFsIaSCUD@z$rYq@(c2cM0xFwUc^}f0;@`?8CdQrKn&+dE%$IK2mk|xQe zvWR;R>9rVO`@@*fH#vXC<@v5_zv4CEt?)AX(hc=I>I5=KM+~EnN^dZ@{_ba_Jrc^X zs!b27$Vaz{D{|aJ(o)VnD^oEqMWjEmc|lDiA$8w`r~EnqOHMXS@J6F({7NoTYPFtU z`Qta+KJ*cc$>-N}Zu^QMK}D%$r1Q@-xCMh@<;P{ZC2?Pwac}-;4J$=A+5 z2{r~8m(E+F4NfncP^hG0yvR{^ zW0)dF?nvcuKJ;|X6gwuV85f@FM>@t~E1WERO-Rs&eY*?&H}!_YDJZp_v3HlNY14A; zX6al{3~%4T@eK={hXo;TpW<0s6*#LHxxuEt6l+W>aVNh{j#gS$cfeDtC^{DN)!Z-}Pdf$w>AOnhlz#y(w zBJlCY@UdR7%{7%9s-eucbZ4ywkU+WkH;p{D$S3&xuIHd`I61j`!vawNK+1br) zzj5ro(cx2R-tPI(MO-Z&@OXV+S)|v8ck+JX4e{PH1&ZV`WVqkujqX}|9pq~8d=LWv z-OT>eE_<_YoBB&Pdmx4&FDFo;g9qepDv5@G1SL>^L(OQh8k`GsHNrrOilCvv{I8eI z1o58t@)3yO81|y!K_2%ChQT(pt@ysy0ZGt!#HZyGMPcB85ywtJ&uD?dtdf0POjOz_a(~ zYt?dWVoRFsKg2*xRcwu^leH?YMQ*bvh9^kD$k@3-;TV%=+O928;G^R?>!3Neq7hJD z)QP%cVyO~TYSD`zH8$t=l%wivCer{!p~Y_i9Zr_j?T($|TOWdz^*xT(bFAjd=(d5s34XPZs*I5y zqgIO|WLNjs>%o)GhLp-^5xmDBd3JTMQjCl3#^KLB!3sM+MNFU}aX6C}THA3bx5^#Z zz1@n1e$Ns01#5LywMqUo(1`ZK3ef4uzb2+fxqo?{W(Dbp^3LWNb3fm=+siYS88ljQ zR>6~;H+mpl(aBa6za?N1Nj?ebHCjc<*l%=!@#%eDYr}_6EQOVmQeQ=nH0nXnb}t)r zSlAkXOg1t+a{B9JpQy|1Wv(;SDMQGc3o=3!`XznVBs_qvTy%%zXsO;DDKJw<;Zsx9 z&n)#|CY=^lTDM7fpZ%-t1$}Oo)_>^&2F*qvFk{0IF20*s{~lY(7tVh1(h-v0abJU7OO_SWa453>N=_UV!fI$B;4m==8s`U0iI1G|qaLo* zY}BxAu>ELrVgqjJg{;Pm;74-t=5WEv}TGDoz^WvEHg53 z%I@{q&=RQ-I`V1g;iTzqcsmi~D@rVBK9&x4K_%id5}%*GKHYMUrXm$PUAY*U0L=c0 zU4p+3OObY#5@H5b)%z06-#nXS0^AYyse+OA)aTJLZt9Qb$5tAw?)aS76@M&LE@+IE zd3kw3ah7R6=*hWhS8lTo0?1Ar0Ckn2e)b{x@+5%zNUT~#Ei(Taf589t@_?ioN{_yt z3hnWt>G{6u&Up~gmn@IO=F{rd)r0EB=lc%jPwIcL+i1ODxyW3ArKHBMpil+8x6F%d z%GTL4ok~tT8bX10OhOea+YiezCssw-mf;vw6aphanFYIfT4pn#$+ear6AGFMOptUR zTovRkKkVzTxG+BH?o)2)Pu#L%Vb5C4R}_;_i9P@FSe)}K*`bS`Y2F~sYJfoglB!~0 zcl8%_<3?varPAVw?rQ;$pmmsXn?H$Ocb6)>E{%#4+P#n|7itt&^$kO*;vGHWiGNENTt z;#&A2Z_91JRGffqkPpP&iV~xfkR&YUE70E_jkQf3AZ0$KM%w>1)6qrGBp2!m42omc zCr;-zj%Q0akMj6D) z-e#wZ(tMU=07btez(r_FZ@Q3(9yQnGboPlFYpxwYu4YhkiyQO?Q@Kf=_8#F|LjG=+ zP8hKGXN4STwNO63KWK!4(AYXUrZf2sjI$`s#{*^32sVOoVIooM7Pu$ zE4Fb+yEA-%8sU(3Bu~?~53g>H(}IV<3m1y7ZndjlV{#|tGq|+p5LF&!u_wrBmZGLh z4F!wPLinjQiv6FwJ?&(Gg9SP@7UJt?3i02&4R&Xa&fS)0f9lbPpRTdW>9(V>FOKGy z7WbnLe3R&~EG9Q)hZ$$}nhcZ*Ey!lf?3WwlV}J&ld}0@Dk(|Tj%FrKL7Sn}fccvp> z(p72fpFqf9Ma6OBE-0|v&B54gUCl{qg%v}83&OVl)No|7w03RO%jcUH9b_VX|GLf+PH$zNbqBjuUmT7oUqZ%Mw#Q?(O zA5(v-nmULSSvO(`{+9JJ#XN>ByxnLwV-#G%2`vpl*;GV;3=5zySIFhIl-edc2Ka^aq!=(DSc(RUHHmEI_zF#Cx{u6W3`DKuz|zPjSF0U3 z9gjXuYZFrAAJ`3dw?{R>&LnbgJ z+PO?iZd|+hByX7GskR<#W~~T`LM7}g>5gGoFC#qW{}_IHY+((sQ){fm}*s9$Fjtl2a{#RS|(T>lWV8kJ&MiqglZxy}?D-ff}M zS*^8wZWDHAjB&^iaA(tE@lDR&NDcWZb&IF5lFI57&Bp;U>!pl{YshUZvzn7>>$Yg| z_p^pA=(*q+5=Wzvl8mg0jgNFk3xQ1qRWkUL{p3L|2h+yq6F+oGy(GMzTZENW~gRXVEciqF6y1PI#hKU#blAJ zCqAbm4WllbFq)+(xIniZq!o*`EO}d_Nm}}LHnlSd<9m-5DLqr7Q1g}1Vo)ZT0db>R ztWmexCM(Kz-R)hyT;qo;V~xWNsQqky+CUm9*+d76#*TA=w?6_aZ@sfE1DlBJSME7B z+_1-37BpMnE{r4oZcTSTOykZ+sP(U>x?q}Fa7mF*3wkXU17F9_tGeGz8o7S9jx}e^ zc5?z~mXPp)jveOJcFzum-n}4+7^3R@&1~oiEOJZH5oA}H1nMZ`2ng)yfeOu=28xts z;CmTvupZlv8JjWPR$OcH2hu~P#Oz;o_;Z~ON>TvlsWrJAAM>wGx9!)YOJx(#P*LdDCccYgO~G*g!mP`Ry8d^?pHAQ_5jG3`0L1;Ie-BP;VyJRM(SV^bdq~2?NO$ zUxfG#(o?I#2KGO*{N)!&4b{Ur`W;N~wsQ%1!nCuuRAQQU)~0 zFC*1^EHRe!HLK4&oscmX6(3U(g$_-}6ZI(nC@_Kc@L;>V$sTKB<~;8yTuv9;8sRkJ zC%+&Lq3U;~*L?xs8WjD>7P0hC+GSrf>h*){O#OaY(pf?0bC-TM90j|cCX+%ZI#VLA z`d&+fU6&AsI-~tMfkX1@xuoQ0(Z6+~nJ|`dN^jC2kaK-+{6OYfJCa3RB32{yuV2Jp~9<%eioKG`i%$h{NL|1su8q3n9+pJ%Mu~k<-6Eq#Z zbb7v-l#|Y}HJBHjjix2cb*56uTQM%5tV9t&pJxFfS^f@RLrN-XqX=yX{SC3@(8^#Tx zw)lN5`QTk`UM#^b@=k342Attcwn4{iHcnGtFt9*oJI8(?m~ydRQ%t`(+yfw`%c(&aMM!y!2ia&r zpRJR%M~?#$U2R_*DXr7?xCca!Zs*h?zt=phqIg~dyTdlmkJ=d$uYaM526GMI?pUjY zGY64|h(2r_Lg`&8^xIu-d!GfY0gpl)C<)l-m+rHei|pHGOt^1B4svx1Ug`r}o~E`t zM8K)+@xGI)R<5cX8ghp{*3enYD8Y?hgTE6^cuhhuWv;x^@={Yd761= za#8KM_zk*HaSLkrO{`ch`J$oS^`en42!yi3tRo&2lp9m*z?S^d7hahT2Xqg=eRZ@|Ulc0)$Zlgdn9L zSSE<|fUy7btdK>CXmHWO82$0tAm8=8#KoeI-#C#U%A%(~-OMf7??d#1>r%W!mOA~9(Hdqw$w5-bxLT2>{p#dalX zzLxiZZN(yMRJ(s~O|b!042keufkKvm7^UoTbE045BWd|R_K&0=i@u}un4HpC!^<%( z*caz6m$6%~S9i>7NieT3y}Q-aKs2kTTsL*nMO?X1N&?;+6hODFMC-~fCIDyV&zD^3g(^WBK*?FII-0+jqsNM2{PK#QcM$#| zvyEFZG%3Yhj1^?CtKyr&Ymq=Nw3R@8V0~i0)fW~~`>!@D(tU^^d9YJ>@oPXkRME%7 zR_~OxZ$xJI$GH#DIq{74Q-MUZ6u?HL-d-d=m|YsVWnC5jj_}brWB+5wII%mG=RPaT zJdHKS_7M=2f5of6{QXY}n9HBl4}$JyFYk>*yLg+C#dFW;jcnoO3M7fF0oH%_xXWGi z#u>>AOY>8U`;`a6%ZeQuhAvYWqFb%uYvNyMl_$$B3ApW*UdmL8rjvF+c!Z|{?pA5~ zemxq1BnQtM{{D_;aJE%8mYTz1iE;ND;`o8q9zmnt)KHF$JO?C`OM8QnHCKfVJWm%9 zm+M`Ht7q+sNp5nx`Qu*Qo!kXTrs$n9!oKj<)rIZR5Df6KyBnqM$Y--m{+N2&Er-JI*gZPE?5d9|qAYi{hvi?g0I*TSXv8xL`ola2*xEPWcwSNQ4F^TRv z>rX8ae&RR?VNj$J-^xMGa?z@3pL}uoBXo553ln~x*P)=th_rBji zQ^@Y?XjmGn&4rE_pO8{-5EBu`6UTOMM2b%ijKiNK%$ch2rnzC<2i7J&Oj+WCr_4F> zBjBnfg3D;IBy&(VuyeBt9q1@XuK_R-WKyd2)QfRdSlTO;gOz6i*LKPed}pBeK4E`U zUjhh=AK<7G*X;Bao@%lyMeN_v>MkdO?f`W=h40sS!M4xwamESruy#`?K2f47r0S&UsNat;*%DH-3<;#Xx zLYT#)TXQ_>v&Xm^3^W>~+?=+m+7rguEfWWv&I3^QMU6SO!eGY+h?u@#%*_GskMc@UyI$lbWy@^K2=B6*?5|o_$DVZ$3SE)3c(QrtTmdKtvKF8a_-r;)z+iFu{yP4Ie5lf)U_}As7L;o%8Qtpp2 z8P!Hd&6VxjkzC>i&lu*;Ei7n357eSo_Q7NK$$2K>&x-qhF(@M?b@>}-XCnP`Z$)(m zU5Gr(tR&v2L*uEWO)8X8nKiqTlNt2~7ijq8a|Co^Tsi$beQxG;gWe%VFx*&Sh=DT8 zA}Dt!y6upHHf&~XF@D!G^ABhBBcPf#F>)o1NtcdJhXr+mgc1tt?$!gQeDX(7Waxem zOcC?4UVSd`V`ZGi|J*s8lE-Flm>RC*-n4ncd(C0L8wHZ6&g@I*z3^wt!KyikA7VY7JinxT zpQF`Z`7w4n9|J$UUx~D%{h-jh{#~qJt$QDq5{*w!Qqi#F4R!c_`(g>nmliXLcDIgzVo-Qy^0w2E_xO3U*k^LVx5-W#|T4La0Gq)X?2E#mw#eNcz=9j zE;+axK~YUtqN3gO1P;oOE|u=i_$1aknDAnMNh6Dg9-`LXHh=Egr@pq4~8#8d(G z%G4inLxD`98I$g7;ya$MgIcL#G!oYEMNJXD%TOY3f-#QC!0*V3f4Sq3QO>wIkOMo5 zAs;0B<^xU*g1$Rltoks2SJzVyoR9z)M6NNgKg)OY+&g?_(&?z!CyTz8N+;b!ff69+ zh{t+&Dyi6g`;LCN<_jaA#x+rXr?|h}>~>_O)#;V2mcI03uaqj_40Lb_wF%X;ppSo>13=GDvWsc)LmW=Dyg`(Ebg9fZ+(YlNik-$fuFIK_ z1zjnw?=)K+;V;*k;$hMlX%@BD)hA-LRW85TB;64yY~~1giYoq|&~NzNWT*2zj$FK9 z_=dUJ^};7YdgR#|Jhf@KV==pE334CL>Xv(~)a_1cvehB9X#8-xzbKr$ibo^`2!1NN z5S8&j=N!7vU@MWa`3MB0J#7XDMja09d;`>eQ`8avjEGEWG{RFS;IsXn>Q%oNb;72m-}OrJBQhs z6GMUIf||%s|0zT({f166Q9M-WW(lMJxt9DH2>}uX+}ujump=b4K){xjLQ<&2*4p#& z5M6f@)iD-E?)XP~UwiUYWEF!!bdzJzb(8#0OA?Yt&eorQp0hL}TwRgbo4q|g_z=Gl>Mvpq$TV$JdTkeRiJoTD|&<_?XyRH8G9d8BtbHf5=UAxxdV(zSScU zuwE6SwjvMj$$GtI{!-s*jKCiAAPWQ!vS;UTzeJv0MGZ>-v16$-bCw&fVXQurJcxN> zi9-Fjt4^IHp>?ESJSwpD7yR;1v0~GQi*9BV-#HD3+yaB#qh~R{Ke&%8U-ar`>#y*y zw|#G!xX~vo_exuZ9JoiBW@q=@y{Flx51>5eFID%)OXuHT#@p7!n0Z644a)Nq`ve#| zt!;E*Q1yZ|GRxgYrM9Flt!)K#VecmP&LS|R;5mp!+5TChsoLP#cQZa6kEg`M6vLRT zTxmu;|H`o)uuqjQ;{Q6#7Rg@{@{Z0(7egX|0~Ma<)ygJE>X_AIR5i=Qi4jv zD+74fHZS}=Rk0L>#0^l+NJP9t5Fsmy!>&>G5Xq@(@O+_57xd)J-v47g?8yuz2$-Us{?_-BCEf=Ln|J==X^G>bCm=hR)C(3o^NjLrNC_dPdSle8L zxFTC2o1u0%(7N4tK?sZM-QN$=CU;d~lw>E@V57^OmN8p6+{Z>soi^ivh)0g7{gxBE z9_eqPs#+6M9FGGOK6^e1(PHP1t&MVVv3@__y@&L+8poAK<>_`w_~kZ3bmx;*nQH5; z)o?nLtEcOI#jBdzSlWW%%gqsN{7mVD{j8^=SJu0eHO(yeDjb%WA$r(Jb&m&1vh@Giku`H$C^k$|e?2^t^UZm}L zIB$&hM|d-VdctCec}H!XE@}AC1kTvd{!Y|5YyA@{38yACV8xZ>( z?pN9ToX{=(Gxj>%`fk3ZEEal)QOqwW^#p>@AD`F zF*y|sEQj#F$bkw)LftseU`7G_4b-u6_x}BYJctmAABka=5I!a55rn+IJr+dzcBqpD zJo4o?_s3SaSaT+-nxA9a!*qawJzR$)R;4C@i)MRFXy@?JQn_S0VWQ;{U2nn$bI79R zGHhk*Txjife=S2r|#*48^w~l7>y{=HNPw1Xr7;jku1tx2ysaFh?w@ z-U=FK1>0rxl&W9_sKvO_Vj{byHCicsiRqF$$m zxH&*kMZ-eUX!o5A`{e1O&A>(|@Jk~pa4tkaTp2H$-h3h(waLsASXn7gEE_K}U7!uL(ycanPk`Du!|^%Gv43ezFzOLLmr30dF5N!8W_P|E9Zv1IWJEtimCa-_ z2Q_K?Qy@T5A$XO2V)CmYEri8%6RIwySGPxFpcG*%RuIcrU@qjU#8>j*TF{GIBa_1y z4uV5{48K3+FT75DduuaBZRf*opAx>cHhe zCgbq&D0W%jS!!2I+AmfFKF2}_^b9oKU{UepC{rR$UFHEnW9S4|jY5lyi}P>v_N(8v z)B#j56x>+GY+i$Cgf8h=4-91?;I*toFFRX_|xxr%Jl$N2BDd(gdKp;Db2 znK%y~dwDlq!1EUIAGx1v`I0d**6O3haChY@<%$0i_aa5#+RCi`*fd1#8v-E2eeZ43 zXr#A;Jd)Db3Y8qfVvID>AX3m{q2=@(sD8%OnDsLhAq={2dO+Uv-%x||FJs{P%aj_P z4Mm|793&l|Phrysg3!>&f67ncY>gYd>{GVQMWs1m!God@no&F2v}iwFeT z2+BN5flsU7!qNZdvXIapFtyS<^+^SPXjW`Gi37;QaI>)*PlZ78nQ7Vki?vpTKO+y;hu5B(p_N51Go{b zgaE-aT3M?5;VrSdfG5a{{(f1F=hn{G`|Zvp^HU<|t0GyPg#?F~JYT+e`HbeWm!AhH zC!UqR(v&@Fx5x)IydS24rx{2z6nsi^R4!&{wR{(_j))%GuJlnYwh_q~P{^!kzo@ZA zz4u+~O3>xeQ6hfrO^SiMH z!^L15xlUqrX#LA8&OfOS(-SuiqTq=v+wagvy%%@d#MK{Mj6i89a#Q*-p95qP&|~_K z$^CSEE%f$uiT+Ka*0|N2bq_`RF6g^~D_S%HDsWW=Jq6rM@Z1~7^)8wyT)wW3$h5@9 zZsN9sRcpPpL+hMBeDs$)p46SY14%VIG`2{yKxxyIw~n&d8NQhFY<_-4V@f}Aguvq3 zw#d(zUr<;b3`v^NVFqrGreW&f;az&2&(%5x%OO()4jFBLjuwtjxjiESTnyqF18VH5KjWny!zMHBH$ z$1v-ydQ=sl!^drXJt;ax+^>n=Kc@*5_f7A38k)zO)L(9>JFMUQUA`1!yGS(WUFrUe z&6hkNuRWc`?|R3Bhyb-N(sMn(udmXRI7Xl*OO*H7e`8UV9}cs^E{EHbFf9$jdbzZz ztlRxer&unhn(DhEUjT~%y<+wRPx$R|V*G{DoCrU&soXEdEp<(29 zgl6)X3Oc}SeIv*0;e)cgI3FOh>bmhec>LnBhG|uw%H1 zEfe|Qm6I0|LdUhIY-n_LUZCXoBp6K@M*R1e@aOv{&Crq;h0Y`r3&CEB8ml=itEKY5 z?CCONelV7*M*t4g-O1ei#@2GPd5Y`lc&}WxfX_GQ6Rsi@qBiA;Y;W4thYf90>-CDb z<-r%bP?WX9d)u2NZD{znZ|YSV>-{Hlm8Q=q=4!PcC|+`|r<0(wKdW9d#g!F0pVO0A zBf$FI(eGDxDO&~q9{irR!#)#m*B6EImLq9sm1-7PK72y*i&TT!5O=atSr- z`fBT7O^pVlihges1X9m4D@p@E4>jFKewWdAIu5~vP)PebGS_tfU>ZiPrjincY&beN zan%eL8^pM=2rHlr}auxy>8JtkVPpq9dS9< z6L2_gP)q866q-Wd1pH36ndI4?=M5Trnld}ze!`tF4LMz`lefS9(IZ+9i|LEd;qZ4}u0N=Tvl<*p zsXm(3L|*znax#2RsVyPs{*2N2LBB~rkWE4=n#t#>Sq()I4|Bz^Q$Tz~;pa&V6_6ze zd;k17!{T^0?T6L105727Ch{x%P(vRmoVVpq^U?3s2s!9-h|4;VbkzxL9<+-z=5^HS z%CTE+Na`-ISNcq&Ud7?P69Psx1_NIyKWdG%y09jIV2aszCJ;FLtJvVW+X}x=^VsQr zBcZ?!cm0Bi!=&3Khm5V&b%4X5+LJ0CTnoV((LIv=4joc@5@0{RRHxmQ15dXJycIcj zRfKhhfo*gv)>O{3;DuQx2RNssWoLYvQ*1V-b3JDJQAn|E%@ZWECiid8=}W}EPrub% zHV9bMvjjb}>7Y8ljp5H#{2mO$3(OafDc4&|FhUT;yE-W!!wq(<8>*hafG|GK>)g;ZotD~*_NDShA3{oz_+ zc9>qTtF)}x%xG_z@u!!wKA9t6&wFadpxstl_sJjwl7tE6k)HBq|DRn(#f5Q_cVQU% zBl(;)-x&R+;gl#Q8U_%o8t!UwnJm?RJ|tm}_3@K`6y6cNv^JAfFH_Z`?`5Wx{L%`6 zo^A~(I0b|nISZEm9^V7a&2%XUAtp1M05V9;ON%QChdcUB+9TWu*5Wh>ZV$0B%<@i_rsLh;x7*Nw?+qs#?ZUsG#xGbjGv}8=FV~X2#nnI!k{3Tu=^v!8@wDR zH9m=s75(9Uy#zQ9MpYvf0+-ONJF{uXX8(@c3fXmJjj1x5UB)ify$$3Xc{2sICFV#j z72&47k+-I*#qz57rKzs`YU%aci)w$USb~aL#e`7Z-JFU z1DK~_S>c(zYQ7rL3u?rn%EF>9X2HTNa#iTBab+w&n2~S@`oYKfyyiWzVCs|h|K8=M zyeIu!{Mj&^j0WT1NA^>ex_rkLE8N=CRAp;BQZhWLXFsT# zyunFU%Tz?!oiKin-Z^tBQ>_)K77~yGq7fjOoE)F?g2W}oQA%^)d(yBC6R?GbWd|UN zF4t2V^qT^P*;0p{O_fd4q1b3?h|fuPkR2DZ_LGT~EMJNQTAh^JepzZ>-NYgumRQb@ z^0uA)<+9bfTwQ#A!yrLjsN5(7X>LQi1CHTG!FmL&9kpcEd`aq!z|h5jplTWTE;nDB z*~x3sHMNeFX8V4py&EgF`!VfiVC}=ST1Cru)tlroT_i8h=wl<3K&7BETu?lwUCVs_ ztpkCKxoE2);ng4W5wJ`F(QMcIn5s&xS#n;*1`V=aNn@#$D&ZNxeoHG{JrGGuPPevw z(wf3(Hk#2L#%3m0EtFXv>GB>=EiX~>Lu)j72S1TnJNuLMEEy%z|}K+5=Hc%({x!mTK&p?u_bsovGN;F^EX)JOYRt{h6wq- zi(R!Bpg&f1Zi`@i)8Bioj89R|{yt44iQsFHb-EEo8aOr)OoBb3bzjLy+;5y#^D4$;nXSl=1byOE;$QaP6GQFRJH+8p2n&f; zT#p`{viLX=VCc24K*GHNDf%IwRgICOSzT7Y^Eq4>)_qNgm^cG+uU->p1!w#&wRKb9 zkRX;I7aome2X1N84qddGsURYdy3crfO@i!c9Cs0{u98SFxAm@@nY0(!S=|Z4NSIw> ze*gu}Kih)wRDYfg=r*Z7$L6!eeYHxIN@S3JC7nC5Bh%37F)DYxcvls_VDaBxLKgmw zK^suV_p*ORV$(Vw(`6QnCxudl0YwgMXaki~>5G=7VFyJ0aCZ9r|k$YqL~8b@5t>LIHz@-=H?v^6q}K&m~AP za8o*!Plv->697v)x>J!xO6<-NU|glcD+u!OxY4wqH(TKuC0V!;*yCsyhcv8Y(C(lc z_h#l!@Z27ZC_ympK3kS;(Zl_lyLz@>S#QhvlLl--kDFDo_pHFgmN zZ#5^}`(dsHNmebjn_wevGGw|)MscG{&|+%alx&KEci;mN%J5xbT;)dsI?s-R&LpUC z1-f64FR{kp;~O@Emb5~)P`!HaS4L9wDrf_cUINnTbMDFn^pn`UtP74qkbXXt-XSM9 zI#ANEnG!Ulg`WKdHZ?D;*?_lF&-%$C&-@Yk&%Uh3qKPpZP5rKcxF5ag?KGOYrJ60=@z)j>WFLbsnBC@bwE2T` z7I1;~-sNywS1GSo>37EgzeQN>RB|szXlam9crPl|>ac?yMZhiX9n&M@_8J+0Rk||} zo$K`!fmZ+>ywdO%7fwPjhtvdk$uPf+KhBk@sLhi)%7chlupJ^#RhHi!G zrU=Kp8MGWh(tz&|Ox&#$+CBaQ48&tFaky4RTLLalemRw!#OZAAgp~65BD*zXJI7tk z&yfW?hH6*a;!b6j3CSJDui?rZqDveur$Hk9xuhChHeKf-1F2+^(G?uF%P>|OUC7n% zzLG2-Q8{T1HdB%Rk3k>=oBg7id zi2}d}`Cm@8GTu$-AyG-vd|mrmAdN(acM%&;?d-dEx-vK%1ll|VdmP6+L3~@O`k{!e z6MKfKv9Z+V63d>OEk9^Pa(X9dfLf+p0H)k7r}KEfVoxJGFx%ky!FuO?3hSFdhFmhK z!Px&0E?%ZW)%4rRw1g0|+dvRurx%=3JyKee1~aJSym1JLuH#ShTO0ZGBMDg)@*WTNQ*Z~8oM4Zh`MZ$bs3 zub^#6T)Sk{X-WK-#y#gnc+kT`tmL})ugREvQFX07gCrBY>p8s3frXZ;HZPtJu&zgDP98oTJ1&mUCGFm}1k zucRIgG^27pKp$N<2RK?6XHmVlKm-H&+#(0h;ZK7RDtV4W2B*VbI@v`L{Q?v^PS@oF zeEA#};R>)trURC}lE01?d(X)TpC;Re-D&$s=ihpu1fs3ukQOnI_adh8AD!^$y6%71Z9{ZoOy+)jis1rl&=E%_b zFt>K*kol|0=L%DW|H|wE(2z7Du0qRLo%`$HFNM(V zUvEi0(9cb;E7k?6I!SG096Awz1XG;ZN=V!D8=+c=9nfWLVMgBbGw0?kw$`QYu`rD9zRy#{Nm+Z7?`i-K81y!H_#^SB>O5tDk% z*?$g^tJrFi>fDiWvvyxRu5?E2_2~#G&x%F+jXchFYq_#PPmD{m9EaKHPe(J;`|@B* zxCE<9GGZCHfcv{Z>Nc7-w z{Wd%)%W5@$F3Bj2INhS+T!gLeh5Wz{`2@P~@`L9n&s)HykjMs?q_C}<|3%g!k^XtGwWQ~%ZL;1qX*e8o-#@Sac8A@ z=;TnNMIXK{DUd=M0~5i$29zIlb+~Z1D6S0Ov}tV3JEWAAU2Ir%yWBXEI>Z&;WVd2> z_d58v5ttL9NW3iMD=1i1f4xrJK1B@}{EIQ6%T;UNqt7b@@2A0PV7W5ol5JL7Y}@?< ze1uQwo9llUr;BZo=~UW+X0D)b@W#r;fg|Ni%T^{^fEI|Eq?~UwGqlkwvQ)ba0VJ`f z3fD$-rALCxY04Xo+V-G}P|D%qfLaCy1GP%6aQTyu(p5;@nN`I9yKB&L9X~PFVK;uc zWU6r*q{0_)3re5C+aQ{30vy%KW9f6J_nwjN?B;UCK5uaK^tt0M8QVvn@mehWy++NsR&{}r2A|0-!}TB`dmGGwkB|44hk|A`PLX#Z zWSGqEC2#B!T53p`?Y{6b9U23yMsoMt!*EMBI4$|*2CMJ9b*A$!(6+2SJK|hO8S3>( zT66TkhkR8$l5k$T75;J$>yi`}@YzYXs_+Vh;RrWseR%HrOTRS+$tO@DG{ZQ0JO zS>7YdfN`Yoy%K{eULsAUNDbe|?qT@sAhAl+T2!MhRC+aV(q!;sQw>I|6W?XgwP{<6 ze&>vFm0K>GFD06f3>)UIh1bbM=?#PG@kgyG{8*=y;>k@zX7fvK$yqI{j;y?zHb@zOSCr4&K|b z3OXdF*sDp#TLtVD-!~s38Ohe$KSaEx zBW0d*W5mULcx*Qw42{pV=DdAMy!Ll^JMhjcJK{0uSst&eNz%+&i^scS&dj}P-+R9! zt|~Wd3*oVPu_VMlUwXUc5Z5~{hE}Teo`o0e5UlLT2(#_GVuwJP-If}b>#zG>`Vn6l z1zdV{KlX*&S_$?xby=%VEK4k{2|FFvtTp6PJoZKP8yhlQd*1Lr)mn!Mf4pYAKV6U@ zO?Wd2U}ELkEL24Cl?!V%NU4_T7)olY;#Z;T$XlFK88|>*M~!_=In|u5RZ#l>ID6}; zxV9wFJ3x@&1c#srE(z`)T!T9#xVu|`;FjPn!L@OB5(w_rXmD=`(pbZHGWX8A^JeDF zn)&`|SiMg7I%jw7s$KT0q^&C>DO#QNU4?amm&&oxayO5+qZAiB0b%!n&oK5<(oIJ* z(@*Q@bU2ECUT|s-I!b(DktZ4Y<-q7ZeiJKP&CU-5GoLdnc}kFQm&jlLTsrt3m9o$w zZOX+h@ufH-zh-d>#)2<`T&zR}0=q1bU} z$Hz@HLfdMa!? z$dW8Sk9iKkd5Odn&SumKKzzQNH*En(;nza8$}e zE!Bs&Y=A6t*)KN#u?Ii8vO6YPs5fjb8k? zLDN!DGdYXOq7}aXlBZBg4X)B#y1#J-Mv|ru(EwHL`RX5`^EH=s9N3N`iZe_2M4PedJKmq|eib=64NDc&`Cu|> zjA3&vX&&G%)?wZQ7M0irl!j&koNshcTU><>JCUjomedAT62J&FG0IFy>b*C?C3KX^ zz7pH~HvffTmGHqobVZCU`4QP7k#8I-!{>gv5zB1Qsq}^5P3dBt2^WnV(QB2nyQ6Wa zNjOkD^bT78n#2aZax=>P)#lXi`f1!Ud!yWYTC+f48 zC6_+sFNB|O?v@(QerU86o1p~1&~F$xr!CdZn{bjYHJMJNJpP?2^LF$t;l9&8w)XNk zM=Ts~=hRjXCud2YmiR!!DT8$FMSVSnP=0VcQb+rZuey6e86Q<)!{S~pTH~d4Uz8C@|Q6J4AYsQasrq`UUfD7b>8cct@hz?gx>0A z_gDjAiQ7wvtYedz@*HTbfR08vSshDW6dQ#RUR)oA(K*Ms^Tek1+k!qJ(073*)7^kU{5|vTZ9Mrm3L4Ab0c2v=}3U*`C^Z4#jqr zkuU>btYIWC0!^6ha{50q=rTS`W?4vH865@SV$pE`P`!HcEV`x^;^F*EhLaZo04dX1URi~bPTx`Gkh7Vwmplt6!T2nO!_UFG&z#T^T45P2;IHusAiy7V$QE$FCo)J2Z>L-yn^t80i z|MV{<@9XE{#+yZ>x6gXKgJkw3jK?1~TP3F_=J~DOX}T}sjMKS3f7m+slbrME1$@M! z?&v9w$qby)ZO2yz+ySK8<);P4H*?YuQUXX zFqR`)b*&+})lSoxV2|~1-6RaAr{+a_o7HZi%L;}c(O>WMa_9R`TZBO6%c+^hAmF-HU@+Xpd>EIyjU zZf{13(7(_`;?F2LHXctztzY#j^ed+qo|bDje6cs^Wj0dTh(2MAeuZ7vT5sb=nTiM2 zg@wgsU)*}7XT{a=D&J8myra2#q^vW`XaQB=(v7o=t%uhYr54Rsn73%X^B=1BD)O3W z0@`!MI_~0(pMNLxCf9CO=`DE4(bLiHHH=wTU>uhK1TMa1UrCz8um5R zvgmaG_Kg8Dh z68UV%8CC1i-A;aS#Ju2&<##_&3PDZ!T4mtFNQTC|qL9U&O)XvHoW9TWtZdbTbXWBQKd zR{daKivim{FsMSk!Q2HNXFX}nCh3vojwyq~ftbs3*|4%8?m6FcCg;ti%Hh-}H12UH z$Lcd1W;P`jYest)i)g60B3(T7fh_7Xb_=1{u{bYDM$@^6w3iv9uVONI6a0z!BI;+4 z;}!@Pf+U$r-R{U4U;iK$3b1z2U~Tp|ok$h2dEqxId<*1B59c-KCi03~0Q6m@c1=1^^rcX)S!s5-+N4qb{8hNJ%{+54 z&>8f}k!jm8hY5azal@sf)_u%I?FNb>5bW~Z!gx)4JrV1CzO0)%~`D z&BtG)a;NP0hYU0xK)thi=icO3dNqf1YLeICOetfI*I!Y-!t0B4e}zNpJ19rtzcWkpEfmvgg5{V12lOrL4 zrvbSjN(ba3=3nIk&gLo5b|E%J(UwsF2$e- z=1injlp9Lo2$K-Xwb};y|9C}3nOS+C?7AqR;_fh|bGV>$RTyRU`k%+}e@_A3Cx!%0 z(V$JoRt__~ho=ZDj>W%cN*Pgc`-BF~8bbT^B=LUD56Z%2ubqH-WGG!-vM$4@#jLpI z3u_pHXTq#W%UqWcmD8^CCFr??ODv_-wFK}x5_|J)9I#fa2x@fT^vG;?{n>D)*h2bO z1gRbk0&XT&tXhSPzuPi!PDsO_-4s30ZnR_+J44owEG+9rIEcq^JSg`3U76y zC&o5k8z$xIRLUgqhsb3J`j_xqzzW*&t~a7yTXO4_i;_l{lVdwD0U%Nu`W~uIZZ#cVI58yC5M(Thb3etI5;2T)5sP+dP0sZk>%pMG z3zO;APj?hwzYvJ-l$G?&-nW`7jA7(iueAmEe_Ut%lxzj~ChR4lX^Q#-v zuF9uV3J3h?=rC|n?W*?_VMDt3oo7jdTI0W%5bTelU#JnSW`5)yq;Sf{fBdBK0&w)6 zS88{L_s5Wl9WOOKpAx6<)STk{t9|AA0{aJ0P7ScTLVrUty6p9oJCWU|DsVU zD=&m{Ru^TXBwoTBnGU7TulwGMfSa8l1C@6mj`#pD(^t%Ph)J19Z!Gz33-`$EYCp(d(+0mg6y`P5Uc30q>?>Jwq`KpLhjq#!ixxtMAHgg6O_G&o@y5=Rqv?=`XgO z60fdSkdt0e`SMC8B8W}&zDH9qbx~J#EEWp*S&Vtcwqvm>*fb$PakZl(XYen-<3C#Z z?%lBN-P0J=J7JwFeZ)>txV4YR`|;m3zU|J(83@0m$5bnlIdJx`i>?NL=6&aT$svzb z#oKHzlf<4jUmgaJm`stW6X58+4(hyRoH%f?FcW7dW4buI)BaisZt}Pn{2gNL&FiB} zgkN2KVh(DryI$t2D`T#%a5|gP*#7WMC+)Kwv>pqdso5BXwMWhyoBGs6dV*Ci3jHJz z>!cl60;z?+=_4?pkFx%aKKe`4{_4dHj0^kN9C_`zF#H8LvUX#_x7YhQhA@uZjg}0-S z$3rcYk!wbs(nv|;ahqu#qvko@)2D&Czd0=`UlIU3%wIKA{|{ItaLK7;QH9qd+Q*-N z+h^byTn;(W3pyh2)9Vmxw;6gI37x~o{70g*fJc}X%&_Z5q5+~dAdncyJo;B@XP~j@ zI$-O`XKw*9)DRZGcD&e5F)E{Qd7?9uBkkr>cY03fU)HMZ=TG3h+qc@TtD5p3Z|(Gk z>Xgqnf2LD8nMo_~wMsXSG4m%*+?rFq$B+0&^3A`60REdd1F^+K!_lbV>t6hW#rwxLoxjBN-;o7Ju(3CSh#8;% z1D5N*xZyu9p$YoFBLS?Ld5KKse-x8{)LZ``>z`15d+j)>+m!#~1OIK47>5FDHlp%{_y5m*qu>C( z4mS0hVX^;yrT)6I8y#4))I92cNHG6D9`WC7XKZSePtU&O{}6i`sPd^B0G!BYG#(Ws z6pu|74$to`IrL3!ok@7!Ra$R<>@oQPx%`t8m&t?Ia6fH@`sQTCf!Dy)*XMCLkljq- zZl7~CCOI~TGs=FgMY_e=G!JmETi>yJ){z4qw`RqvsFB|dJ_ZGt$rFpV0quX-lH}BY zRAIs0&qQjKuVg;l>>8Enm9uM9Y2T{ZbPgPch<6watk!!jl9adhNAH1f36q(PkUJ#wHCVW*2U^2yMs8DThSMm)7V`S1p@AV8UNR} zv2SfOM^uO0;+T?9;i<4i4E6c_Etw2Dyc1CIN66?6sQ(h0|7v$l{MI6&pKKprWApkv zeB~b(M?6QdqDlqv{y@8q_&3t@pX6>GCGa&Fja)kAX$#fqNu0s`Nl{}S>{tTJqq{oT;Mqp)B4M=LpJ8{IW9_bQzufcQ7< z(0-*;`ghHiYN3J@OU8Whh9ueq5Qr;z%zamOpP6Rz>?z`lav&(dcyc?sWZmX|-0q3)o8xpv zXTC+g@irTc5A=pD_b{Wuplbo@rMf0bbDfH6?#G|$R5}xi$0w)E4)&(IO za0<(qi4=dE+xiQhb3W#EZv7n>&tF@_l2HU9@ig)ZZbVJL%;ZyJHTv01Pb!=)1}Gpv z!2nIY4@9ih9Y#E*kCoAI&ip9H1PIS6-Ko|i}%ZwR=1Rg9Uq}=Acyo zIan@b`5wcRd|B}%p6uUlOAsZtcHdEwbz%HC4jg^UE!GQ3H4A2yA^YPOppK3~)Q*hE z)YHRQAPdY}+I513e_2BeAh_?aFV)vdk_0j-V604X2W|4@go%XuGNE#wtm z_;xvG0fz<43AqZPv8cBS2oaMosKt_)-Y1A<($^-jmW#j{Tf zK}1Z5HM#0H{9C(FsW_>efFCfz;|w+*oKcHy@7SZXOIHiH&(9|Uew&DsY5b^SL{)Z= zBXAs0ZfB)23$(dE>)I~oo|r;ZE0OuxuDQR!=X6lfiu|0T#{@hQa^V7^@+P-H^%Tkv zcoKP5i+?!1Uq@IGKaq2m!R|+nLADSKjF-1csycSvn@S-#b7M!9p}YnFbmgZRd~UD& z&b|}&Ghf_)mxuX#4t|Qcjagz44@};tXSz8P7=zv}e1Vk$!5_}|zie4_?40aQ+Xhi# zJ+L;tLfG&(qN>^nI<7^Ao)inSLKoEC9^HkBx|%bxwkvn zoh_H>G!;^Rvpl{%2X)ow{z2UP^Td0K68L+JK#nki1{nZYQme}3qX#DEh*i1#O588A z4TSd!j%lv;U9`>~HYl*1%txeVMJHpAZ-liUjyfT#Md9M zA6379{a&u4WBG1Q({vcVP@bR&eP4~kYn>&q`c1YLIxrJET(=PxK`@qOi8_p?iK@9h z+pl7KRkaxSFtBRSE&t9B?u7{ab2(X^0#_8GdP0RNnt zk&5R2U8|T}Ya5H`&w%k2o^$uLCBK$CPb~kG@!C2L5AzdW5AM}fj@@Kdx47fPEMc2$ zbhf2A%HXk;)f6ug#YA9iQ_IrC*xU}twNVTWJb7)pLRVm&gnX2=29CI%&J1Di)yJ>Q zipP;Z`w+5SOfj&yXb0}H3TC!WFK+-kuT6IgWpK_@dhT-qlC%Umt>)Vxs~f6I`V9s( zABYp&ewHw6H!rv!Scmxs6Y37u558283ZH4TpJl`^lpgnQOi&1>r8cB_JP-QbnEk*L z&;vTDhkkOWwLY7Fe`N4Fb=q4YtF6m{M+Y>vIn`_sL^8bERy=plfJS1L|T8U0Mk|Nu%;Qz;Avvk>y)BRV`fPA%a@J9yyDU* zaD?l+)2($)vTQ^gy~sPX2@RD`dAQV@UsI^O`!Ma!Z7CLPe;}gMXHVyIwIpd^F_LMK zvfomwb=zb+H(>$bcgWX~SoUl>ZYA*T-Xxl%PhN6Siq?H;c9m%nBDa8=MzKIVYi3}fQrMxw4~7y8`V0F zNEz;jch&7z(7oVQX1&+mt? zUdU!#nOn@}E+Zed_?1dZPck!tA5@_!iOgvZY-y|;t7+JY!6q+JC_g@dN1=2aMbU31 zBEP64K4FECKJYS-7kJ#g_9oL)6(j&h|GwgHm;LSKvnS$*Rg(%`jPaGZs8+vX_6~P9|NzXfHG;vX}#;wZB;b6z+l?(s?Bb? zJHK@c-_g*v-l)c_F~Oz}oVeZ%UYk3|$2C@THHJ<(jAn9e$wi=mqc4n&COV)EgBs_` z`ooJxbh3*GgDSEnojUX6%>iX_Y)`QQUA@|jCg{mLWf(f~)M7apdLlsC;%x3wws3^h zT9sUuMB%s_=Dp!F%~vHE20vLoo%MA9;+hD(^KDk(NF#KmkL0ux3?xzNC^-T3w_t1d zWSV)O2(Ohi+@B5Pa4SC6Gvseo3G!uq|7Be0-1rh!la8@1{*kGE)1_)Jw%(=r!G*=n zIH<^ac3vKi<6EE_d4;wnxP9vFkXDr$0x4&%<%02e%g#)MCumnk54V|P@+pO-#pR6b z%cIXvRxj)O?mMsq`#$g4jNG{u?KWf9oN8BwHcA+bpU)1P-;vpi30%9;hY07izZ^`E z_NO>qE$*@!JJ)^jD>kJg>AHG0wAh7VCcOE9J~>e#i{K%$=FiiIgt>=G zGLgIgnDrHc&tD(mt^y@{qrh36`VJ6p&Df1SFxzVXJ{(DsW6_P;5Fy=AY-K+E0XYhGcXFXn%JCmQ9_{PERQe; zonnrKLv9Lt)U1mO19Hf(I);VcJX(b!V&s-QT-P<4Jd)z-PtKu}{=~!RPPc=%xPbXZ z6UR!2eRGWLjGOoU+UjS|`9y-_rDvA|@8yO!#mKHE2kZSCx1Ey&l)tk8>Jym_IjctB z3q8daeF6u(Q09t8Jok_XhTWOYRV=E44DC3!^shZ`J~Gj4Ag;8zHCDE{!jzxn3+T1|E%25cu}J4Cowg_bE~-ggLbA7{@0 ze3O}r2!UB4Zm{b! zm<=~{qy@MfI=ITAUq353ppz!QoJjhSCD3j=9-(MM_>IxB$IA7CAYmh{v(H`5hO}XN zSpaye$=%)m)KF{peZk#zCQ~b$kaYc~mi(IX+T}CdYL3x>rZxZai-$cs()E0;=Ew7K zk+H8bQ17G^q^Ujp2k!^ViI{A8oG2twO9Q_wFJuL+ zsMg9)uFTspcE}xfWqPw1+L$lKtI{hKn%z8%ucu>}`DpcuV?JLnb8t#bhm*e}1xo50 z9eO~fq=u4O#;f=bi*JN8eoK}P)rHqwJe|iDGXjZegZ;Mt9ry}UcS4kGpj_=P#V?2; z6Uo}~N1KCtE!HmVKB|qv!prw0%MW?8Wfp1`M6hvgTh02X27F65Q8YTtZqn~DRd2Pq zS4Mlg9fFGgc``qA@bqW!$eOg*b3Y#|%KuAWeiWU;lS$^xP%OvI?`9$9XdRtm@`fdm zIw(+iWRyc;_=*NOY!cpWmX8k-_V~xfdJg>120``0Amt+Druei8rjO;H5RpB{vF0w8 zy`qka0A?@V_QG*os_TR9#gN}_nUi0ImbHyeyJ=yE$HVlP5X)@2M(zHo+wE=$4m@G9 z_na3!Tpf$0z)4GS>T24V0wH+j(OaR1G2&8x;d)8aCmfu1B$)CL+tP0`dq3KEzTs14 zxr4w04jrJVv@V9hinZ>5X6IEyz7ur$=QY`#{ue_~C)^_NxqE*-=pISjGBo15yyn6z z#TzlsK)DBBj~3AMrTHFWK%scc-3mI&L$WlN!z5^UnKGIr4w-w-eGmJM_x+e7;qF*g z$~My+c+`d#Awb8-HLsOl2b()}Ju_cA?#@niaSD2ymBTSW=H7{9jL(|5=0G;eoWDJi z=Hj1ns4!}q3-Nh~Y!uq}Q8lQ3h@e$7lilg1e_(5H9vA?N=fBO>n?d9j*B0U+w<2)K!QBhE< zLD&1b3d6QZ_vHn;L(fI7NJC>^iJvqd4o6uRgskq0f8)Ph@M)=w9TUNx`%+R<%Bm(62OS+7aWsf2aJ z+Q}mEBQo)O9fEt!57>Cqo}v;C5o%~q+y#flUXPl_bIF@`EuqM38m|rCo8?R<#nVB* zA@U!eHBpT!VQV-g+w2fvu>Sb6g8Swtkynn$L*wS}^*97#BC>||4?*a}4@t~AjdF6y zW%leU%P*72>6x|_-h^Pf{d~P=vIf-fU$Yr0#+Oc;-!4^p#`#qAusqZzUmLJRruF#S zJIHsBaJ_q>8L#iU_2Y|YgMb~yWO;WRbB)DxEqS{r*-WP9|e~ z*d1hMUu~yNm*CFBq&t#L-?88HayowUe$<(3cweoU#;(=%WUaBrZn#iBWoxTcEuK$} zwl0R$q^-3Q)VGtxZ`Js|a}D|SfxH-_?)g6{02M^lr*1a3N9hF3j%Qz8{f-eP*~TxW zlbRDr?Zf@zi}zW&ao~^9T(nPK8LbL#pbw}lK7Bfp%4L)c(l=4Nf`B`eUFn|) zU9rPeJ@N2(zV)o5%7~CTFi-_Y+O(3)qM5;K<&Wnkx7yy4CEEqPX;1b6?KU}w zoA2=KDyx6LyIC_IlgH3U>AxwwJ6hc28hj5wD3zYa<$eNY8cqh)@E9c1xX_k9nqmkX z#du&xLiyNlmiBeIz+aCsrOy0g<9l65qfL}XmgrR|4{|d~!2WxCr6mM)=)bM~lR(dB zF9f_5q+)O7I$`eVFNEAj?3w&-FPzu>XbOFxW3-+PxfOa%V*IYB=nQjTC2_4L)~!5p zq+`jGkjA+i<80=WR2o=x?1KdRl6e=XuIvh8axEKot6IDQX5Yj`!&7e5ZZQx zjV6rNN3PEqV4|EYs38^epzD6JY=&^n<=OiAnWNoGS)t%B$8~hmhsGw?L1*HtZ5f?T z-$F|%E|yyl)5Y4t!hQLetw7|VJ3SV#mxxjhgP-u-^4#5ea8sdpi1P`5Mw2a<-LWwR zkM(^!r~QmdGK&F~+K5ZF?{~SyHjf;P$k8N@6v20!@4On0nc~^aVnA&r^#q3v0wdE*r;AwTBm!R3Ygd0v zWOU1^_i1QoIBN>nq58`W`2C+g860l&I`J;J&IhtzK23R*&Wp%7+>7gGh<9u{f3}_D zSy8tC>9sZc(`82D5iBuc_JTUHMXp0`)LXbcjXs9aBz(frBm&aWg`;HVajlt`*+BVoV8Nxl36YGjPfINIO z_&q%NwiM;UU4AMhT#66>eEAS2a3=ht&p-6-v;LNNHj{|c zTHFpd2D(i?22vOh(wcOkuBg!P53_pdZj!@B0WiDZ5YBQ* z1^L$cpP;6f(j%u>H1Hs=g{KI7-+hEE48@mi2m(t0LEg(u>EZ3l^y{43kepl^(l|8j zc})H>wOuZ`=Ae{XKG{jcJ=eKftVq0V?k!`niU1tSpWW(Um++zsk#czR56nxhfCuqO zy?m+h;WkJ+&Nj4JhV%``Sb7&?mI-WASy}Xx8l-oPaM`R_DeH?y`P>h*nDmH;&~?1g zqoPABqBq(As(~e;lbA`T_IA9t{{1HH;qytOE~AsBCL`~FIpuzTE<>p}a@y~ax8pyq zGoGniF4o2ztp#*j1$E3DV_wcJRp_{wiaw5yoQ8k*J2?F(L%)9T?6cF)gGIVhAsgv7 zz=PRe+x7E0No)NArm)PsmccjSlL#h=BmhoO_gbJu%F%Q|LPsDi95D{&6h!kS$Wf56n|hiq!#xf$q-hYsppr{9rvE*1osP z*p2TX6fwQ#Egnj=&pf0)M(DAde@0TCui=4BTAtiXPUTyO98R8Z!u?vVbK8zxa=@r| zcQmK_)}nH6KOSc^c1~2{q8TPVxsDM))44lj*W}HPu~$t^Qk_3QHvcPsFf}jh5&Z7a z2_p6j7FSoew%b?ex3nXi(LTx)Vt*w7sqT>##(%!ob8M(Xz-_lmOHz$Hy#e!{p5Hf# zQ-9W620dI5C>QO<7q2$116N%I-39L-_eM>FUFxn{S*=eat^bNNu0?O8#Hh*a03Qqb0qSC93p|&% z>kniz>6c|sKs@V!u133OIF(lKH!0HkeA9|&lRzrfFN`M+t*B3BdZExCJj(8VBJ_oo$%0`}H$tJlhB%%ovK? zj=DE5IA5g4`qMl8yM#V}OPRK#ecDO$!*EeH9yhhivBu7&(N?Fxza!m$38b|eR<;}f z+MTjeR2KF*5$|dvhK_o`rQ8@$C38@es0>xrSWR>1luJ|Fo6jCxo>ZW2k798dZVS7- zNY4_VEL^y8 z(E|pz_vIj|5K;_jRn#@Fno|mYe&CYl$)>y>WInb~?IhnVq5Hl{6-yoPAk@pW=j?UE zOe1*lLZHGPC(AE`!=jVLjG~`+urqy-{X*S>p*wK{u$JScDXv_%4kswi10H6JTixY$ zJD5_kn%uMKWCn}H;f3fOLMfbrB$Js9@Et)wVM?4Yn`^X?yW7N9h;lmB+bHPa#8~)g zPMtmn@z&V(or%S#GAf_usdlZsS*O5A+;AWs=s*AVupfGlS}&3X>T_wo^!7Q=_d?WD z4EyXT*HQ~@Gl93+N&Unud)%TZLwXhRr;Jh`FL@+g7MbWpVIow2Sft)xgQ$7^8sw*S z5yQQ)K0-<3@c^JBi|}_>=jdLJTr0E+sartY5Zg**^wtm%JOp;#2J)Vg5(qt)ErBl9P~FkHtM zK%g30xBMZ9zzQK|)MoGI6nU-hnQvrEAY&NKU!Sjz3#?L$a1GFfbp+XtnQxOj*5x|l=2Xe^hk3hmjb@+Tl0v{%kVl}FcmJW|;Y?b{_Olc|?%Q_- zj#OSJEf%H|xt()5^OLqO)QXkP4YREN9xVAo90SYgKabE^i@hYGN4duNL6qDH`xTI) zh^$*H!&N`+da)q;We3?tYJRNpmGa38Zb`p$t=0v<T8o9X)cyQ!LC0cRf+ z&~-qWAx4`B2Jha?rC(QAqYYHptIL9-?WofyYKhxNYbJIJpd>Cj9Z1JMNO5Z12Nxyq zYkXo8c56l<8}^@Bh;UwCf8WBStTf$10!!jvy_>S4^XX>g2<_m%VM0KPJ>}8k4DQEm zFsg2XbmnX~#h&*iu(mT*OfNZnryN7SY{?aSdApgHtO@Ged2rnEL-EFR-Mf#4GUx1H zXEV)~YbK8DNK3QWfji!Z?Vm0NdgbbHl5p9)cIdo|0HTzl?Kx55ZkIKfY;R20rQ_%I z89*Ya+yRAkdp8FLneNJI{4b5MKO;>Gs&4X?sy9?AWN}aXT;?iRjK&XQOzkfPq*^B9 z2W&Sqc@L68e3>Z%xV3A|M~^g19}9Nf%HWi6X>T5JeueG3eB&#=Or71a#`9D3zn*;3 z)s_voehO*)E38ap$rwGQdxFYNey^u&QE$QiXN6jl2%`5%oTWkxFC+lr?_ z$>bfk5$EK#7M?KZ@W%Gl{e;V_4Za->mbnDk{g#-^o*MW+y_Ih|#!HRI?1#mC?yx0? zE`v~v8-4qBHfQI-Og@(%DSb$?Lnr}0-@OLTw4D~J-<^PS{K0C##LPosciIbw`1gIn zJUs;anL7TEyNh$*oS99Mn{C2)Cap1)d(3p)9m6K^~KNf|=-eSXv-!c>Gqc*Y3q42eT4G$(Q=-xniWim?GDd z{cm%XddDVq^2gxpE(~ABROFRb_jrFlkuT%k(0E{^b_O5bKMC(QN@MR_F5RBHWTJFQ zQgIf?y;Gbes*M)?Y;dymdkJDo>BVxg)%eOK_XXMm?IZwC84p(OFoj6W+8=+* z;G!mFg5s`M-*<9p4+4+I=3HkT za~gCx)nUBh^|@-7-Q<%d;kJLtU#W#0M|7LEMyrlCoOv3t?>MV^Of^1%y_!_6bw1*9 zpkApu>Eje#ET2rj^T2!Qd}v?mC+&F}grrz+yP}a?iPH5I?9=Cs*y+A^&dwe=YA)96Q2k_~s!&k7G;bFl6Q3a~NRiba0WvFXMZ#oI8>NeW)K>u|#yUsjW@Y+DcL zhrZjd1KWw1phj#9?W9<-beq<7#s-u&zfGxO7KH{VB(4{jULk%D|@+xexOcn`{3|7tdyR!0_ ztVqkw#kc4u^H_dQ$5prJ&}HXtez$zc%}M&n+@VAzFLRuo{2%f;e{yjh30sRft7)fR1XR9E}GdlW9Mm(0hUU%jMZ8VQ_vTr)~Zv=ApOxB|4k$CwFhB zg^d=d@LjbLF)V>7@u+JqD5mBmvP{=_*b=5&zyR@@OJQQmkbmm_D|_2oM$6M5Q@dL7 z>73a!Wn&t@z_IpOdQ0yG?i+g61dmZDY~eXLDUFBcj;DrPH{xz;b1KV3)?>&fjj~J5 zgN{8m`(F*uHo{Yn zzv*OSLmfI+dyp7>mwi5C7*6D7CYYm}7w=WGZ}y`*Pv7#NUkVHFY5~6UR*S^}751rxu z?36?${EX9gdtFhEMF4A6aJ_!!C+utry)SuDs``-_FgX~GC?lA-6Hr#vKkQD=^Mx9} zwzkr?C`k$hKj_MLg^8BOXy=nqao!qpp!LFq-&f4F&~ib={o#N`uX73}L`6GbxPUHH z;{g#SZEyF18cr&p_b}7QEt75UWah$Gx(*%sfP@VjXE-hj{F|6nUsVF461vlq9LY( z_HVKRwYEg2BeDd$@e!ZRRMUIpi;!E=Sp#5&qogtKkdyb*c_oq{-G_CUeZ0WYK@2?) z-gt<&#$)2MzOD9WcoXGr(*?3GTbx(-V;}u*YMUw_nK(BVpWYPgW;FIGB8Xg|+84jn zh$&0Y{Zy5u+akevy)>WYu}llJ8sT^J>O$()ynG6*!D3q5J*e!*VL7$~2MF8p(q*{Q z#4H(HiH{F3txj$&{zKucD{ItitkuJvSTl%&kGI*?M#$RmAuY>eP)L;Bz*gDpp`8YX z{^agMAG9sX-ImVv*=5T_hde1MeQpl}nCj4Vhk!|UqS-A)4lA)H5bYhAhwpe2Nt_l( z)?v=D1uPUiLa)>vg!BfFNmquy9js68*DR;5c-p4Wv{dRRzrW%UK8iOrfIc`;lSSuA zll2TUmHmCQ?~G5bLi(?K3{64fCGiVEOtZ<{3@bG$a2}=kSh_`wRCH`mi*>`p^i+_)cs803J;<6t`Xx)=gNmHDJ7 z&giRr9YUmx^AQ0{F{5)5-Yp?@iEoYlyZ2KS1aayC6Svm11b!m38A#51Hit>cG0_Q+ zGp!_vrz-_GUy0vy;zl98=i3c8&#*F^vzy!E^Z0=eafd9_3<%GRkUQ05&LfMQU z(=2+8^-m?jFx?m~+Tt7{t`|HQ;{Nd6!sXWYYBoB zfhZxT)8k2Inb3AGGX!@L(ek^BtDBuCvz%<;(kZ3xuOqSUsgS)(;-sz9&vib!W^0q_ z(gWCVlqy^Tk5gSK%i9CTPR&@`-vMV5s6-uJ_7YiI!&rq($_rngnlO9_B9lvDrNO75 ze~qPCW%^i!Vid*jFUKH9i8G&}Fz7`(=A}-Zpo#UGlTEM3TO{1AiFe~kIcXebC_CoC zwJaTSu%V>kqL(MN_bxxb>bGBmOces^mJ?|;R2p-zNhg_3FXi@@&BLFJ@_yEiM8b7F zdFWhr*W+Gnw|_5_Q7BSU5{%?zX_0OyRIy0#++`9S(>tlYQA2>pM6doF7*d098A^O6G%?`wy_QwoaIsOWsfGc26(KgqBv|AXn*$`elzlI#HYwAdQ@gB<=B5S7L_TWh`^ry|~tDVo-qU-6nB~ViY9bhKC zP*n`6mR#t?e!ieoNA2Ujg;BK|Fb9ghQqL>s$hAKZ0lB~zaa`s3xX5D#kXbeCw#(us zMvz-pn_~s36(^(bJ(eo3_&`9EbR!-U)FEiY$|8y`DVIl=rRc=J3jOX!ui4B4vhAAj zsTKAh$Tz>%SW-ryU}Oqk(M}S9-pa{xEr**AKOCV>wzNnX2Nt2Fo+Ad^lhTK&d3%iu zBTsEKS=@IIzX7ql&+}`Z^JApKzMqNh^V75D9_OlbUN;;H+fg*}EMoAxqX^ZQHO>LEO_k9`{KNk(d zEmdnPs`t6XA53L4`Sx8<>hBSdziq1LA>9q9q=nN)Ms?ZE z>;#);9G(S=0|$j{eb%8a=bhyoSw=^(Fysk6aeT6ILy(Np7wQm83nQv&FX9?Yy7E{I zP@(lUDh?qstj1h>q5{ENo>3C?rVFT|aj`)SL{+W19US zQTf>9B3KnE4pbCZ1_5qE1LCrH7Zc@obLJXA4wC#FC- z4%p#cE4%~otOi@m)~%I|c1AT#NlaS9j|4DA06m)6V8gSJ_o$TKeT4H;YB>J;u<3pC z7w*qJYr?5ve}+l^G@PHS;j{CoMo!03eTO;Zl!fJ3zM_PYYI-qDUUs>_G<=adexat=N@#dCclB$ z&zyV!3Dey(`dxll^Z5A`&9Fr6YwpPZTUxMvfW(pLjQG*wMpNj6G3bURlj6iJdRN`N z-GXI6Ih)3_NAB$dWU<(07&y1cuYltg70}YjVW6&uMy(Hf`0cH}R~Kihn`hQvw9Lo2 zXu4Y*6@{|qXM6VU{DBPVf}R`)-oT}LW;9w45$%Szv%K8E!BcwPJ_*Z-UchBJc0sw# z8n}7b^dHQViPdmN0K1UEPEPZ}FetSl;n>U9U)PH|h!XVX*4dj-bDE>?;{GI`3_ zTKR&ncImr(GHZ&EPd;XmcBgNW0_+6YCu)dl;z6A6F=C*vj#i0Cgki`aOUPqPDE9KO zFYG}DbaPIyumtHs#`OP@Akc)ztkQk5x!^<=xw%FU9T5K~)BXwP^deaRLGrUR)%%%_ ztBre4kjWdvPUr9UK&2>#;g8e@^U#=6XJ=ZMon|#Dbl8aS%=?#^?%afw#HPD@)0^)2FV1;9;W^Lm z^6PuO&lfJ(d$ZS?bB#IXm}A`cJY#GTikLu=3NszXUKl55TZZw@=7`V zoRjP#1C$m>X_Ski<@H~5-N){hZ2!2ra+Jq>&{HgF_MsUlre~^_cO0z7WZd7a%B?-n z3c%oSJ1cR!y|x3goer6GJ<)|xNSNun>R}b~6OXQG-EPheSIhaXcfvmxSC}yH1F6w6 z7nI9XC03(!`{~dsLa(ZNZ9LiLMC%qiAi^ED~^{0S-q)-cH|NeqF019}k@>u7c7+ z`fs0Y4CO>_@XKJJ$Oozb_eHdy>?Zu_gb(cCpTFigW!rMXIXJ8I|OFS+%F}TZEaZ`J!&yZjk+% zP94Mo@88zj2Vxj-)JvNY^gN~VMxf{|C6mNM&VTiCb}n)AV)F3h-R$a|>uwN}RhruI zi-YB(IETtU4b4bGZU>1h32bR?L4(P1(_-2S{nAf(+%kaX9KGpSfh`+x{-v^}F~z(G zH`qXo!=mV{SniP8dF8W-e60;Ru!H*m0A#VXzH?PJ%SlrEt+5EGRJ5!i$5wR;4VrbEXJpQB(ro(glbJlXJIXt=oCoMrM;7pfreOWUFlMF;&4X zS)2?NkIZJ6W;1%(As;D{{>raR{;M7J`C%Bpd5IT7()M)q{8*lPZ931MfO9q2g=oa{ zYceNpNB6lcMEZ@Wr18i)C$&a)MOR6D!?s-vj0Td4bz57$2Da-H zr3qI6ALry8v>N?ss8SL!g^TC!PY(S-h`_^Z1@N%@?s*0sOTAA1XL!Zyj{r!SkV}na zfM2zYz--O$_NLzK{*!Ik8=)Uhyr@iI>XGWoz@P%7i61Jm^>Rp;`Cb;KRl95KgIQk) zfzc#AwJi%*vNZGntTJN3lo_k0{=48Mm9?l#>LZH(lBu$U*Yfar^O zHF|R_kG$St=QGfmdh*kQ`-mvmAm^Cv$#ThCj}(b^iBXVYr;}R1qsz^F25AJ}7&FSN zMKV#dXc#cdf`-JGI$0ObDVpwPzm=}Yp4iVqS*pQfWhSHeoZ4Iv(a@*5mUGiX##%l2!e0}JRV?5GN-fZBZ z6`rS&d&W%N&0;~j?dT#3g|=YvYiSDVUNkhIGjaGxoHL~``VQF4n+*H!PII_G(y`L^fO{dnN=feX)c4)u} z>_IiiM8A9E-(2$D4_~nb|9Z)2Q2H!nZOZfVR+b-JQeU?`_Fb3MKNscMWPvTK_L>yl ztFmit3&q~RMWGq>@VcI9GaX$DhC6HLd`~6xt3vMP zmC!2)GY8Ohx12~iJ>MpC-ps3$V_N~X?P%!)wqW3t*_Sl@Xf^gl_l318(85+E!CA0) zxBoM9y$2=_EdWFd<&-X?eT1EOmNzi2MES z>_1=z&!s0s6>I=MkbilMGoRi>qgT(G0BU!9r|f#oVmu_)*wE2Fv!uqN>u*R3;ZH$3$i zV*Rc9BQNRQKdbk^PBA9Yo2#9lOdFrPtZc1yt(N)hk2gTG&VOA|j7P6iTBw}v#5hO* z|3~2Z!+$*v_<*ENV)V?K2fGjLB3`EDFmYWZNO@a;XzCRc-ScQjki&l_TR;ycr5E`m zU+U}>4^l6^QW@(5T$|*Bz!kh&g%N2ag(nSHLF?XPhF)*1wLH*IwYFMMoV%hGIOysP z7E7*f$1yt?y1?Ij=;sf<4W0Z^o%-`p!bvwrTDKh5mtlTGuLvnmt9fALqTlbr_1u@a zkpC<|wo|{p;P*=c*L|LN4-e;YUp(&}bZNX^;ADGJe>ZVsD6hw~%xvQ!AXb}R@UFgP zj&w?~NL>!WV@`P}M;6x_BkZRg8#uDRc$jIGj{U7DsQ#n0&Nv17@RWZz+@Rn%QKDPKMchqk_ZsgmJ(pDz%D0Aaka22OrSy ziN+z+^!|Ov{%xlI^CL*|Zk$1yFIzF*M0npLgcDy>O%M5Tx&M3!i88h2mNnUFWbUy= z@ix*wo}2eGZCKoITrC^OX#SMbKka4z{->A911Bc>*i`r>ocC$3mHzIS|8are&l3+m z3NVGJ0QNx@Z3g#WKJ)jhy{8T*AQ>jfSz;VgxA#{V>N|NbXBKTL5N=~DHxvA?Gv{_>4~ztnr0@Losw zj^MrH1&m)Bg|9q`ABV2U1V|lewQ=I_i~HXO{o88`WD5z_UcShD96yI6f4`d_x9K(T zFmq4527SuC)c%*ApFp!{GvzWY60Vz>(|^5-zrFDcM@+EfRiNJ_&o2!d4r{Ng2E7Ca z`Nu8(-$vqv{s6rO9afPo=&vi{-=7(9Ta1__R?iG%Mqd4JSO3>l{`cMgoSpy8$^Vb% zL=2+T&MLo-FssGpwe_v=`TS^~3A&+k{_gnuIYW}%h z|K+#v2XNnO(3dE^Xb^-R^{)MwFa4`$h^V-ShZ}J;EV}#)A4V6Of`y}hz5@vx`=z_d zgnyteHY7_NBKiw%gTxpay(YXOgTjF2mH(U`u!jE0u zmLc5p*^JLmWw`%h5)Uc`9(rTHlI}hE6=N453BL=;?Vh2d9{$?rD`2UMUUCT=`Az;> zzy*gD_)-y0?h#Cu%6}c_-`)_!)y@q}jVu%V6}vihGR?PJ47Dedo=xXLwp+DBd|9J^M zU{Zbc)k*ff!;pW*@BaI8CxL-;W1@fFd@}+6D~9)gWC1vMFwsr8LcHo@f69~m7fTW# zv4f>;P%h3Qgi{xD>wj1Ydzqo>_c1PekpTz zjC9BkcxS{TZbv{~)O7LQ}nFJJ?JpcWg$hN-I1*Bc|Hg)`2Oq*68hJS8Gd zlLCOhqkfluHwK#4XO6i|-KB8=KbwvvwpjJ?JA91yKW3&#)C<6GcO_pVuC{fR+bn() zkqoD>f6*09SH1#{)L_b#O;}g)NaRxhbiki%IoNN^Xaevc?5$((T5pE~0IwT6t9P>P zsD9k+=P9+|J)8`%94M`x#mYL6&W)|ny<6R>cAdbX*C zW!+R(aLkO*aDD*;AQ&*AT4Fix!RfwM;I5LZeY3Szx%{-rHq3{t<+_q2wfL0p8lihn zhwLs96ly01krHS{zpAPeE%$a+qJ;i*>t)KW79T`% zjSIU{RP|V(T_(!6fonF4Be(CcxQWY4L@<^xe3T8Wv3Ccx_YCMbHO*ESr8&ANKl`2{ z6ffy_4&6}hlPMo@XWfSYnl(eOFG}u)Q59Dvkwdr0g@+O-;j2a$PLP~_p{3<4n~$bK z;{o~z+O(oDnoglSZvDtOt)5;~dD{$=r+O$p{TiJ4(&){+@T?|&ObIN2JEGI5w+jcf z1tdW(mE=$jM-h|ePU2GxutoYRB*jpovB8;aw3f(V!HSosXS|c~2H;Q+6=~qc9S=V} z{lFaC3&*AR+2HL!s{egN)NTN;_gS|yG-wPua?Yw+YE$Vpux#GcB6-J3pRW6zl}_MT z-v^f>5(;-ZUUn}9bNryZr}WtefmaV=oBe3kQf_4bL232clGZ*=_5l#$YRodW?GI1I zHXjI4T{Y^am`#8V->fc2OBiU97de&6Z7hArg!wVFpg;eem1`Mmnd69e``8 z6T_NMJJ6U83LsZo{ap2D~)c12P~eq1F( zq+9<6du}7qS3-;Ig1t899#AZZg!+5F!^>1lpggBHnYo`R7qxxwSeYzSzbE^%H%`U3 z5DMhsNZGN3NkOw8S^$hfOd*ln(1zin@*zEqC+xcf++fci3q{~1K<(!b!tm+psQTG^ zi(SCps@ITsUhU`bhJV5vmfRf4gC!a%oMfu+0g(Cy%Y8MkDS^5YKc~%6?iC<*C&>9N zgJSk1uH4Y4tT4aybGbo-E$D)+Xch3JHrwlrO}crV_6c%@xR_Aw>W!J&Lz}hUxZHT` z9VS9V&0@1gyAAmY`;4!t=KJgx?uuK!CX-#5l&ifPXSE#W3iCjobo$ZDzJ^R2VyS>P zM7AaKm)@geu?^X}b;X$n>g)T7eD++LP|zF&*GlU&)NP^f;w%F#Q!(#yrqheUX5~A* z528OBGm8~^95$@##uZS}mOXL)$#IATCXmtb#?*g3OGy}?ONBC6rt#qqW9 zU444FLpBO%ZPEqcWp^ePn`q++tlT}3kGjVgnx5+7V%OK_9-SA&)IL0U?WyFx#%ejI z24vgFaTzr1APg#J{CV=LjHmnWEbU_gh+GETpIX1)8k?8CZ2G*~quf^+?Bftl;xXPr`U#aF3_; zeyD5$Q0sb8_|CpW+I-~9*_Mx`f)F2c`6#^Bc5PY!S0k3s-6ijB;m5pb`2$GU%~_S@ zJhg5UJ|(kZ-{<8{UP3YU87rR|hpj^S{1eOrZ}G)sX2VdUptas4hI!cppfF)k1}QE| z-NJsMBB1HC2+#`hyywk%&PQx*Hdl$E6o$4;m;LOsoc^eU)RHl@F@@7rlc|2IJ-3vIC&W=j8uJy$$+`QvcDo~ehTIs$ z+Y`0JiPh%Y+W}wss4PK~yzjq=g%xKDWp+4$jb`h7%;p-Dj(FnEz)!m3>GH>izDHVu zt{bl|dgSZ1wjZh=)X65>?O%V}2-$uE^pm z_|>fJkgO_abAUW^%geA-1WW3LE(Yj7kcK3%MAaXx zAXU_HdyenU8mNR7>v!}{?i$Ku_r_%cPz128ntFU}Kb!kgr9thA{duVfam<{$`522j z>JThy`3ValW_ut3&GA)QCF9KPEzhMo8K=uxEZha{!Q8nd1Be#DeXv5m#7QSKooGJC z;J0OI2I`L(WoGRURqG8vcSX{O{pe2y9A)2zK(2<=I*o|VF=uWvPL=`2ziq%605Nz) zy=F-U=8shTA3kEdQQ*Rky+;TwI&{$M=6ampf>#5oMjL-q*WP13D?hUdMSui+_Yb`lRGMtfyVDd z`C1UUuIV~kL3w&vgQc~D*weTFa=D+s0ryf03NS|TdFCfNg*5x1tXQrN%eqJaTl=hjX-OVH=_=VV>?z8slrO^+*U|07ly+Da2XjJ=YMP(lW19uK@4@Z9trW0l^V+^=< za|Co5XbDLv!kiwrOTBjL59{YtP1W|O21&*gMgdSNXUi!WQ-eq#tgls-$6-)?5yqoV zC(jGUDbsEtz4Xv5a>H|UZae+*AL4H<48NM3*0Kq6vz=N$OA`2Z-tTKdtM%PxQ$Ue& zayP@jpWP})my2=zkk6*KLD{JGxXO$#KZ)0Nta4~PL}BStb;XSG$tkedK+_p8)(r6w zDee+baNqc8(FsL~2tQimOQ>_6Le5Fi<7HzMCa3EVM^cUJV%4;x#KCEnLqh%D?>g!8 zxUgR=8{=p#8_q2Sya5!i>{6Fz#(rFBv~~}yl9pue^5v>nGWz=qOse!G zt{rZ>FC)hCJ!kzG2-*6rX#l8&vd&w^IGTsJ^i(}kkZcDTA`Yu& zqWSz{hv=h?AxYpkNk%wD6&bXYR8q0yvf7}Tq?RWyLakO1$UBcir)I{iVKiMyw(3t1 z0qA}%;xQ+pIBZZbe;9{qvSXxLWmdbfkgV^6+jwPDp;xzxQ(hR8 zq;!7{mrh>H<=CyCems<(5F-cM=*IMV4*WIXBUly0RL;+<3Ig9o+~|g!8p3Yl z-G&tNg>Pv9QlN{HV4{HJ;<~lo$UppI?Qpg$Gb06hah@~Dal;4&(@5WI2ehpWW2#NZ z+s#gED$FKFTrp3WNhVUT`M3i+eJp0@$^?<)88g)~6g`Pyl@ejpnV8Jbi#?Q97e6(Y)gGxw-8ysr>5A?UYNiAgD4D!n}o(H(A4=rp$g zgS_wrM3`aNb>3y1Hug1{fXEwtpv3Yxn_cJq$i0Y7vEM`ytf{xa>6Cd zUIh*&U03JGQV3C_4xcUrT19$ecabIrSdQ(tM(o%zKLYgj<^9CKyR}sx2<6NZ;xk%^ zLwHWd&h9C~9a6b|o(G+DX|HQa_d-)+c_VtC^a^{2W2|o=Z$9+2D>oI2($A+b{|H;I zAE8e=nMrA?%6$@*f5npfX3e-c%m8gDUFZl7zwg_8-F_TyN`LyVwyUnXoTM;nWP7NY^K(2WMHnlscX}x4fFHvrkCM!b3XhbOWZkc+U9}rCy9X z2LTOltvH@r)`vK;&(P7}5yesWd65RMAhJ^a+s|@j0cUnM9om?Jc}zyy^I|Yabvn|r zb5+ukj>H6P7Ir!IOIPRodS@{i+YNWT=kE+ndmAN=FZhoYHH?R+$_b^}3tO$)a)eh2 zzp@#NHaHG=J6_sXhSMeQ&#|E@BEyv6A2_X>MpmCi^6(Kg#6{ z)H#0=)gSeGhL`g7rziRW%19&0hRGfPf_{s&2?%#XL%TFn1w8660HG7})W9Zla4g?+ z(zPCFPXN==Ae`dW>O!&e1^$rD`GG#Sx^ENLR1oJa1m58@La7rXyYD8bUyFN*iQ((G zom3TW0pwM2@_3nRKas1FOPf2l*TbpFycXms!3NXQ-M~?xYYwHAAipFmz>c))s<9@! z6VO9h?N1p;p&05U1HEz4a09C*$JF#b!J>DKEHvSHStH?MvvL4eF?QiJ-@glbi zV_8Gil*;sGHj79=#D8MB<}kFt=CZJqSb;kYUDI{evstk1 zx<83|He1+Glt*XP z?ebu|-g6q(t4ARirOBwC0|4EKd(I_wku*_yt_skjVN=IJ) z!7AGR2v**eqzIF~OLw-p%*0T4XPbBhkn}R~p4(Eqc)^}BY?|5eQogxr%ckwg`f=14 zg(eS;^WA!=d1ny<^Lh!L45#C6gHfF)oeYU@dGDoW0M1a_N7yd_fjSakvrM-GM_eRD zF!U}g>eJ9@TT9s<69}-5I!GN^Ew6?PQtio@xg*QX^tJ~1p$5%ULB0p!n(Z!Zvn=I!k zfdqe<=;vn|YPHqEpPzdO-y{?-%W`MES%mG=Yrg!J9g0A26n~6Dz!s$0{&>Ql%L z7UAU;K(0B_nQL$qsV4+UXx>xba^lfPN;b{KiBT%iDsl)ad0M)GVGS>GD%`U*fe(`eId z_QnlR%D$=|S|^Zd1_X2H6y=VGvO<^a-exmH7cqv10{|m)o!^fO-DM?=GzSEespM-? z^?)Yk2p#L;7&7-Fs#?0LQd?f)x4m6W>t+MEWnlw-COHM_wNqe(bRjpm7kAuaqt8jj zlM0D8-F6_)asAY}+RB1%VJk8D;x`)w)Cm^Od z?yzn%vUb9hH&Ef&ER2B933()xrV+)8rxz5SVku=>zb>8H217W^7;S`J{FGB z-s=JUc7MQfytc%e4b)$jBJ22}BZzvt{%ku%h5!~b?0a@0H?80%OCAvZF3CCQQ6kVt zXCzX}?iwXTFy}x=3uG>~&DH{3JSQ_+jGoS_qszIk;DhP!!6*>V0z^!_ zr9eJmFk!b|D(_Od8!CUWo-w-pWCn(fFlw?>*0%|#qHqvfnt2z?63sB#mRJKZVQg5Y z3XzD4(&bAHD(?P`tL6D4x-#sHHu&T+tSejixBAh8B!P#;pGjX;<5vBo0S+8=#9uF*?GKl^%;HSX zMXi0TeW))X;l?HTc(eKV;cPCK?^UHxaqOKMZLKZjNSS=7VaEB}R{P1vaWMkqgvC$X zJG7RA=^>Rf0w8K4dGM^t7{*R>(+jYsC>2=wejFp)`vKh_e1`$Qu$lO17eAD1;q)+oSrmrf_(`9!5_ zwNVukwAs%uTVdAOGVfMVBSlDp7V6Fy^6CxxI7Migl+^p&=&;2#HKzssl|E^gH{K zZ1x5O38-+X1d5dVPlYWpf*U(Dol5hP+=r#vMb+Ij_{N&^V&PO)YiX`PHxc4--&}z$% z>@hcjmC2M$7@JLSaNEExm-|AqCb6&A#VdrL$-1#EB=>4C+b00EGdHi#IVX+h(cLi5r6tEHg?0y@Pii!c3bPR(QIU?%Qk|dg*UUZ@!u+jqW zoac0o?R0<95(|xxOFyGA;`C>-fDG`S)w)29mJ34|$IeW_(K^|vNPrNB=M7pMpKdk* zpgbvTHd!}nagyg^zf^br1jyGtWeIM}0bO=IJaltK!)0`@qhyu>K;K!4)br2S9}l}~ zeX`b7WsL0?$wGWFK}!@r`F`@F(m~sD*!N8(Q#0*A139aqHB*vipD#o&y$pv}J%c?e zy^!&F%7Cm()iM4(Yt~=~HB-O=X>8AdM1is)LH^p)!-v8&ic}Z9FG{DJ9v8YTtsq?z zlGdg9G|X@5Vn*c(NwNTyuQjliw%?I^(SZ;4Dm`=W8=S~Nv8I4b*_b)KPu(Qa3DpPO zQXO;#PcU<~gLSJ=-227!%TSE=Ub!(jz#ZCeJjMK-`7j z3*R*^D3bNpBf$L{@szX3hCQnlM%~k${M6k< z+BZWwf!$Kv%JIm}1{SrEUkgAtslwa4?SaPFUYm zm3aU_%F%qCK)hq;e&eT{39#tW@t(d?Z7?6ITI+{$KM%gGsxk|iwRC^anI#e+IIxIL zA$>7oSo6Rz_5oo)gT*Wt^{kY4iY!V%M+kvfO5^p;zP*3&Kwmq+_M1LoW1FOc{`+7 zKBXfUE9JMrY(T1!JeFdrKJ-)_XdzO}LCE(`TH6Z&t4%pH;TcOshM43asmM$(%D#Jt z>e~hTRrg^E#@1&X zK=f&tq(izH`{|LgI)>*-Sf&}xL|xuus+TPLtXqb81S)QteoJ-mj1FmhY_q=rx#D;u zP;;7;ah~mH5n_ZGr|xVtByl?;zQZ~=PvgVEPX#FAaYm|6d{$|%!LjEK+2=X_T{YqK z8eD_WTQ4n7);QVsjh6UlsW9kyszgTPQz(6xN5gq#hW&HG?4mw8*)o?iMa8o7TP2vr zg}z(r(o!VT(csb+HSyXtIu6g|yyJ3^3mhQG*egfCX7*AeD;Iaei-rf==kAG#o@SyvfQiv%$oZBL(C~g-i7NqwhzKS z)O8L!#wqcqS`4L7kZx=Wm-~xSV#yO1$65P;%Sk{oJXSllY39_6!l3_r$j%=e?mXX? z*@9XjBLVTtkdBwu`982Hn2_BGlwQ$hR~=_Gdy-^QZr_5d zaxfgPzmx$)xZW13>F%t7FUPVyPgU2Q6{;<^t;M%r;`Vh8#~q!@aM~X@8V*4!H9=gv z3J~26DXg86hi{L9X8W@{>^_)m?oU-(AXk}0tj#+u+o!jZ8VxRz+I`1%jC~MkPm)C* zK^UKeHf7}>Y~>#`u%%eCjh|L`Vk{6?j^h4R9ZKEO9i!!rX(sm_5^#|?a&)Cu6-!I~ zPC9)0_2EjLM@+s_;nMJl*<^Va>#8o76E2-PX^)gY0-el)Pk%S=S%`xs|Am-TYNCOc z)5a>h+2*ZpeA;*(Dw?BB(>Pr`yS0zf5L3FMTP-|r{j;y~AR9YYeRq}DJ5eZlW0)@ekN)_s9QwGGz$ZM;H z!1DWb@1$O~Q8K;Md~2I&})Zp z9*u6bkL5``clAc?uiA`N8*M-+-W(pJSA;8FCVC&xj1kL*gHn^4t}ogh0R72vnSq?- z&BdGjOE1JJ7u*25y0<&=2Z}M2W=T_mbB))!HV1kKQim&jI}TL0XTu%B_VQVJhJX~J zC0DxX)C-ov3rtxaLY9o?X0!l_&QMuEmSr7(ySo`MLA*4{nY*3V&mY$^zOW8 zIIT*_clzP&hmNC%C>%!9RbMy=ouLhvngcF?7?N(8)u*!Kb%nmucpZ`k{jLc8gJz+y z?)zwbqzp|5{*IsfkG3bZ>Y(-y!ZM@WoOQV;JP+U#>BeX>|zziL}&bOfvcA345Oa9mjo>-<3>sL-@?qO8eYr3 zTU{@W?GtlPFIM{^(U%_RF)A|*?l`cq_2c4rM0 z*v3KmpJ#?k8jT>*aZKd1sUdH6TN5lnr1Rr9f--U1$nM|jbTV+(jF&g%+no%)@9|IS zblgud;(DF<47q}AIqfBa_j;pWoitY{h;Q-YO+cvpR#kjDR5FfnJ|-b2AD32zDj3%j z62Ui~U$57dIO$%Dc`>q+5mpg{2IMFSuXcz%dPn3GOca}xy5sdtrE&&d9afyUDa0ta zoH%uZsTO)oN6Ts-ooR9ClptYz@u3lIap;1)8^tK}IR`{5t+sDrGC&wU@gT>4F?nI+tO1 zp$3cTUr`m0mf^n54>$zO%#uKVF8T9X%qT_%_J^B5Ih2-dC+auJ|6n4Xp1 zf*VgR5{!U&?0hOs@H}!PNi4)wE|m??I2_e=ZABUH`h-`m2WG+biMZRinY{@dcx`NAG1bqW{h z(dJSCkz%c+lX2S!#QBA54wxls6aQJZj zX~NLb92=XM$w;TJ)Y@lhHq*XBrTo}5ZHKO*tezDD+obUixO9bTmEp9iWfR7blsE1S z`LWOp1T*6*WRxln^D+rm(=p+P*z_a;9=x=sV}+Pt|IedvXa-F$>aPjE8w=HFV!Eab zxMteYvgB4oAU)1Ac|;8?LV*h8%$VTxqz~6WqbW$Z;910U#);ky}a9Eh)Ff`3D&H)i_OtDO!XJVb_wJ zsY->+CeECpgrgI2Y83pDNI{A-9YFQ>k@^4eKG~+K0^EC%xL?^uJ3X_tKBrkf#tO1%z(155jRE>s%~L^*E#JY>O5tBf(_Jo z4IpchXw$hbOEhA`zTU?HyA92&bLYR6R9pB| z9hxZvL@@<&8SyCUR#Vo~=B$b0DdWJ{&+Vd2ntdX5+6~(kT{6bK8Jc40lZc=u0SSX? z8i4daLx#TF0M5qC*Os93k4Wpm;CtwHt0c(uMpK*(Yx zIPSR=B)SS^_6$bl&z!Whdw_hs&w&4Ep#JpT65-N!)f}7EE&cTYv|cFItXXsO>HMv> z_nC(k&SisxTZIp>Nsk&PHzJLmmWeHXW76A0Ja}^{x>JIUub9a{2kcQB`ZG0hY+LPv zWTK$pZ%j!Omu&!q!MzH4J7@UJ@-Ash^>~l)1?fkJL=BOj=xQWW@HbyPg(Ti&E6N?R z%w-)kNitw0$(V|8GaK}sjbwr?^ip0NSvK)Ko6qS_pfJA;cqVBMZ9=&{1x~Njt^R0O z?xRdr3+Qo|?aDX# zL6>le_Ko^r-x{(UV4`(vNT;gh*;AoBo|3a;KsT(Fjhy%XR}U&Yr#_z#1%vcPzNgu2 z6;`)x3=Gl2aBX*FB4w<0QF0@E{nnT7s7!e1yCrqmW+$_}Nq6CEc5d3OwpFV8dO`pZ zdeA0i>axGTEE<%}(GMU;FEMW2$KdsQq9QoU`64^HdEawe%zo*YHL7z$`33-OBNA+8 zJd>gtEjN)A2i#BjU=kwg$YvMU5@;^<-WU&^B@6FZ33 zuO1p>k}Gt43NlfkQhvC~sS4H;w*Kfq6+^EyGt0MI{s{{0X5)Epa+ph#Pt=m7x!hA9?h#Imm`_>@R zTofW3$26u#(zU1&wQdZ?XSUd;8vKMZ=UVgjP0tLOL4s+~obBTmfcW6va!n~&Rvl-| zb@8H$)|hKwg>mE(_(hg#jzOHc$zJlDZUeb)_9vTRF#FUzr_1ps4$HK3Zet9-+wo$+ z^)?&p!nb!U-``&xQ3sXnd(e{)2Z3Z~%*z}&Pu<-|Pk)!lj-1_?+WP8rBe7rHo6I|0 zw*tnVqdK)(zO~tlofSSYYcxLl2GZF4(_e~B!-|F_m2fvhTa7O{hFsv##du)|wKOED zhRSm0Gy|^yQQ)%q%y&1(&4OJN5Fy_gpd$=Z^_D@%JMZ>z<*YaF%kHCv2K73w< zvI|h4QwJ)xT#Z;7hY+Q&>2%Acv`oU0@sxi^{Pc_Z*wBU|S>D~Zx0g`QiBE7q%dkjq zgGXm8c5jk6oQIxVzYmiQeaiV9kQVIf7PGoKvmTBnOeZt|I!KG#_`^HqcuTFH3Qfn; znZ9-GJrcX$7!Uk&}R@m^T(fLvfxx9j-_|g~Maj_Cn59Rs36ulz zxj*$Uwu+ixTt6oNC>a!?9E@P(n~~W8q8jkE zf{S*bBP79o29;VZvxHzGHt|9>elhW6XP$vFETsZQ(`8o7WUv=St+VBRz;jP8HwO-~ z+Yf=hn~z3M<)K>y?B>z8%$=!XgWr%062)^h(o~WM++PJ?SbHl7mGW)^uH!bk*>lk{ zO2*Uu`T_;q5`+?u=1>fDDyzPLr*F%|TSBY6EsRV6{Ye@TO9cLbAHFW9&-2lP73mpk zL%QFKM32ePwH98z=j-RfeVr;j9kBg|0gp*99DAOjK^uk(*8u8m+3xCL^3lP4D(+83 zi*Pph8)VN6yBof^iDti}0w9#O zgK5y^)U}LdSzd*)Ed%8KU;fotg2X-Egf8S~ulU1B^1uRB0>)Ok?MQfJoGyR_Caf^9 zr2^5Y=UY_WYGQXj8_-cTgJrFQR9@Z$zE$-RzBGsH8q z42IwSTrm3&(n~-ONFJ~ad+UB?efJiR%`SDND``6JIK^$Y(lyL(V`$cJ9-rNUs-H>N zHw@{{r~ik&H{=hHoQFEB)4%-XdVgFwk2ajn^)0|RC^Z+UwaHSbWi^|__#R1Fz0wmS z3lt8Y15&Wzh{Q%@@DHy}nNigp&Q~MYEj7CU?})`5OV zYm8|B^5T!H3z#5by-<8}apFu<$=2`S^Ppk;bcaOpX1cuR3mqNMwEfHy`rP$T0Z4RK z*o|}p*-5$oGA}>I`TK|iIRJ(+>2CM{$*+7oT@<*{bVLV>AJ68Gxx%0Xc+_o# zkMVu~@z#&Q{rQH#(VfNwZ)ZI3e>0sw9}%G7xCHk=J+MaTmCs*a{rk}Vc%tZmM8F`^ zAu8oL|Ge&>cktsk;Y5I)Mn2b4LD;h49B@10xd<26`twOGiZv`O|m&ISD`iMpAb-g+`FFdlC%J@rD7z0ekZxgZjkeghW`|%`patnVaS+h+Wg=Z>j&P3i{(NiLMfA`$~XWV}=i2oV)KP>ov#{G|F`ajS8!}I+S zbCCYebN_567-Zpm@6}%YOXT2nThm-+&b?CJpFIsKP=Gk(sgz!Mx`j=G&fs2$;?o77 z5=GM#)u<;srR%!omp$@gc~+v=Q$N4ZvxF?mc60;vAi9v3t< zQLF6l_eBB#1$YHw0lO(F8gj_bk?X=Ynsv#{cQ|pa-V@Ro4Gw z@4bVXTGz1eZ9`E36%_#i3lKp-=>k#&5$OmD(owo}0zq03K~d?whR}QO9T5TPolp~c zfRIoU2q8e;#olM1b3V^`XTF*5uW#o3XJ#~UJ$bU$bKm!M{VpX$m!T`>w6R#cG89>> zMMZP;3krCX8UUiy@K*D7X=h|sSG#KBV%|-i%Qc(EVmU9G*nkvJNU@VEE(ezO{nOrB z!ef#aqqvLzC@>?m)UDXOuNcd>+WAS;ev${^y(Sb|PPn1EdqrQxd|Wn?RjfZbZTVom z6b#MIH98zCIm72z+)&aHRe0=($mIeavhUW)|K@rAYg<1x!Bk0>y}|E3DinimN3A38 zI)_ugy{D5EXJA-ilH{rhZvS{DaB)~YdxF!zSVT2@r7f3GJ``7!1U)df?Is{KvRt?JpH4ytS^s=C82gg-L}Fp}kg3!=;?fg}d`)|AQP+Cv$Lv@m z?goU8n^cWT^8}Y0Sia103?{4`MfJeQnL_r{8i13U$+6KYG5$vV1v`O`o9UKt&k6h8 zUQr_e3B6H2plagzk7L^<3*bEUAF|nMq3m4dH8k(z9&)_h_5JJk_wzv*5Gd}B z#>U-doi`So%M6u1%2}cN7l`$i>zN3tO`Wx>*uwv)6J*Yv*4NHrz~ERa2P%2^gCrM+*2&BdeNxmYP|} zs(ndf3)19|O_W2T^x{B^T$-HEQ)d!j1YG)F+??QqzH4)nbUaSoq6cZJ02!fTgLMSq zO!-1UaUnS|dI0=I=e>csuq66~=%@Yo#p~I;b?T}2I(#Jf_9G*JJajJ7Lg=PZx2$^; z#!dfJ`O$&klHC~Q6V6AeYiprH%OIfqP-ARqgb|0(vN)HiVF=zKr^@NA*f@VnX67P! zIakFGScb5QCCqPF$xc1TZATe&yCiy0_IGAmN>ClLuF}+Pr30QHkW;cd63^}x&Gl_b zdx|U(4QHfXl@zJlBsrq^xF#5+j%U3YSu&f=&oeCY{|nO7-%y79yr}qfyFJLWs%Ojo zK_m6M=YXhWQ2LT(4Pod#LbdQyXyWZVRM1B+uk#t)@g(9RPoCKZjYnZ6Aiv5snyN9b zzzpFcs{l_+{|Z}808~gehUZYN%67tnGG6$Et*w}k&%8T2<}(d0=G|x>`)hTt`$5d2 zFFw;zeij|e#I}u4)hZ^P98zo~ceEO#$hs+MzPorvx&|X|t`r+pWvAaMNgN5qGs4e* zY*-yx<(jB*DmQQ$lozm`2Swbq47p{~-UFR$(=qRyH{b1D8El=eahR%-dlt$F0xx?l zSyT|ZghR7sY~$t+L1#decB&{_kbzf^8yJ+<86pck z8FGQPKO8X8SzDb_;WqFLCU{Z|j}vi%n57kg79bxW+6LxhIwD7x+0TS7lOftl z(L7uTL*o|!f0%ozxAv0pU`XuIDXPxN9gO+Z7&eV%M909XHj2-%t0FaMnj&KZG-98B z=k_3Y8EF^2Hjm|f{ZQvfz*kl7b5PjQeeGWfqZr!&_m~3RjDm?`%j8wgYhAGyUWd9Z zBTzlDZ(0>5`fWhaI+xW9jh2tVq?2`u zw}vh=$B0Y-mKiKN!W)540|X!IN1&G|ZLpg6BdZ)QK?mO?akjlMkehw3H`#8evU?%o zFmIju)f}I?wV_8a@TL0|7Ap>WJ}su`5m+}TvWKx1!%qr}fq85to&evcSyM!0v$~-~ zttT}@SPoT-n(A_Dv!E+|MEL85_ql*x@<|MzJ`UGxLc6N zc55Mhbw}}p^#jzFYxkigCuBT$>x(qyYjum+=qe)vA2f|q?n-U!Ocr!NhZg(Si3$>% zJ03tbqm(tW;A@2)7;XjQ;!UlA`>(yWlGMsliGINr8qFdBts+)kWE6OwJH*lBx^@{5 zn_=0p_Qy9ID&b$23AG}$g2ZmSDYtRYdMJZ(EH@XOluI*7vcTwL2LS|5rezeEK47hW z1qGrp=)X9R8MP9ig+%*9n8pVGRnmh9>kV}0FY#8SpJ;6XOj6`ltBy&>WMdUm^8 z;MWof49XibZH83SWkua7H2SZKO{q;>a? zz88+|wb^xqsNh5q(nz7t=9v4w;HV32)9%`Zp-GotplqwNi1PkMTZ!xUwexN{G#qIr z{c#$r@;(c3VV4ezv|EWx!HiMZ)!i^0^qgwp;jL#uwSt)u6U#liVB1P?^WLNjZ56@( zhozoGbtUiqqQ|Oc=KN{iAXZ5uBj}PVaoS0$07jeO{$^$1@^&X^AwwN5n)&3=qwg*8 zm4t#@9PJt2Y#(WCADxiX8o}CaMk~t?(QG9-c{%c~C1e87?yuf}jzdn9i({jRHi)9w zfJy0PDziuMSD|ds*LFVbA+TE;O=ORcEa8)b*{+2KjP#FZN0yRwhNa=wCl%XI(|nAR zL@R@l4Oc;eAE_QZvI7L;FJ%}EsIzBlWL8-n819^fb;K( zL`=3S{I6o-m?&|Yl2*>T4b-7_e`Ng>OHZZphUAev(VA3tZ5Mr={+6JbhEHb%$5yjk z5?LB$iXJIuZpo{pWPWMz1SO)fZP-LI4J0nH&c<^!OK4DnBeRY$lox{Qnhl=<1)ipwR zJ7E&BZca(o*w^+m`?ss{^K}^RF4bsG3A}yTO zzB;sLD8eUc1+e4A1|$#C`;n4I>Ic?|!VjMWQW+cz>vOetw1LM^HIE<*Ae!ebWl@~e zohchVT;>|@{|I?T^{!iz2Gh;#&}2h-C~dQw^!^mX@`KkaSyK)}8L8^7=~Ao<7BT}D zFYI46t$g=NRr{O3F4vphuoM>P zUceuVs;X!XW-lZPJ7A@B3mDnoB?MinP5@CT0_g8b3zP}V;dN*1m&Y!fC9Aex_hv=< z4!ql$R)&X#ZM4gEPk+14d#4_Pi|JRn)nh^bF#XBR!l}pi$}Lp*)k*sn^b;jcphRCip z_A-}FJ0T*9eBW5RtQ~Gp3r+w##&?dCjWFR*%_y_iwdzfAWcL9c0lm&e_3TM}X_ULT zK{@`V0P2+_L$jc+yhR+X4lk2R+7riw(l&jebcOV1yz8#=8y(omst6|Gyoss;!}30h zuy|q5BARyV;oaN1TZeZBFFyRr)mb`h^0hr!KY`~od7V=rF~vWRQzlifQeQP?TzVHu zfOTr5V!SQOrl#HC$VjQm3GFMxS>3(v`(ug4l9B zLUInH?Dlf6Da^iMOMDQ6)r%ao_~Ea(n}on918EgMJwqPtr7!z&D86|HjUSN7hl$H(=0b> zstQ%VH<$=KH^nIao3VvUhfS9c6 z3r%0}^=9{QT&XTjZXw6c`B~{(jxREq^NyJ7*(eEC6>(9v?qKsk7>p_#D)zpoN<8&t zthFP;O5mRzE14T-LRcl<*r17X5ASFJN`VZ<6Ev?MIn77ejyK4K+?2G3KWmt)bLMos zt?+YQP6vOwgx;&fl6W0p(zfj?KDL_$gl|tJ=KQXy4$m}_!H_NgEw-sYKFo8xO;)oT zT{EgK|4C|)dUY_3=V!SW%p@FkbT|*$v_{MMQT47z9!~m7LZ|Pc7j|DsT-s5T=XGe> zDpS|~+^Hp1jvY+-l$WJtTcfC3WL?#`w3*tfSw3bcqV)lyN5d!}gDU{nyIq@lGLoUF zJW=6Z4l9lav10a0`o*am-Dg`Au#q`+!O>X@_s1PCix>DqG;Pp?Z%Y?ub}H!iLd0oo zF9q1=!%N@U_8bIS7!2H^=AEQ2olO*r=ykazCNB|{bSoHmuw00XZqd~dqnh&lqdA$#d2uL(TrPX09(8F_Dgt*-Snc- zR5-wS&3Xj;;)Zk&O>C6&lR)}xunbeLF#nOJ?kW9N+`kg98VKo;cJyJEz#a_eYB5ZG z&Dc1Ft?xqwong{Q&-AS3+x|(8&o8k?^l}AP>6R7&oFUC8aG?;I;vT z&7ul-ytYjN4D#-g-P+Ts%j*T{u+Hk2x#kixf$>pC<(BHf!{Oxa2hGo6b-|1Nif4=E z*mw-Zr4?JGQpHiO&qDwKk%Ve>Yicp!Qk^YmH|!9>Ma>fqHc=?msMZXe9(MQ{ET9*}}#WrSeCOOg~=aOt2MZ z+FRshn$AXWHx^l+-QBN5c`{6qf>m#Q8}_9P$Pv4h9{`7351kRuD0+ie>Cav<9(Foz z%%9Gd16m}br2`AOuGWJovGJUHrSF|kV59Q$Gp6D@!a03hqxmQ%5Jm|oW%QbfM!6fp zCEy=>gHA=m3AfYS1IO$+&j8M~jRY+r{nohd96wHIH5MR05Y2-v=gvsRq^gYQkg3> z%FL)&?S_KRa*Kx?np*HU@_I}Q!Js8TJ0M`;H1A3sliAiZUUE8gRjUa(pCssEA0mWS zE#YA+)JLJIKJieXnbqGO4Nr<;*(y@*Ti@yyl&t?2sp+%uId1lb!x_I`N8SY3Q)ME~ z@FW%Qih!h#O(IybY1^pz1f-Noc%=mN>3mzSh(_K^YDU5v6(#S=8~pS1aBfitMWQKHB%s{<8mn+NGnc(!Qnr{{kzSZVSv_G`V?zo*QWn&+8ce->yc7U$$&YF$5J(BfVBFMUl~yvrS?k1@Ui7IU z!T|u5vfsGlR%aQSorxlEOyX;whyTDGXsE9Ud!{i)JP)L@@FonNJ+YzBbT#D(Q=hBp z&o3|RFX`q?EgHkA?yp?pJOVB-+2Vd(y;0Ahg5Uk!gaQF%nyznB${Fkdbj}_1{ifwi zHOiyctg{v{CDK~cMXKqZN65iopo&3~Q=H?q{Q z+!e1ym1xss!La=xA%0nm-US`?rqwIpthjZPx<@d=X8tL?!PR?KPo&9u~p2n?nXFWwu(;*dQ4a-)82EIjlxZIsDQKfmsoij|sPI;n9Ht5E=| z?IiI@_*3OD=?dW#^n%ddopMFxV)=l;b1$!Z)&Ek3V^uASU>)H8YAuNwINi|1!U$QjW!(&X)H1%M|@?fcNd z8C0DweH~yhbDs$<1T3baUs_=9(6k1|kS8=d3KDws`afKoFq=$Aav#~NRQo(Kdo@n? zNv#Use$Ay_@TJ}=n9=^be$&yrWb!Tvo$Mq5pNUWY8f)Ywf?P^1=q{fqQN>MHcK3cs zV;T1FrqvdTY#W|Qc46pGp!W=Rv`mKQyer!}UEhx37M;E%arz@I!vZgpS^Cm+EqFUp z(VQ*kcm_mF2#ZT;ka1$4mWark#S6O4-6me=Jav+uU-}qY$iu& zK%|KzsNQ=$_~s+4{YGMRM?IjjoTKIKOt*9 z^syI2dRpLrqPa-G(1_G-_IA9&JbTrIBI>Vy(fbuKVPv8&5@y;SLRWJFH1#p-nZsm- z(|6Yh2|<|ql`$?#TxrF^eRzKyhkD{1pODpDvM1B{990E9yT+i?3M^z^GgJArmmY## z3uG14Irtn{`$@p!sIf2ejis|%fz<9-A~SUqv_=0nYJmaTcMjYZhv^4^DYr78LGZ~< zrUszftU{yK5fQ@Wy{vLzu{9bUXKt>t`626znj+Bct|U95SFPMWqx^Br`y;jKRi`oc z22H+|q2Xn_FJ5rl%7*V;r741cOJDJuZmLM?A1xyPVXp9Cl z+cQv*Dl`w#XS6TXq(in`)=J|;j7?Yc4#g^oIH_2?1XvQnV99+(EEX-)KL$ZL8$Ppd z02iXO=)?PJ@`_29i|~!x!Tjoupi;3;J;}qiQbba7{{dF3gImz+lNKSaU58-s;6=mh zfmgD+Is?J}jx7MhU}nLrdgg3PU(+0ABO5L{u*2;bI+$X*dtOhY;$K}T776u%qw_I)6_-jl-36-f)f`#B!_3R!32NB ziH#t`>4A*NT{gUAD#WIv0HR`b-OqKIZayINW( zJOk2Z+aNq|XgPP5junzWBD5&J4E8c#$Wq14-&F{y8~zHj8p{Y@iJND7$#03%k+Pm0 z{m#faUsR8)V7!&&LB}FKuaY1{Y@1o#<2+91?QS9?ivY6w<-|JarX8)ab)ci0vAD2X z9zff6GcbwMyprA}JVL45tar`yMotkWo`;$GnyOoq1=d5?PJr812)*La5t<0zj!F`c z2C2g;VEfdgsoj9lm1W}{;}Nm>L$`2!fL2$G>Z5TPiPORtfC^Ch5gXW;&b^QL#83K) zY749JmLzKDX3*;MQM-#Qk7Zcjue^}B`U4nAKlLGqznFMDQ8aNA*H8{AD`)n{c=d

qK=qpwHs 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

rw>It& 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 literal 0 HcmV?d00001 diff --git a/docs/static/img/astra-rag-flow-interaction-panel.png b/docs/static/img/astra-rag-flow-interaction-panel.png new file mode 100644 index 0000000000000000000000000000000000000000..6e106b316c51cd4022038797844a33f1205fdfec GIT binary patch literal 168580 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

j-5QNp5Z;XNOzCeK`$sZb9gBz9eM@$(Q;8= z_m282aX?5?PI~|7jE%FI&k7O#8IxS&q_=<91eva)ei8P(=8jLOg<)9L*faNNyL%C# z6_B7{`-mCkk@UIxz-yusxsP6*l6D(I<3by5(|6}^N1-#;HmQ~tAr^)&io)~m=+@mY zbxs7?UCirNkiXK@Y)Q2DXDklpdCQ|Ml!qvqc(jA#=jwM0=ez4{>TY|8DFJAKARfZ6 z{${+jMZ%?;hvtSy4t4h=n(ut|Luj6uTuBGW-W%0p=frtoPrl7wf}EgqH);Ff74TKE zc>coZ`KG|1x$COK%2ct4QNSwcs(hnbahR@Dp_e`98VJlKx}hM@DE(p@#nNrJCSm=T z3}^xr*zlx)R%*KaSb^+qEKlLXGHsF|&^fRYSsihzic=)lF3oGds+_AEPHUFt&UJ0V zWGXGro7qeJUWng`{hcRf| zY+{crA;9gY8rCfpTY;1>`F1a|dv}bMm6aCR`^+oOG||290yZb4#k5;Lx{ip{_Gn}% z*Th|ur`O9@u7v*@gBAHHb~QCCfeYRJ8HMAc5#v)`KwGy535P4+rR z!M2%s4W2m#fTl8OQpFTF1RS!NJGDYvy=(L95!^V;=UdMV6F~J^`Yaz<39xT3feO)j z7|8VeR$A2qnmRrzs)2UEFw*ucL{S5z`@uU{!^cKCj8tE{GvzKFS79cVdRY7Xv8Z+P zo^9+k@LJt2637}H=5e%zy!!Q)E1?IT@|}>w({Lwh)&*H_5vE&7y1FN7ME_5&YdzIs z?_G`9_R`YYHrs!UkwdDG*R9i1KW$;5RS#27S?807u@i5RVy~7s@m}H(|J$;|1Op$k zhSza4m#(lP5xtbDn_2C~E)>r8yHt6OK|JlXTR%E}!tLjWn`WI23>_O%jqpQ+h`#Pf zNj~hYtvQ*j)^D^@-ssyeBnHTqN%*yy4;r&Yc||2zo97s{dZ+&o>MdV7$~naS&O4V^ zqJ-+>EVCdN`+F*p`!8NDzDpil*l?v@3sbM@>lJ-pItjjb3`Fo^)-hK)le}u=xV+b- zDX_~+!;|fgG*+gjASvvRo6C9l91y8vNa zR_T%7o!-a}N#4=fbLV4v*qC*3&a2V2mk@pPof5Z;3Bj`dy+`~r-3z3Dtd72hUX&24 z(3O3V3{$FJwN)KUR-Re6l4m+`aoL#E@OH;cLwu#OCM}{JvhzS4RLer(Sgd)0rxNN% z)V{ZvIiySESmWB4h+fl694@4bRP@{XJ4v3^4n11$dza^%pe<%L{iDUw=&6VziJS=| z{RY=FO_mnV3rc5~3+8V{%q)SIN|n4nYa*nk8Y_-L$o{n&`z^wse*C#&eT;Y7o4{Y} z{f{<~t?K%leqS91v!3mcD9X79xi|H2cjv^NLvKa2)enuYzR?^;@p}ij&wK_oyw;8h z%V1J|-dt#t4@>{FSvRMS^gE}q-}Lk0VYFie)6(vNNQb z>!wDt2N#UPs@J90y)DO2pey!_RxK_|EF1k`bX-qD5VBiUt{-gCh&I}uW%^N!M)46k zGQ-^~ojq8z;2s)0!Z1JC&}*hhObT=Kw>|B#TQk%y4AB^1^JG}ZZS%dC`?ZCyTL_;#2s9#7%_8HxYejiPB zIS3;L?O=9qL4`4&LgP!Qg3{DF=Fb;4c}AVLv=6;MK~pk)2Ac&bwc z%^Pt`RmW*#ru|17E<{n7fZ@+68Nw4)#osFPCb`Y=3_HasllA2Sp$6v9ea(uWz1gox zL$OMPu4Tj0`|6dBZ&w@Ul93iWO~z#;*K%scD9`d$OCMPy?N*()D%$f=-fFn`Hg)#0 z|BofttgZEh{&kwr(&s^s_*QcIekGHDt&m#gJ)Z*)1oObP&x#@c(myw^TLBH(jBRJ?XB*~9D5%k2xBD?)hLs-w+6XjgQf8ti<+Wz9;gklu`4 zl~g?QW8HT_mNGerB#CNhj#c7x^->Z{`dHmG{epR4YaU^Go}^n4+wcEBw&5Q}A_lER z9y4b)~KIu_QAUIaZ@k5iNW3GoqC^)kB+-Caj+GJX2UVTBI!985oa#p}6r zHN$w_+|5*3Bo^5j{rmU2Y**HTegldgG@#3(0L7jHc_w5lsv*fqQGi=IDn*6MHi1 zwRe~gT|D14rCF@UZw{N?D--TkTCG&nArQPZ)Op*bdUQ7|lgl2u&Oj65)ZJ}d@{|hD zWlu%K)|SS7s$UC9CIi>IER@BAU-J8Dz%OWKmyX|5h`;$OZ*T&jmT^XdbyeOw!b|Ca z=9!M)kSPGqLPO>a!QT7M6?5;p)QTmb(i7W79FNa5(9~{(eZtl04Sp6WICZYco!u-}QrM-) zib?#sXoO}X>Qbbi%Wt(`tIyn6raI*q6&tjKO^7uXczS$&`r7|zsG6(Tk@#`#v!;_j zohR7kZ({RRz)ODDZ|$& zP$RiyR?=i1>m9!fr_qIN>0&Q+*tDCl2b*QV9lve9zK&qM9v2I%^F5?q?%6wW2b6`g z{Sok8v$)+mbC1ua&RVeff6zmM+gk_%02qgFMuH@h-832Mc?x#^?V9DG_Wd3Gmg zHG&H@I(4EG^PYhbMjFuw>zYqfqT6+Sgs!!#`^5?DOlQ9DGd^^nPn~27mpOlmcnrju zU@X(3)0xq0#!=z3XU_XgfB3e}xLbYfg8T?{z&*o1m}MtMNs>zm)#f1%Jv+MOA828w zYby`KBIrtTW2jMgfsC=g-J{jM+X~zj!12YHr*ZU_BY;{X<17xtZU+tqGs?fV=1NI}#&eTLEkNv4& zM}?wPgOHmSx~Cz^X6iNKfWU}fFED$!-(P!7#A^9C721aXdR|K;8iqI3VbKa%K=!$>fQa+aW^t$?}rxi~B+_kJes^?mrZo}NcrYcwY z5G;)P>x7zRNb9kiGt8jpd3!Y8<`@!MyxJH=^YtndWO&+n3O{b2Wc@mhX2Q6CA!*7M zp)Ma$*1uYOAqt#{X^D_{*JkgBwH4-rRb<=&E& zR~$VDvA~qD&W2jIKf7U_amKqMpG02v^k22VxQF84`Knq#u72!Y`)JUSl?e7)%UpEn z*&=4P#5h;DVHHYE`4F}{12iEcJfz6S*~7x1vTFUW?Eq3G!l6QhBRX}@V)6&{_Rhv1 ztxQ`p3*(c1)2OScB9sI6$=iK1LGtom#(F$SBk+3E`Yg_F95kyhs zL%$9INcxEMnUj&r$G-8u7O_HPO(~7SJH0Vrgd7j{Z&K9Ou&g-*|1n z(skC#l|mF-#BIIVuCKz;2LN>9Uo3#{5*aBmJ;@>-Pg zviTv{vu;Wm_bff&Ip+RAV6o5&qmj^Lo##CceRMScD4LV5kW}vSK0JSV->6@PHK;+l z0u(CQ3x}b>-aYJ>i2ljNiK7Ka zueAf@Zwt2*k!S8G5s{Pqy!YJ< z`1&+9ZH*%*VBLgoZ;toyF7F+qIB2A#K#*fc8{~Oy>zzx2S z7`kbeyX!^b)%>F0c81L-)abSF8|?rz$V>fEjIOo8E4;u6&Nk+~nh{1uZxgwnq!_~S zHuacLN%=D~%U%AhHQ;&+;7>X~%FLFPI>eZlXo-M;y4D9weWb+< zBx~+U3}5;oM4#4ke0FFhFo=t(4ma59^YQ?c56DC$T{?7IIV>-X-Y&yfIBX68keH_m@&T{`dmleDBT= zc<$pJ)n06SgHwG>?6WR41%XVe@ph)cM2iecFz}gaw#(x(JltXMN_c8)+0{2sgx*BK zU1aXeM&>hqUFhfh%)eD5LnoAifXaBeQ1fu#`l*G2xx001k?(TWWfpUbNm;rma4_Rw zME1Vccfrn%hswJ?Bl0JpZ6}Tyh73?c5vj?@|nVWn~>!~=gpGGOBHQ!*2Zrl*qtCsj(?Ky80hWMDj z&Wmyo?Djnv;E%3^t=l3Y(0P4el${5MH7^<(Cz!w>j%C|yGo?Svtr-c)uJKrFgNKz& zn%!d{*EG;XmY{2kV%ut|fAj*FD+?oztaNW81{{cWo9CT)Py<$tB#pAt%K!Rk zPq_|$+ z+NkXpFfa1M+-~WtxwU!CaxOu7Y3Fay9E^Xsgii7DqzSP3$keTC+=0&)NGEHgL2}z1 zOug_V9%Zm}B1!{Nm3ZcfOd_ZNI@<)jxAWI+g$qpM;8!rKC2OjnkA7Jv-@{@`eI%Px z8s|H(^0uj9;l}lOPpDNJzJYB9<4B;Zh`;*8B7)2SsJS_J?7vV69wymRgprt2IM;AS zQ@Ukz+oWBD_s$QuznE34CY~`l{ak0v(qnf2Gow-z4ZKb)s8fJfg*d!|S`(4(H{ZBl zXwJ9K=F15%r@M3PsJ517W99A73A+k(J-}67Wp{hP5ts7Ad*`ieiSr~e82=mrqb#PZ z^Dz6&uNP*pob!4;zf^6#etSjlHz$vR%ASH#mRDvMiY)sd8bzzFl<7j&6tTIB{KkoY z_=))!&kpYQFJM*GCKU_(%Xj?8&4d7fLpw`a%rd$lyijlIhUHG-{H2+RqDxpk7e%WB z28-ww) zbcn{V@6?WU1=~RJgqn1n{wpPDsS`mA##5#=ig3{>C~s&ULJhTWY%Sz_%U6K z==*XSQF9*QyCorbu!ZY1HP)!`jxX2{HebD)S~40QWb4MiDMB}tTfOT}2rxZ+=#&<} zqgZE3gCmELxWKPh^QRz$rxZ`aug#2I^BgFtw#%y1C^Vr0YmaG`MbTG7o;JVulbqZm zGF>LHqu1WGcE)sLhP+aCLWE3aQXomfN~%Rf#C%)dQ^23d_*93J0Ha#%G>uhVJ2hK~ z_~Q8I+geY*&Yk;JSkyoNR$ll|04z~BwU`P%v;RLl`~L!m>cx(Z5taP^g3Z5y^zVyD z=T2=)JMorZ_Wqyofxme%bxa_V?3!<04OQRo@m~}E*UMb6*8V+Q?g5j~e;V0D@L9dZ zHH1ku<+QoY{~rSz{ys20NI~&Wp!k~?r;l#mzGwKmy!k(^po6q?=c!fvSV74@0>O^| zr2qcBdwc(8zJJ4%f1$N?SmbF3DXOgN@PGdO7ee{{)-$g|{3jLjugLxl(Eo!Ew+nC$ zwYJ^bQl%Og{^{?(S#zass?XP_UX9k-e{=KCsM69r+#zsFQ?)PL;2%f*eSTHmnLh2Nh97cKuYitg}1^#1|#{}+Kg`+pxW#dAPt)UmQ4Z+RHGBy>FWA8GWd z*0G%>Pdj$0=lv7uZ5J>Sh~%Dl(A1qflY!JQj@CeZ%D(qGG21w)7kxA44-37+d*|-! z*D~wtpSdlbjQk&G{n*!M-0ZoDT>(IQoMXa&W8`c8p@b9$h}FF9WqIcY@8vtU2S?$j z_}cGZVqjJC*&g+jjir){A_2Z3N>!ImChj`j0;F_=ioX37Qofb4VsP)j1V#sJr^^&4 zntN&6NbS4mE;RE(Hd<# z%w=u_P=hD$)xJK6D%fr>+}``fdgRaY>i3Oo@D(CFtjK3$b!Pqad8)a1hv31xQ-MC; z1w~inh91oCQGc7%{QRJ*tDEBg$`vih(YGF7Z%)3Yq;4i&mYuxZ~4$oDx-R=L=M?k~Ez-{a@leL2{={87JCOK*Z%ut%c3& z=`q4|;AyXm!i^hivH!R0nEgLg9vpfpLW%Mbx>+yZFCi^V!C}AEgiMujbL&qavej_;=EXWa)NC9YKn(y`s(^sP91T3iqflf1NC8tNjExgao`oU3{T-sL|BQ0do&W_ z81pOPSIVUp=JlI+|M$or1S)bTI3*B5)a?IIcQP|bg=_a-#i&t^y%cs1p)RZR?c@t_ zPSD*sjXyNd*Zjlhagq@pjW(sj3w_3>uhZ`h7YYUc9sikVJ{xs#@bSin-h_r3M+O%Q z7N$JnouW4JS_L_4n*0W%t%eToJTBRCa6W4Oi1YcTZppz9 za(_(!pZv!ZJ-;v^#%9gN`?06GZ^$g9zE!_N7WCiJbDcQKXY4p{WA^@Hvthy?G=Q*6 zEf2hiljZojgiU1|mC!RLS-W2L=L^3M^*tpP{hvGgyLnbKzqT9|aha=I zo!R(px^c&Y!M}UzKPO97+IKDU?5|WMsT-XCmN9=}qmXDV^Zk2voY|9hLF6>AXRnU8 z>TTAme_T}PvwHZkW(n<|ubcH@VTa~U{~ed)KwyNUQ?!}{WJsh*KrDc`hJelQa6T;{UV3BM6a`{>;F!0Y0&5%(0f zr>iY?ke|S~g-xtI*$sa9Py@-pCDiN?rEjlgvQUh3)ZZ5SKQH-a$o( zQ!cm@>`=gf&^T+ofTcVjZ$n-*>rfe!7&Q~exSEs`J(Xd*y2b$!tpDs0z7|H`Q!SxM z0Xkdew}{@+c-WYy_NR?96H{k}gN;To5}gS!v1M&VeyB={D@}aHMvo&>VNpmcl|UH|Ep5`XGhOLWFdpS$C^U>UCCDj@EN7id;-4 z>t?i`w#V~<>7A`QA3q=X-InSk@FgV-&8rn42U3R&+gAhVhB-);l09&0ojK)3^iu@! zo$8f+v>*J;7yVlf;JOgloF9Q;g<)4S^!qznFFRUCWyenC8f@=X{OBm|K08QDMihxj z4y7))qX@|_<8z1}L!a8NL}7$ffy7l$`uS=+CK`(zxN`=<&xvQ;}j-|KaawSh_^&^ zQs|a0btH!H3eL0&i@fGot_lCSuqz{)^hdJImHS`tX;fCHGx?(2ti-)W|fVcy* z_s}nKRW5n`?-f<2XsddWCD!=-7eA)!i^uzM6Bt49pQj&%Q}x2k+>r2}rR_K6f!jm2 z3B;I!Z#7)(t~O#?akJ3{g3t~Al{1YokfPwcvDP!^_qn3mkJK<;WfJgO6NlWt3hv!M zeCw&+jt#cHIznA*T?NSFbeYTYG{=-zZ|!th;`rS~H5}55T^!5L{ti+9I*}L!+|Ojb z9@|Mb2?}PaHXJ?LZ@1A8OdIX2A6gw85c6hy!lUjA5{S9!%vGBo-HAEV-2q75@{aP% z*2AYcpYQs^q6mZC4%|6$NP@xs?#sf$D}!7w9-lM-PGP(-rsL6{Y|LNB^e-3erJ4d% zpm5Hg3WLhi+XVD0F48Q$E@~xZeKf`~k!~jJbWe)ozXgI6RCvrR&%uNv;tamCXqs4dqS0-~!XP`J;CKq01m_}Sc9$#0= zoYk?_tU5%-55(Jqaz=hlO{HfqJZ2oQ)}Nu@DsAmCZ@_!}Y31fWVus(aBiM$VQuuJ@ zIWEPcPJEzpBn1X@*Sm6NxIlHf{YW~>CnG&gkDT!6;Cl=rKxz{{9pU}a8`DYjHR{d^ z_NbC#kVNqTD|)HRVW79?#CyV^n*A$>cK%!OlYXVan zsFV?*^gy`R1%p_XYxP9URoO@eoT<5vigWLZO`LOWn+(`DV8Ji^ZXc(d4$vgqmqaLS zq$KQ|f6wH>aon>^MFo#-FSDw>6>T}x{i7)dr~*I6Qp^7B)Acl&h=FHHqVd*flrD1= zdMzz{z+5P< z^(XT2Ji0R9+q zFp^6P*jS7IShvcu89Y!4^x0%hzyx{mbDQg~+X!I8e0Ym1KM)IO2qa?CcFKU#H(C!k zH$8B7H97Hdm<|``W5-V0-T79i>rSXSY>9cjk%aNEMK^mabI+zeB10)zkGq@TXFBo6 zE*@MLJlU0mb=^*Ru{q{3*(K;p9K3AQpuy-%_)5l?x^DR@bLi*Yb>~snd${ZWWJ!AWOEX(R*wtcCy%*%US#l6wJEX2|jM9tn? z@W}k=41MQjJ_LNrd7_$kYgt{7ot=7vm&7;dg`Yke`LU!i4+S+=*AZtg{%$(3(3z81 zSF)@=aA{UtR3YK`DKqDVKbGcaABNNc0iPhbwa~wraojo(h%9s2 zg?MBlq`TCqY^+`Ym)|JGdzq&>qKSRlDJl=Es0Y`aM%magBic5ZnMvOKAfMG~7rDWB zl1I^3n(d!u%D0>P!28n&N?^-a)KmzxpG54qfLCPuKtQfj`u(>${9Cadoi~W;lGyh< z9XMpmXAZ;R(c+;p4m}TYO1v-Ez+u@?5i!j1Vz66t+t8Om*-rU*{?eF)88_7Q0Nl{9 zq(=D@Yer-_>E5Yk+uU+=M0UIZv;7}5LsB&!lP^v7KNN`^j$WY*7e^G~~ACCz^feR0zy5rL1@ z*!z5YeO`5cZLR5`=v&CxtjmlWXCiukb}748U}x8{O#=0)D9&j27Ic0m5gwtk+wdbh zH{pu-OKi!~wX}hH5JD*!99BPLFCDB#hgr?qfr{&Tn4629EgOysDIzH;NfHFUBvsBj zUvqQu{9m!udQMc>*?cjfZ8h7 zMmBvWDlgL#6ZIt-0o6Jq8zWaUTUs)#?}TASB-UqgLV|LOIc|M6_BAV=KM83`_o_dP zj~S2dGDuA6%jIRnBhsd1o0_}Hyf$TB$$8bh#7Sw)f(DV1(Mr|Z zB?=QJt@$P>)C)}T96)sYL_~G(&mqcxS&TkDh&w(#f!Nx_o|)BFzzqe^bC1%pfOSz0 zWm>_4<1D50%GIRo6)!C}Xlw(aO{kBsLhSuwZQnSaFZ;e%Yiu!=QJ-8l3 z=if*oey6v<>{4p&ROjeh<22!bM3?E}A@)Z1v{9>axxm9R1B^T*Al5Gc8T@UD`I&6B z&}u@XY-8!=%hdcOC1ddQ!D5apCM&9O+#&dN6?*~9zNBBFx-R2oyoh;eT2A8L4#?9G z_Be8#7mw=N8IwHk(YV1cxpiJDwg*{;oEh(Y>bO8CMD1_eJAJhB$(Q7Z&*OF9R7}Qn zl98J+`k9h=yvtKAGi9qlSbu90+t#eeepli}5?URqoi7kFb&axNh42`gnUcPTzy-s= zg|ed9?{e$4M>9%=v&BN_-uc-lt(cv5gb8QG8muP%Em@R4e{T6UmAPMUP6R({V0G|4 zy`;&3^*HT+?dG318sg0eF!2Mr%g4lMus*G2>s;=&P6OSndGBdGHpLP4L~Io=gcb_? z2FD5&8VIcNM2uE`Wcz3(z7SR}9o8z3cspLK_F~DG=o7!78|)JtxHcy}QY~S;^r5*) zBt#mNI3E1%p)umQrel->a)~k8%t2d@v-A<|Yf>UnbeDs9=&-uE17bVI?VGnpI*=Sl z2h>}D#6M_+ffm&pf!H`9YE7?PiQ};1Rqx*pyhSZxGak~s_Sfg`|fq~C$udXzI7 zmPGT}Z9h~%sHW#fc79x5?Mm6vmkN*oa1sbtp028ImK<8Mcd=$eM|wx&oR?lHyG}1ssSiRku!poqC|4 z51hal2o;!(avnF|aJN*XJ=5fu&~vT0P(b%ND+F^ZPGDAS!@L_Ga!_v~i>)bz;?+8< zUc8?mZ^I$Y=+*e_8r~0^FXQ1VH^p_H@Xl5__x;qZ*I^rr2liTN`hWCzin!TNSj;w_ z0^;82n}CfkX{X@N(eVCqS30sK*=K%vz!m|<<*vcFZ$%=ng8TGNt;XOfN^cAxwkli$ zh8_30+V4qrjt&A^xCA%?CXe)0eOKn((v`0WTZA|X8dV7E=MNM=PC}Tw^w_~hpYvZ)ZaJ&8=os-$%wtFOS3TLSvRt20>C(3 zhOLrDHE3=EVo*QRBES9%ubvnefV~}u3TKs0ovJzPNJ;P>F^y0r<^X^;nGE4#g}h!{eCn*k ztzb9s!;*)6B2po^nMsEsD-o6np#0 z?SR#I7uOn@GdGrWO&thM*BS#+fwSWL(|m_@@Q&<7n961?_Nw_}DF2g5n_^8Z!?(=? z(jWy{CD8-Rs@;#QgMbOsW?47UpJ3X;EN{szHh;S>#~HiQ&ayP?v4cK!;80G>It!tt zc#q7xU1X!cjUXHIHBeu(!j#eyIAgRti8#zv3^fG8iiqw5W}%x;Eb(!E zx!P~uP{V5PY4Q_w?0f)xYM(P>tXzqs)U}G;f^5De-dg7BBU1B&VYMDDsF>AvE<(4;Cq;7Wesq{mZP=u5*c{6t*Eu=b9Kx-+oTt1y zS+wt;neIA|Q(XS-HQxxva;DA;aeb;EuMvcG)zyPZNr$Zs;^e=x_+kG7bM?TR#moJ0 z$V0ZD1za=Zfo-JS3+A{A^dL@w&((u+*9EsKQHtv&&%%0HN3wHmCuetLtGD+;c>#O- zs(7%SktW_-VC882gLHD+s`%lYmHGS|imw`nNgmkPvMKBQDX3@54hP1K_66zS=ev;4 z!@fkl!aV2`b&3qswoifQ-oUOeQBSgUE#fN>^fJf|21A}Hq1;9~8hS(egO3PkD;COE z)3;pA33W7(5pwCMZKOl)A0OZ)8T4t0PNFCj|H{yEhH`-TznjgfW0k*Vp${+82$45>4`iw9LL#HC`` zefefT{*~qT?-a+6yM5|AN@W-(&)SzuJe{}~UvBN>7r|hNY+7m>eoM2NUM20Hiv*HdpJSHzTIc&c~c?6*A`Z$z$i^b)8+><{E&S!)iwekJvIN2+Tr0 zxe&eJ1ylBRK*o3xZlJm#wq%WB=Ng zK59JR7x0$p5~aU9>CaH~_YDM+TmU;KK0M5e;b;H;vwCqZiMZz<=y ztCpUo&T~qNPB+FrRY*%q0IzFUED+vSs(Xt$J5i6Ewe5gpN#jwaHT$jeZ1fi&Fc3)m z$O1pd@bkVD)q2Uy5=f1&*y&4}k@00PBXfO^p!!h?5ssZVu_fhumugbr{A(pSrv$z( zxb$qco)Z~R%Pl`uFj+)^8ErAZu#=`1HXo z2!3<6Ir8$NA^i^S#ML(O5FRWu9@UNW_&l?d?QNE4Tc0i*NQ*01J@Z-$GmZr5L(`!} zW_aw!r`$TUo_#}v4^3gES0MKwf|<9;B=C6x_fwCh{~##+X@vhVtpHPkmz*8+X-Dcg zRE~xW$R~6-17xirC@Lrbh$p=z7nS;(MKY=nwqUj zs2)FpVAm+FClX9XqHd;~{70AmuB`5vVDi^}Lr&nqdLHMZ8}IvsU8*=YRW~A=Y*F9$ zHfT^|IWnO$h0hLsf3BUsKT#ErN)Ccgc0o0ouaE>rI&zrNt6p7J6)RgtM39<@%+LS*9FMBvp_`78G!RA?h5}wclx{e|My?ud=ND) zFzLs>(JSfbU(!THnfu;1QNh#ef9YmVYyYXt7&=t>I(GcCGU1u{;I|odX+eN=#fkzQ zFDSWG_@%|K7ku_Q5P}yC)f`;lCh*#MGGX+K{io~m!y%4r!0%?b>TcU>`OAeQ1sEm7 zJk-Kj{6nT42GVESNnkx8v^UIt_|nHo1f`$%zlV=Kqb~mMZKk;f%m5eU_@wLmucu1{ z$si}yD)HoEU`lOXxc85e@}DPZ5%QL7I!o+I$lZJPyWafgzyI|YNEt2_OCzz#J5@zX z3$OkE`tQ$#`AcCtcn;zK`ISJDuGN4ggT*Lsn;)dKH`M>*2!4MDI1sPsoIe{Mk(e3( z#Jqg&KML<3O91DDw7}*rK=9EUbHC=-XGMdJUf$VF(My2+o!t0e#uNQ41z10<$gZry ze{AW`C;WrCPr0{iN$OYMBY-Ob7!AE&!OHjhjDP+>0@AE(;7CZ7eaE|h`oiy{{of=1 zx0e4TBmWbke_EOUY0v)+O9W}bXl~Z&|EO-6iT1W{;k00BJEahCmNzYglvbat9gN5( z->h}UymB!h`on_%!w1MsfZc;!`$Br2VDHBhcf_*#q^=0;md6nqApJ!CNW#ldOpIy? z^$@KE_!Z_5gmn4`1`65G&RXe2Q!A{flFvVmo=XL(*^$;HM6I;Wol`8Q} zIgZ-NA$B98!h1YZ!I;SB{_xIpy1N=J}#7 z%%LuhbIDkw%Y+M-VZcH&8-G{@mqFxY*Jt2qYf_B&NknqyevhbVZt)@2FnR7|iF()1m6%{9~irutBoXzz_JIA0j z>rEX#b$d3aEvVRX-Mab%3BgR}l)r1|&qMfTbq%2yxwNxBamA+!D9ZlnSxb8;A|8ENg_96%6)yLDxavg4`qzD}KOcKV>w31B!1k0JR1o5eAcb z&^cIQKB$tTpZ?jCd#3;X<0I1Rj6Gf1H7A9M6#DLWYd_UK<|uigW!U~yHC)b8z?bEo zah(*^r&1Pf*WEe861d)`KDR;Jd-^Yhb}v|F!(p&idjpkQ$*Gco89-mC;9=I8#ar&1 z;z}70F7|#<)9@ZI>GLIe-X-wxEIb89;jml0n$&N-R{JPL7zeM4q1W9(DjH8*JaGIbsMNI^sKirT*=9@tXu5y7)a6=&N3X|@bQv$M%8-$s{`~K3VrJjqgN)a z`T_D++l%mNmyW~rRNj?fi(r{`kjr#@lGh;u-mb*)G_I^+wOld3_R!t@ME?lO&OViM z_w8xDM(UgN2Q@9bO897eUWc@>R!j9xrTA9KMxB(}7bc(0RT8BK*`Hbcv--r3zj+N{ zP+OW>b(9qg9TtP-VMsmhIOkcbOvi~Yv+SW17w~D^<%6wRgB=^(OrhQU(}JSMeGKN= zR;(8Uf{i;m-Mfb=pg<`gEhcgXC|Wsg+RZBYpeMHgwKpyMc9rNICAa>BeTc%qrB;xt zgR%^>(U~L=?jd$r(7DG<}joz4(N1rvWCSoTYn?7LGf%l+bKxsH*QR(<;)$Rhf zXsHF+B>Jc^9AMc^Govwa;-vtU46ilZM_AW>J<`0Gy*>fo{dtb1|5=y-@)ZYq*cKm1 z_gr`45soOEExeF1LwxqQd_eD!3(-bywTXDh6@}k>0cc@)Hqsxg#H8_}U5vbw6$RHz z23#*cqQH0P`SX(_Pa>TLf$@` zM)W#{Hosx~erdW{ZHh>4*+d5dxjYz0LUQxIU~VBYll7iJZ>FIMut|W zh~=L#^K)!g9nAo^VP(8tN7K$ZW_eiOSzgtLtCV;zV2FFdiy7FUYMo<-Y zJk>Hm%W69F&#c(>;wU;JT_m^wwwUbx5AMF<`*r(0)d=fb@NTaGer=n$l|&a;zu%JFBxqW8NG8*RN|7zwnUskUhK@K{2 z8*FuoB-SDLv@8nR9=XFRj=jpbOsA#N3D4~ObUk#GZg72_SwVWel1@a=@^OrO2 zAJ9jWJm?*luqVlS#?3VgK0Eo|cN5)^GGvu#fD!xEIr(X!vOt(fTD^56879t^r=`b zV_;gg--Fd0TKU57uw+>h@ss3%ZK-qL0Z7ae3b3!tn2q9d`4vX>e2mPC1<=bQH}ao^ za8%h&yg)k*I!{_giB&hO1;2%;>q&hysGd%-j`vXBNfZ0tX@}v4_Hm6NzT8 zu;`;%o5F2_z|G`~eEelGb*3Xyk}jER3#lUL%$AXJaphE8_Aiaamfa4UcC&!0MJeyA zLMc|0Q%VEbVzK*@scG^@=Lx%w;5>?8ub>gGytXRTm{qS$hSTUQo9N!sU^Cm&X2`_K}3 zZrhIVUd80eT^=&_dpGuf9Mr)&Sknt#X7xL^=cP@{E-S}r7|(r>W{K8zgLYUGYvrgc z^U$2XIUSkgfoWDN_Qt%4W?5mcY%(NUBxC5-s$yChb^y$7SaOn^J+h}i5Ss0cZFStR za>@7&Ztpg}ZC-&L5j-BVZq0{IVh#g`L~PRyCC(;`rnlV2qBFb}%HE|-s6pQi{TFi0ynnyj2o8W?huD?bfeHE&wyM`9=bF9}9lY)hqEieV3tw@&VHJ{0xkk>F?+qrMBe)yV^Qu-STy)46t z?EJ87%KX(fInLUTr%wJxYlfRU+hjEChVK0vUnaaM_B&>)jbB6nC8b(L)TXd3&%yvB2`A&|CRn=(l4;#YQuA#TPDv%B;vBA0x|q4lzo zfmfJ~_tFNvqx1lHKH#c-;j|{NU7X#cZFHbIpd!bi$GwxjgS|72{U%8^82rIU^w<_T z^H!YW@%~YB@%EJwO^<_M^JJZ`_j@OIYN`#r-|6@?cC%-c3Zya^Th=9iI8s&DPmXf| z0czJ7#Xsp;k45hqtxvnmvUZ0<2&mlPg{`a^!}nFJW*Oeo`-%mRN`v?ki7w#tr>lzB zsvze{!sM!bj9Y^@~;SApm{Ph}YP9-@#}*T+qh zITb?gA${C>-k9&_)_rsybK5y_k{GcEyZuIo^O;zluS<-wo;$+4EX7H=aq z5i48?Fs=&beD|Znf1?#SHb;(Tl+SuIp0c@{YepV_z8iRIU1vT^7Ro!~7mm*0XX+<< zJPqC^Jf%vXpcC}<6Aq7mNI*09LYCw6L4)dAb_hdf3@sVf2eC1`Z;f|5W#JPD&8zD+ z>_pc2oO)gMX5-OhYr=bKX`;)f*v%S%>&2*MX#&JUa*ct#&*I9y6DEHx2wFU@pB23; z6+&p>K01aPP(ONb2Pia_mMB_W=srTLuj(b-PNDa`9DI=0`KH&pL}A_O8)Q~?d0M#1 zc7KH2F!}D8dHV@+%7TtpX~pmTj_a9WbePc5ZUHp2z5~#|YoaGLy4TBi>e!QH6~tW= zy<>i~HFG;nt)0i`pgFMGhC#Q@?T<+77KaFSvt*q@fCa$H{f{t*!d|6P*%tv-c?qyf zq+lF`fOCCZ=t>1}GOFgQW}yH#{9f`QfMWM$SItz!2SgltBU@$=nY@Ngo^E&1NNVdy zJ?bNOF;2{borJ-`C~eO|fcds}$D2)^-Kqdnwcf$Ksv58Aq*X#rdj2Af0ziBA5L)*) z(#mn3J`jLr$=k3>MPFEs++fYE&_Qk}sH^6vSlncIZXpE8?-4-NLJX^SM2=U!*y!k&CNIo7kC(KIhs5XjS5O_2;!tgp{l zug*4n%y0j1)Xz|RFfwT#>crpfClYLYda!{?)P0LrePp0z`bb2%-%t`)ZpvdcRJA&a zY2--pH0CPK{HDDapLY{zXOPsY{^ch)2W|qXbN4Aq{fv5Z`${S^d8&ZNWVtsJX=LB( z$wEm<2Mg=-PncNKBsrgYBTK1e_*{eEV7`x&I{-V>j_WtSAc4Yn3yCm%!wsmnN*8?R zmIhJzLE-hS$pfG7qa))`NU}blxuTL512{pwnO{2wkOm~0G zJ)0An=sZ<5Tyu*1gceJ#YbWY=ty$iT2G~jPv}fU*MPHDZNZs=Ms_^=g@h|3il`A<_ zit-|B@u+mZQJvCZMDx2w5@9;xoA)aybCF`$lYJsPp?)N z(+G+-AmHNc>{2Elv$@?R);h~op5U?lp!a4A+77!f zK0lULe^X7@X_;R#h$MMYa=RT{$-P<8SXQ}TKD#$-3kc)#VQWs^tDsn1Sm$a);1QyM zn49{0uacN>y=;|NN3Rd5B4+%kv4uJpv>=JjY0~ed(7u9N86DJL*(qJ+NG;3Am|N!K zLl4Mb9>pw|&+j%~VbWlveJ3ZJ@Bx>yX|FYK6JfmH&3{E*-%Uotu9*x*QeItKVstWu z-KNFBQAFP-EELT84`0ayK#~*T)3(Sj;;#y)9;%u95swf@>o}_Y09{Zhy0*%5QTJ9v zmy3FbmPMFSv0fASoonyJ#00$PSWkO$6BVnpb=A85;0N#E0CB_^fnk&R4GL6QYp^r%|g~;5emFRkFkB5-4lpEXOV69I$D8%qb1> z`iTXu)lbpEqF%xx<|+vMRAg}QX$pWw{~g(t^Z<2rfBmqk-ETN2huiwVve{fo;8{{lngu74OSzT# zY1KBmbF%^{pVE-r|E;#ojDfb|nPt zQ$NxV?`2%irlXw3!BtFs{O3|bD84>^4W1ZEQm<|gk_^*+$uH~FO94)q7D+qf|3nb}vcAgeI8iUM;5Yfje)Y{h zVw^3uhQ2Z4a%ZAneHWafg3H#R%*o0HnNzOF|9}jq{-?8;C>#;0SDT#L}S&Us< zeoa1b3TU4;rzqqo?OV;oUYTxcGrQ8oy?jJ`m09$RTWQ1`aBOP&vzthGyGD) zrcb*S{_l~0U&25B^1rqGpAh}Yo&Kfh^Z$zWC|`f5T0Y$s`YW?}4$^T0FfsR6hqHe5 zRd6{W0dV5LTHu$`5y=dgnE$^Ysr)Rq@&4C5LN=`$K{mbTAo9`CK;+VJUmqnEHFdRn zr8_Rcr?+5LRn@G#yx(9Z-=69u=g`P;{p5d1jFgD>^kfaK#&NOQ{k-GbDzX-rI%gtT_Y&eOi^@sl^V5l8{o|V;&|0mhA>BX}vHm{f+F5KN`*b z&Do{c5D|d0`Virr90X!neeHZ~IMa7X>m?Ul-ky~JOJO~2Blh{Zi4*yq^+6*-r_-ip zAT>Jg=%$?;XEitjo8s^#s@m4o;8IahH3Ey>nLX$}nT?y|j;yq8iCtYr!W%)iDAe@5 zhNmzC)?KkY0`fjakJr?7Y1B0Ao>Sg;warw}J&4|D>@Gjy$rW&1>$7b!7hi|R&1lW1 zCnwTo$h+O$nu*f3B)=lGn_XL)ZG|MOfA-44Lej}eHQwRMAHL`(AKHK|e0hxwCT25p z(l<7y0qYkzXA>w5II^FB-o?kGTCrsuP+9Arx<#FgS543>ja(cNv1yyPgH~x`5 z-y5xe9pgQiYcP`I;$YPhYPZ*}*GHnqbmQo}nrFh3Gesyx)jtiy1a7_5)W)74G1t=mb=CQYT)slPe;O>u8+*7WO` z7-G7MrBjak;*D;m$=6!mX|gLdo7h|rlH&&Q*%ZiwVtXZvoVWSi zu#F}V_I83(PyQq>2spvc3*XV7{Jy&!of*LCiFmD(;YZH61#q2Zv0>|~V?u+gc=u-a z!N~&W{=w!fGtymni0Ia=7S#hRP4%j**FqMVbsDIjr)pf8Q;3gr>g zO)O30reU)Yhxv)j0q*eIeNxib1(%gQKDSGSPy_}91Xx!e1W@Nulug(dTUYCUvF1HZ z1hl*pXnd8Ock9QGAB6m<27Hjex?U_fkSU<|dZAaKf{$<7?JiIY9OCx-9y6>?4A^U$ zAwA?XyE@Y@SJs+?Lt%qQMK_w)`dQ1`Ir^S%92^`N0C|X1A6;z00%4la*NJ5Zht(b; zVBR;`e}E2iFMK~QbMB!UpgN5K)HxL1&I3n{RU0{E-gXlY*1t5jn+lpJ2=2opioVj+ zwdya{ix|JsFq#^B$$@gwaM4V9m;B{ReoYh`ec>xWYj=xkR71*4?<6nAwwqd=P}!Zl z5$|N@U}{i2>1y7Io1nsuKE+W~AT^_Zj|Z~kG4Bk%^iXiI%i%kxkDIl1f-kB44gR0H zQRPCMq}!@(LmYa~XS1d4d)z4Ah@b3z)d7WzZ}0A|D{aM2hEwm<2@89!?CTRbtaQnQ zD^0oY+m6JFlStF-``M089|au07OMAz4eDRo8$BpYa2RQ?d>zD^U&W!RjXKd8uHHWJ zI6g{@XoN{(K?OPW)4@WgUx^0`v zNeDOc>lL?MH$soOumhbOBtDfZHZr^4Eh+~k11?|M$S-#uGdfCaTopsrS1#J6joBGf zNN0v{A|xwTCa52F-FhE+OzK^(>q3YRIxa16zjoZG7t3$uF1T6~(kO0?G3^1&-}3k9 zy4~?R&l=Pxs&nL8v0kgX20%`zvI;b9vauVAp0shO_d2=+@GvY~VeO^^77GVN5&Glh zdKvViFN*ArmQdfND6nE8$g%6@)0BOrt0wjNo7bJEjRQ}Tj@H@@8E_Uy>_wpX`T$J7{S!}gGsN44uC&VI;bk{Mb`9lumFlQsNz)XUPoh$5% zsbm6H`}k|rUK(>HJUt|K zvHp24*(#77at|-FndL9xgPN*X^Xr~^sCKTnZp`_ykpd@d#^qDPewuoE@ddE`Y-HLy z)ntEN;w`f1~Jf`X7?8T^#EiVfD1C1Z~RG(nnfGXV*Er#TlAl)sO zuJS>L{ncJ2-)k!?Ka8pOSGs%oCD98j=ibFEh}UC6I2AALowv8lR7Ri_%HM#J9kqgD zNwlI}W@2N-cD>i;Tfeu9qa?=MGPktVFNKDN&ih|iy5dud$>3i#j0b9K%1C!)>}n&B z3%d>980E}W->g`W+KZE{ce12<(vLLZW&m$C)*gvcVqC}Hm_PO(aWeF|B68dYr$8ZA z4e1)+)MIoj7%LA`F4V>Oe9hX@wn4dsAjOYo`V&oF2OWhR^>hF$MLv>H@VIPpK~&6D zd?9P+O^i7`t6klqA7U}dRp|094GOWcY5wsqaIcvfx60ne69kb~LZ|b>trZ^=@>Q=S z!$enIXK#QHQoS!8(dbf-9pu-P*7G!%J)XeK5}IORs|JDCaej-s!6Qu><#q{t5SbzA zL$>U^BKv`sUM*aZ4ieSb7+YV%MZx=#kE-~Zd@S-6vT8L6HF){jVgxwISk)cn(p^MV z?tE#9sAOJ+6DvZxs76|&3F^ZilZ4+ zBU!Y*+C7GTg`cBICN;pF78=%;cpnmN>P^(b)yEl=b`x#CNl2&bz9TvG@!Es7bC!|F z9O=u_PU+b#J5_FjyvHOAhF`||Yw&CMOvCAYP9l-}a^CH<;Wm}c(jT4UReDK4+-$Tg z8dro*j&*h$c3*z+r9AhZJ%kiggWZ*83}lNj0LXj>#o?9-C!ak_N&T)QdH#rn(>r+X zf_TVJP+|4ZPMW3JHJ}b;1(2Zp81E@e-LJK_hk*qzUTm@lN`v=~@)UhZ!{m=bXw(xH z)50FmQ+SfL?tM@YAOy)EQNTIlK#v_SCeQaT!-Ev@Y3v;`B<2&>z(#cn^F7%IQoJ@6e?)4p3iJJS*-Y)P?@U3|@t z@yY{u4DT`BMW&{^jE3NcCv45vyuw6;dioDK9hv>Vv^Qdm>h~MrNz|4F)*9ArbGyI< zmW!S~T0M>(J519Kj7dx_z9z0cEAK07NGic*_u$T3%xyxzu{g z$qYiJD?CKuOH%X>UtMPp#YcW(;rhJeK;z1`_)e~Ln)hp`hS}KM7C`!DQPr+ zy>o3Xw;atXax@jPRYnU6^VuUxHn;NzV9$UtMPBW83;cKoYim4)a!8iFK)fJ1xY@9h z(Jpzw>9to}X|ZU3sj%rTzF`I==LDX<^F~!ok9pGS2z{__lfKn_13i9W?>Ku;Bk!bB z-=P7YK{|}U2h*7E03q2sNyJtPw+r@tDiYUonDrtleXZs^ z5`=PW7Y$r$BSsfSmWQ3}ZoiOi6HuY^uy9d`QKlAzx-KVQ?bBk;c()UmSG*!Qjt#vF z&A%0svElUEW3cJ*_ z=s=<_Tq8rFv|W6Z>7a>UB)4$kM5C^v*Yx|U*#29`>byJ-w3J&_@e*j#N|;$8Fd5ns z-pRaK)p@0oWfYt1HvZ;#_xMvXmg^;ORhG)h8>CAZ%2{Zo!V-K!hNZzGmBy?_6YZ@W zjTywU>P%$j9_Q5WL?2lL>L1?x+P7kQj;Yo*IYn@#3D9=~HHgyXr$p8uj2{6Wt+(7Gmx z2pps!asV&x(b19owe3Q<&sB_<=`-ba zpcT{id=3$w8(L!YVa%+1b>pi7!sO9BZpRSeqUovopvnt(r`CXdy5_9=4A(sr3^f%C zf?VXDOL2PJdhc#0XVYZ@ZUTd@F{gnP|A$W6`WDH53rv68ybj5fb!JO9xGEy^m3i!+V_7RN3&`^soF+SUwC`BaH=xTx(UCJ$F!$I zb=G~O+hGzx9dA`8W9?%1ksaV1#rs_`q{8MjS>CY7<)feMu5C3YcAj)ll zLd;z+g|z|S&OGp#CHmS0LPHZjjR_*LHc%&-4C(iD8STu#!*SDDE<_RvrZoBUbOYo* z`IGx}jys&Ionv3sT|~v0c6#*h?VuuS8>tpsN-PHYFZ3n4Oo%n9N2z%qZXOLdFEoy# z>kpyMlR6XEsdMTTGoxDqQFiN))?`-}k%;sjAA$8j{2d?C8SD$iQyfgF2O8Yw)GA?e zvHpI{XFr)MVAuj7c{bykw%oXRid-nU4P7%8>JTfF=7|+G&2pSd?Zf&G-FuZ=Bh+tj zu4|1lmjK~dR09R)y-x6_q9!^&N+y-8%W`48T16+4UNe%2hfd;~g?2{joMTPz0n$O& zg>jYJ#56DORwAM%wMz=S)7d3;+|z4|Mro`4JM$~}YxaA(N;+n(D;_kdUrrfkx}-Sv zs5)NL>kieMa}enDHQ8MWOGG2vR)M3aHZpsmh=@C0f=&05Sljju zKhh$3Kz!#TzjVjy6$$;rfe+w-G*ImFc2Fy59UfLqt*b-%$~Ye#J{z;l>E#`p9=5|o3HY{->^vfI@#P%y23*Z#A@^kT42oS5U{J1+qo7lN5!ITBk{ zRmHy=H4Jg+sb)I)F&e!R7ruT_9$TVHnap0SF}OC&2WP5&vEIR0dR;^ROCFg%1Z&J zY-?bKdE@bALYI6?7@;(y2}@{;YX5{JKf>>UQldyLZl|mX+~GKcM${>o)@E5oV1{y4378hdMX2 z%;fCwwZztN5H)bL;SKyF(1fgTT5jL({6y|h&)e{w8ZSU@)c~K4xe+FKGUxnCfF{fV zgA&(?&34#VP>Ix!@#@`=N``W{4O5vU+*99d(R(y z=8VtmXYaMwUh!RPuXSof9MrF9qsb?N5(JwLp%39w68i)lYq{|bNY7y}z>o1b9)fJ$ zg4FK!%zTidPzr5w-mF?nE*?s*b{_8TOMW}W10cLQgunr%k9 z?VtBh zpi2Q*LCH4@Vd8Ljbl83|@oLFnyIWDnoB0y&pcZqG?tELEFI(w3#GJQd5d-2t0Hoc^ zjVAZ(6gP1Wg}h(2^>WVy!lSwZEKM%CyeB~(Yv4`7DcPYSGcz+x;I|GPwm?aN1%<4h*x5W%t&0XD&a1(txNhN~)cRdGi;-5tBq(ZM?kJ&hI{E znQCAbg>|v*_-!dE3bMq|iNUqYYg;xcdw8MwE~X*yvq_mxGS2KIiSe)ouNUDH)XCr) zGrQpn!!Dde!`i~POeUJcUKL5DCQutz08{}SQ-`yWW=c3LrWmT2f+@5K`&8UvogxZ|%{YSUJ<0UPowf1N7Wr8v4B@x%VE!eW9U&qq}O_)MVQSUJe6u$D!~| zrG|541Udt~hDk8Y{S7S=HmupZ(n9Xb?Ux85|#d5m>G;Fcf z3VV9N*-TaYk9I8Hnt!G&r5*R|*wCMF8oU)kR^#)s1MiMXFb*ZbppHwy_79bwtQa7- z6b$WPgM_nMZ99iQqRN7LuVg+j50k)r%kb=Q)FEa&Ca(x*huWFhMX8R>@<_}hXrnwS z5++zHczysMv*9y+F>Fz!1K>P}n%n~ec3w-v(1yJp2oZ(i(~Xu3GVgg8C_#cvc#S9? z0jnkvh3oW(?Pp_{KY4ZO9`bv6GdRnbEZi3IH+ZXG5t-avx7yfX@wvJxdivtpqRb35yErdTgLq z3fi>=ky_UXzz$9mB)kDYfx&bAd&mL+gz1p0$$$0%>g6tO-u2lLJxNAw5LnW=<9)Cu zr-ejm3IA->0H+lvKcPK5_@SbRnO9IQdojbEGt)+6?1L$)PTxkbJpmUgX*w}*F(?lP z97@GulfLIHtncda;a^Wu%ol@U(*eUp_ko(ZiQcQBT1FXWb~_=%agoAEu-zEZsgFUI zS9xIPSz|y6RgpL(@IDSbJm2cM9|0lrToOz9FgKZJ?~uLAs}4ihafXV+8Jz8e%o^~r zE6?GRPB#1}gr-4&sjAI?Q04$lu&IkmCgpiy#J`oO0tI07#nov0bUvS!Nc+Umd&;-` zh{d%z22Hkal(zWd( zabSR+KYma4LHL`PFqu;$^+=lYl$xe_({}b0oRQ3PdPviV>?Pq3nw3?<;9&l874HkE zc8V6?;D8-V#dz5E8b&v!htFn2<@)Utt0qju?DJWvnekF38BX^74zVa}9P%pd;{jyT zjCzXiEKHwMz{5-ZGkg$HrWHdSXV*_tA(+H?to&O)Y#WY3(Jd6!(@+@CyA(?AC zURzr1BeMQFQ?#-)B3I*yO=}D@c z{fM$_qIx$3PN6WVIdKNAj+qe&nH;d&>UAuT3s!+^S}yC~9@-oXs3`={3g*J~yG1VH zu7RPfpxDp%s+z&8MG3;NP(PXp9Ro_;ghTh)FPaIyA2v5T`X<>}``MjVne-1mwz6+h z*a>_v)|gGiqAb_OJ6484@HqJj;wbsyi6*Dd+E;a=>l}3-ZZcNdGrPm|7=$S;4+JaOjOvmiB zCU;-Tk(KE#rVjH~a~8(3++&@>1h$`0 zkl->blsbe4WKi&^JQ;nDNg-_e=_x#>oKW*VC^Zq;AS>ut=i~K}w|@<|{2DM}3K^oz zlNN$8@dA~z9J0rd+%>6CC>ytM0e7(ck2Fsa*HPl73K5O@5Bcx%yY8{6{i-bz5Uz~Z z9Ux75Pzmz%)FSq)6lKBb;@Urbaw|I-TLVrLTNWp;*b5F=0w>XBb=ZZ5lPudi|p5*3gqP{wB4 z`6MKZo*oF6lDzEo?&|Jo>_nBKbdv@$QXH6gu8pLDQjdUKfaPbQTM&=~lAG^GjOAxc6NXI9oW98OE6cF`DFCW#D30|x35u$} z9l=Gx%)!72rzIv}*1iJ-|Dy{z)NWHLA0iA445StMSjF$8f+4FVl%Y5OVXyY{0Xiff zY<;M1L46kx&b_wt#cXG`*!78*x;B_{H9}2NGToTO-RSvvqmg|42Z*_AJ<-yPp22Sgh_cn?sbwp&l#d|3#qruUw2rw^}Q8Xku6Y z`r=m~Kw5w=XQe>)+iFBeukQd5<^Mm2%t24HYoi_U81I^5EqOHX4;c{uVqrhg%Yc7M zf<5B(IM+`*ok<8#)m??<+VI~`Q1RuEH`00(DsTR-%BWu-a9$W{KN0+HnxGV*mtOBu z*0}F)pIiazl|)WHd-E$Ux)On@JwWo)vV)5Cx8FXw52WhI+T=d^rR@E4%s-m)?N>hF z)BD|%%I*LwXYvi)`-!~QPGi~Ova-u~Bq{svo@A&64t8I{iw{=|{Aox2_S<~{;N4!< z?O4AlHVovf=>qa+Md6F|uZFskGpC8byG8jHQ2yZ-P&KunVdGUt>|fcu~ID*Ce)vkKQ%w{VA#J333>hy4QsM#?4nOh!zP- zrSk|RpE@_4!+XgZKu1Cfl&D8}XA%DAc~HjlYw#(0rh0-=N>f8}tquVZqm=8}^98Xe-lFSE~uF5l%%3-Wl@e*b`^w z*w(A8M?@ySgZSyslH9$92pq~KV914eu{ex$@myf94-`nGetAI*1v^LXj1FHSRN({Z zwW>oe4xQT=WY%A!7syM~aSS5xET(Gn1oE9QwXBti5@DLkSNj^74#Ip)BBm;zS#e>ZuRnO5NwQ&mE~?njnSu1i_-yFkf5r*V8QFh z1=<^i-w0GM$q9fRWpQ0pS|Z1DDsyK+khIIp?A%Mg>XuyPq2_S=t=l9X^C@-u1I!Uk zL#84>8e@-195LH;N7y-rQC~W#n`AY?SC- z$hBI>OC!}BJs7qeU^K?|y=v+H_egjCi`^m)X5A8kUEiwF&C1H^s{`x~qB_%}zu1U? zS198+HnCi<=u;aJ1{6M{7Tm+_^F*Vqi&(sMt5GlXm~v`ujkIs?3l9(Sn!uI1%0U8_ zn{-^E1S4g*V9B_8(bWq6MNI(p`N4gzHkF&jLln-D3CH3eQLR!-T_Nq=&tq*G^r}>P!@)YwCZ|bl8g1>ZEYLy#$Ff9=Wt{=wra{TA_ zrK0(*5?S`fW`bH-@A&<97Za&^%aA0We%7OsAS6-#l{fg)OTw7z!y;?mqADb~p%Pu2 z+Va=j|M(zy+w2x-IU~IP`qTKcK=ykND$O%#aih5rMOB{c@2N;gN)937E_Nq?opJY;*f9CV-PK07 z3V5}|-fB2Gj=U2Oxn8hbZL%^e!U`VdELOX5mF!f{!5|6gAcmMc25qQL%{^PFz22BmR z6emp|jHIL`EN=hvjqFQ)21y~vpaf?1#n!cj^xlqkP(XOIwgwd-gwsxp7%s`^H+)rv zlEb|igwJ7-+q*x8pslwhp}}kKaXh?W=|C)#uHa~Kth52EV)AZQ4W~#AynftKAaG~y zIePUbI|pXY+Eno2u7wRo|CA@aWz9ukalf-xV8xUhU+u-h{HexP9pz(8Fl)YuzWnfl zPx&n-X0e*4gHYie&#!ZZAq}%lZyZ|Sc4s0pg=dsXM|>lCUBz?d2_gBqs=I9UH^C=H zM8amELhrSAQ##&;u{>u1#gn6kP-~f#%ZnI4o!9?hN3#cE!sOi&xZ(J22`qUd_j`eM z>b*qCUivTG^{NZ_uzjjdqiv7EL(X=l%T{bMi|CWx9+1H|yr2<1HDs(8&;x1|R-=Ux zLLhhf047%y1g+aSQ67Tu3Psf^xjDJNEV?W84lPvd+~9b?c!>5Ua@SCgtA)wSqBBZw zM$e^UFKByuOplJ(-o%mpc?Wi#=-dYGEYky~0)9>}%F@y0?eRA%l7@I*d&?0$Ay(z% z3?h@Kls2^W_(#IWM((a5q1J<^Wmg*Fdc}fPt!+8f zKmXDabhOkdM=>aNd(&h26F1sSxY$IP$z!4<;r&nz)Ip+Z+4!z$$dM=kg~w{pc0)%| z5UEYAkf%w{28QztP)YI@j_|Idx_4u7@j}*G5LS5SEr-Q!3?^_cR{C(UbtpYsath{kg93Ak9fTlR$7MC{wVbMzRt59mMo01ctjxYL|f z4-9-NUwsn|NA%EA(`P%?Pak^FoIQ5&yIaOA$eJb~Gq-MCN?g~ibDRdCiPp%B^c)^~ zx+aT5n9la-J|A=jb)9^W1mf<@fc4NU#|CXD?E)Gq7Gp%FE=uOKP3Ry;me1+_Y*;U8 zXQpfqPBa^Si%lUZy1M+J`Hf0e&t3^qq!~BSIMOd~-Z*%5cDEcc-=IbT z{n%fN@oDG1UOxWCz09|BKCeqmT`-T^4M|eh2{Nt~@bHp(Pm3bwS(aSHvj91lvI#aN z)+D~TM-@|x_pK<_kJi+ZfQ-Bwfoj=Z($V5(n5r8YbNtgxDVDcA!zS*VXb)Sp6hIZ= zHS|D+695WII5{~vSIKQ9Sd}?{g^g-K{e#}zVufxG0xdqz-@H>8Hwa+;^68&@z9XG} z1UYH@rS;~q84x+_Am9(G7fe6u2qlUas%wsox=ib0dQb9UvpEC~h?qU4g>u8e0Q9-% zT^kjX!>;FF`Xn#Cr4_D8bFZrY^D3HZXqF6+sLWv~xwboPsL=Abh@JDTR_!*wCfM*7 zd23fE-s=gKhQIhq2SUpDhT)~;WaX*vtuem6OKRRZ_Nm|jj3ZAG3XXo(38C5=RaMia zwkg_JWK54y;-n9x36MZ5qKUgBm^W1(giB{tr~mb+p1wbmNRth^-J1@CS>@$d|M5;3 zFpJ(gP>Umiq?dkh}ThC)7YGosu5#I!$F>i!?RKuJQcTj%fP?K=Tw_)>G&~8t|V& z%w)2Fkha4dq<=0izf2-0Z*A&hw{OjP4A`x+EFCG6{)}Qy(0vMdYYuG{PEWPU=~7M*OM>X31Snt z&d19p`mkZuhK5IPpjng&?7ju(0alaC^R#ExTwqb%AiSSnxj--QVzbKYsuiyj8NF z6aY_#*}g35Zs!Q`evn_;{31z}>Er}!C;=A*hXnTm(74nlbVU5Atmq*1NY<#Z2}_9A zAzEHRi2-m^!3)SLlqvGsIu|gf3v#tTvl7LtJ6;K`$RTu@^)m2nxRk2Nq@tG6>MjMJ ztyTs8c}_PGtdK`9Fl(&HrO@_szR|m!sUN?!C`Ny~uw_`|jGq2RgeIq+&S%Wn`k zsrH*Rl$t#+9<;C?v|3nLGz4W+49y%Es%d@d2g2(C$E*2`M7}awma%n{N$29R2b&)H z$J+}H+i4vO{Ppuo!uWG8!sSsk2ZYLIdttIZ#c0NgMxPWsQ20IYHV zq!cGW^~eKh6HwPhXZ;xb5jaXs?lTVu>Uo;?uN8@~<_o)@WLCbj_|3_pM;7!Z8KalM ztYW*>xQ+&|T>8Gf{-!7cI>pr%n|dWUelZAW2mrtxCuF;B-H8>l@#a7G7X#9<-T0W* zzcP@|Jg3wUlP9Wpf&6|j>=y(4DNTwm6Z)Bjv{-!5{KOI08p7%kp@7Sd^Idi+hL@Wg zsL(Sd%Y?0CZ9D9|_6|z#JW{xaG4MAQ{ZD1+M*uLbrtRR#0_p+XzRO7h{g21~Mj=oS`m>|)f{D0) zmXg5k=G*~*@hHxS=HHnpNbZ+=jWb*Q`)&&V8}iDr`qifXkCy*=PX7MQ|M>F1IFPAX zc5PjyM-=OCw5|nq|Hg*Kj8upcaf*r7zkAegl13T7B}%PM zsx3+&OfPU!6yf~0Er+v8}4-bDnCZ-RsClh2AF5+ z67ma@7#gA0Nsl@?_n!v2cG^I+F98&Olln20QIY*x-No;Myf+bQ#ZygW5CXZ8(iqQ8 z*PlC=@i{)B{AZm4Ou}!HRXO4fkF)`HAo>2`N}t&8*3m13{30HTy$i+Jt?)2yIrxVh zmOuA+SpIW?#J);*zX?lixMQXovPfh z4dbmx}g%aXd_oJ|Glf%;WK2Ecy^RoR%m$64n}!yPgW%q4^z| zKubU~#k_gc`*-rEseU_qP^w0%?G1@NH?7|ee8W%i(!!C=K=|#b08M59ShbtgA^8_f z|I=RgGAsAj#95*Xo7L-IAI|uBYRmB;g|$?mrJ7EF%I|A+nGxieliT*jKBnR39V-5P z?Tkwk%E6=8G$*+G2m>i#iZXn?C7Cw*{=dNMZ=wBoCgY~;+eH2Qp^5xx5G9yD;>MG~e%nG8SDnN! zi?uVDH?I1h?5*+_Gr4@YXosXu{Ukf~?SVAeNwJCRj7%VM`lvMdmg+f5P<+~)rZ$g3W9xP^ zX+QK8y{A|ra1$8{RJqYitmv;sn)F=T*j`Ro3T~nBVXQeA6w;q>ow+Pdj0Ql-=2F>8 zDYvbwP7WPCf}V7QD6M~y+aduW?=NogO%P1R?mQO^*KwW{%`YEiyvv>o@0s-aCZ%eO zLnam{k4J@$BoXsIRT}kX6e~gg%ezru^fh#x2F|yt^42t6bV&2^EQ*Fb2$}q!W*$v? zP(=prA3~NCCk^}X!(}+*rY3sWizZ#Bj%tZb9eRXffX=Qrk#H~nATR;$x1QH0@<0Fo zk1wzO_`SfF9y<m0}Tke(o|QJ4dH5Z{u>Vqw6{2c5(!TM|vpW zO1QeZMwKfFbqwWe*sQJhrX`V0L0qB+DH)^AkK$q$W~7oC?W=~sXF_~8^f#*B*&m6( zOUCwBfKq0Go&^D@5%aY;qNVkuS`}6?1zIlB>gus&mLuAu6&CkR6FFoR$$7?+rhl-_ zYPr_$u_=UCIuMRFRk7Vf3kr&rx?0fdTR>*zk3d>9D&HFj|M$-icR%@v6)GY9a#s@P z2=@ZTvJD08!_Q@#MEaam^Rj*AYP16R$&JpU3RUDoI&`8JvGYcz9S3|c-OcJF3O9>B zQu~F0p=T>@-n%P9yZ$R>1NJMlhUg%Ego$kUk?e#BHTbva zH6W*aBgH0#jZHlE&v!QIi|zUe1Ux!j-8SC2yg{NgI}B)`rKMG+a9u_hm`jv1-kS6Z zQbX;kN#1HzX&xO4fF}}hZ)BzYxfJCJWT2$m*icNVO@zIBt4Dw9wna#nPLu`$gH>8;@+n2LoIaX#+Y_kV>*14=;^Ka(63wFZfbd-cRlEo_QAe`KtCAN7 zf@hZ=;F@K>U8U@E zX0YxJCLzO6qs;`i$`zqo%%*hP2y)Sdwm5wiN=oLF`JaS(9zO9)Ow_JCIIO1S_)Z8) z6(_|RKO;OjX;GS=ebX!*lP)A)qOVM zM)&VsVWbCEwg4L@yMD?xIT<`6qV^)OQCr+ zhVz;}*YAf79@A~~2wL-grShcgME7{uG4u$J9REHvBs7dgi?@11Nqajyqw74PwK<#C zV+Cw{*7smjkPd;Zm|nlgBdkzIu(DtN4%>DglTG{XLf&{(sEB=$w#&wr{2@-nMS36} zK0Zs2*jX&rV_V)h*oKmcbofX&^VZcVx`7ad3#7&3xvszdPf-ADk^LkHZsfl^f@xi0~7`O6GmSBWiTq_m>|S zw&>~^5ZEv5?m!~?rBd{j^m}Run-X9Fjl32NGY9FkLVWTysM&*!D^c#98S|1Qu5I=s z)h^&qV^J;(^#L*;&0#UDIuAa5GGCY|Xmwt#bXc<1D7JmIKANO# znv|?|siREno{hQN?!y)5aXahuee<18Ng*2J2`Rj((g-6Hqu44gqp5N)Jco~M!O9rz zWnhzbxuP25mZ~8|hio%c`yPr3qvdIF`;EXITG12l4l9?o$dv4{2@3CJYk{N0e&d;s znY-KfmD=`+A(crjFYJCiDVSenYH7n7(s?j5V=M;w0*EfRnI@UtnHKOJG`*K^ENGTe zT(ZVbmb5bTq3UrQdwi7_&G1sI<%zuNn!QB_=hF`@$sc5Fy!5jB`};SlFZS9@r&^E1 z6djfl_}=hIVtB50s~JfMm5ZGo%el>U9a$9z!RvHwz9!o5vRAez?rrPSpA?n!$Lmke zb`)0hCkeTPv5Ce#Ga@yukN>h}ydI=BHiCk++R+JyM5Ed4`1lX0j{>USw zEzS11f1B=QR?VZWSCNs=sw*kxCOtgM7be6Q8D*_&Pc$pnw%{ez@_a+|9hjz1pL!&@ zn|8-D!M)ebhq7mKJKN*3$^1febW z$%V=zk|(O$P7Hg(Rg{P~*JtY>$9*(zt8paGzHv741Radaw$4>YFeyTuU($8xeS7#w~ zw9(;67&XALX{~N1QA)0D*VR>`51mQlh4Hm@cYm;fz(?x1^$cd`a9%oh3uS6m6!K~X zCx<#muI1Uy@tZpNxnS+uc0Zb0>e8a2Pqy{+vr3Gs+#_sDu6^a~+_+ueq|0YIHaqzR zI`JR?m-;-$nT&iMW_{B^^T z+>FPVk5<<0KR4D71ejB}(mJbus=X_@@vnbQy@kBnkRaP9TEzWUh~f74?|2go&!6%N zQ!5BgvQ~#X%Qa-h^?lUgdiC;kB ztx8%dXXfLBI^OW0<>MMK5|fU}Xnbb=V}g%6p!x}xytW6Fe0T2|co9LwvxA^36AaO{ zPh7b(q&Q3~r`B3?^2Vw|^c+Syc5=2k#uhpHDxdrtj@T)f)U)@a8`qe4q0*rR9pc8F zLH#>rW-q+D!nTjok48=!;PSlW(?jPMO63l^L*|EpX_6>1M|1C^Vq?ulUc65y#&pbi zi9R&N>N0WC(x5tg;_ck0YcoS&PALCRs38UiC;$L`YTt-ME); z-$wQ;l0PZb87!D$P@38)!4mCdCMHo&)4<`i9>3Rb+HDtt~U@t9uZ+7WCJ;~ex2wwX#S|&fk61M5pKD3y4NF0XV^`= z!CbyID(<`mr}^fO4;|ba-q*V7J-NXGvX*utJK83A<2IPi2U= zh+7Ymso4#GpYNDxaJN;rxa0Xf=bgkUg4WU=2weqC-@kgK^@F744S&{HRf!w^Cdj=` z7sjvArH{4H{Rl6JZ#;g+enVX6i{a#h3qO+Xl3Z`dmS2lyGz$6Pw9(uQm|LikQsH^P zmQU;p!n_5nAu#o44&;Exlio}B`Hn$DUKcAgE6$dL@Z5(*Erv?M_u*ZXCO~aVFz?Yc z|D`!Ou^IUU`Vg#1;RPe+yOCy-k{ne9whV#=T$xbM{Cu--t)||()-}P+!M?fI=$NN# zNK>=mI#MMnUc!ABxN3}mVL)qo{?Oc`Z($MrkY7eoo}=JZSnFd2TE+v5SFc}jYG8$T zshm=vzsX^<>mrp|-Ib!%AB-rOi^-;4|JKu&DueHVQkjMLgLLBgM}sbQ93J($<5jJd zAD?QyR{H0gkSWdf9;fg=Ev(ypT9Fwamzux34B2uLIzO*?_uiT+G|oxUv?!|)?sRGi zS6JW2U{kOU!9l}0YJJlq@`UCX#FuZ1@Ni!}o|yWdpq9^P8O2m`$z5R2&vi&1w?|}88gLm!qES+XjS-9zeG$pq zB@xYFZ&>@^5_O9d++@Feu}3Y1%f$)7k$0bOAmuJ1DQwM<BtxJA{osvi}G6$!3s6uwJXTxVzZA&N_ge4H%1x5lW4ILTI5<3 zLoyy^51I(=EqyDtJ$r32B5kms_Ug^?qfs)KGS_>nEBpv})`FT2(6t!b`Bg2?qbchc z;{LjlBC!c?!%wJ(J_z1xhe?^%d6K0357ys|DRUufJI+*Y=3x98Wxt;~1Aj0Ohd`jfL^n1k<&!*YNLG(Tw85@r@-DiqD2e~kk z{lKN1`npY>>se=$LV@hheTxzlfZHu{Wc&DClUy|6@WT+Tq8I}vA1>r1`n2DN6p;n0^PoQ zccBwyT_=Q}A@6vKPcAy2!D8>}5TDH^sl7N~-fIH}lk=X@SdqODRXxOaOeMy-_t4&< zvqRXaut=DzfEvx@IG8E32j{gOM{U7a3C7=N zjTfvnQzng3sQ?UVynsz1q;i{S?3|O?%sId?RAAJ`sx6|{!->t!_-@fija!1*s(1FC znAItbCHSV#rRTK|ro9jI$A=-JIi?qkIe!%=PFJKbIdYiHJ{Rn0te(G{(=h@*500IA zz^EC|Es(fFMNeO$8C=28V5$Z9hJq9RhZizVKpOa7S*tA7pC0K`e3T zk8vjDxQXm0u=r|+tp7vu5@}&Q=Zm5&bV1xuQIWzE+)iixx}~Ul_n|Z*ZZQw}ww}(- zwuNA~)wsPes&B|#{L+Ydv-t5LB|if(F>zCQfil?TgB3}_vlHXHUb%G{B|`e4)wzHK zqv7Q2OJcM7sMfQJ0g@gr9kP0jt<+m)j_*=e_R6~DG+3k83bxjJB93?_16Zn$gxZpB zAm|htuRa4GB4RNR0g|%X@<*HG!hy_|jKQq8Mu}q(|4kwieomiyylMrwcP%Y1U9+Ov ze2PieEQV!r>{lg{=I1rZ2vLz7>5|NmstsKyG1-?MEu>4wY-Ni5WTOWk8=G}# zQ2V508&1KQkCw{m3R9EIHlI#CGZ5_Clbl#rQy^E104@pVObhziN8 zK~O2it#g)Lr9$m##G!1xweCcv`x{YY?~Q|sH$K@u2j!{D-)m+eVbYm1!&gb6U!(UQxGN@@|1>- zZqyp6(&czocoSK0JTSVR9;;09zFBJPGcMr(eBWZ*@0@(Djl_fXo63GZ@!ZzT6roa% z{Aer*d^S<<$wyUFgX72c3o69It2a+#j8vy5KUEIe8(mQ+brvDShegd3eE9Qez2a5C zse6GZt)LKP*>6tVZ~Zbqj;D>xDfA)V`wy{S)%%~of{a>1Bj;-+jXL@s*#G#vL36KJ z_;Z0Io7o~FM?LB((H9g_{(4lwg;(qjBpIop^yYW`>pX1^L>|){#^CM{)=5ZFPE@{+Z%X!{75~}4)t(IpNRX0c!&s)!Ix%sL;SgOd1vfS z!bBsnv$*N%P!TD}TfRaQ(UL8}(eO?%~I$Nt7z(>y~zJ z9`2RJnY?^?KQHfIOF?Hj39}twF1|*g;?GpgBj~GMvg@lyQZfq;`ua8a(A)Y)aatF} z4m7ksQNismP2&If825sSYX$x|97cRu{UVI|HO~Ut{X^%he`I+Fp zlO$X)k^G#CV3{3LP;AQRQ?EW}*>W+)#iJ#j8~XJPP2rKAt=JJjn+nhBSJ)WeOQrbW zT}<3w&C5@$Z!{>Wcz-y9?=0QgC?Z{}tpi{%7l;YnSDFUWSkpspTPV6{?>bhfsAuTg z>Uqxx=3jBTIA@TkkWQ1GZ^r(`s=1)l`TEY>RQue&zWSR<vIr$fhq6)xZ6<;Arw5x=6(6NgiF z^puM{c7~uq_yo%KRiV!}z!Kj%jLEH%m`+O~Yu;o@);ifObJL|Fck>mcylDZKk@yg6 z(!xy0CM(A=Xsq010;S>=Z(M+o+5!IQ4|g2M`#s<$OjT!qC65LgECt5q5F%@xDvmeW zwhJf-o`w4M{QzIkPPnFv+V`!}EMP{R{w={|moIRSA|4JXTYIi@xtQO=vhry}C#gn3Et zaw<$qJgzb_Hjz<${$3-m{uYl)xz*GH#aEZDO=Q9TiM!tTz(L;RBRp>VY}jp!v)i1o z)lt3Wv)WCV+)EE{0oz4%-B5PbNnPX_t49wwtsW3k>Z`_h9oO308U{A)bRK#udTxsf z0ql8xC>^tIjdovOpYiK9+f?Hpt^Ol8j&Uf=fNavG?{emPSPII>ia+a${18RPnHED_ zl{)rW$5Q9C2N6ev+8uj=g=BiSb*|@Y0uHJBM{?c<9pxtcizCM=Q4zTU9WD!b9;ocI z45RoN4TdY~fvj-($xyUNH6=;^#=U<@h*V!t1l^AP$->;iD|!kpB{S2ulr31Ey!#wh z-09vO^w4~^3D%3yj6j?Zfh@1WlMJ5DB=`nwOLMLJ^R=6ZZi{#tl~4^+6TyIRS1h(% z1T8h&{k9rxX=lw6ql^q$6Zb45iuTCjukVpZpCobF*_4)%%D*kCJCUh8O!!t->uc&}O@e3aWt%~-qPwnTv) z?mCkxV=V{|XB>1;udq(n**FO9&@fHbT+h0{i-=lMQfj>GqGB{sqUtO}KPEnt^f*bl zleJGCU2!mwJt9hyi|Sdq@b0$QIPu;g&1+avThm#|@pI_sU}Un+=wU z@mAO^5-8sEaP#DB0*{iCEmZh07IwPEwmaWQPa`F4zh8MI_k7)Kq|PKJgO*lCF&Le> zwTt5>8Xa0aDGQ!%PmN=hU*MzI7{w5`bzTjVF--igVbO{A9>|!CB2i{gw14g>Cke~!cuESMIf4lcbItFZLLRnq`5@Ju3_{v-2i9I& zLFL#W4@OruA`@(?p2zc9tacK(UV=HVUcM~u*sNOu(|vlJ{Lr0-E4{tUHp&o6cxk`4AcPr@r|y2LhoPWNgTUPy#sZ;Wq5GwV=e5U|=U#r-9& zU&wy5z*&Dt_2U^6KkK!-f)>eWd%%M~pGgP~8-u&%!8SG_9U}0rN`r+ObDRA;`;gW} z^LNG_uZQMySasnnVp8_7nuxrZgkQ?H=* z({k}>)!5O?$al;o*1lgpU$gNJ6L27m^q6wC8f&e#5wWQlnn8TOHKheqt+W*S`o#eb zgb4_|;_K9k=8T$N4>(Ws88bB+b}vPX$%kDAf-6H+?~-DZ^(u*8OsiJzu4))Unbwuj1@AQG^s|NmxE{5a`%zdk z-F@i$r0V&W6z>lU&HWEVJe(thtgGweSav5<#l5&{B*jjgPRRspr&D#rZ1u!mz1pen zfgK8d*Or@*3emMKcL}!J9$SA&zXixXqn_l4mvOT4_dw{peYv!G#20~lHMN!)MIyBJ z#en8_OX7~`B0MZ2yY__`T`C-rZ9Y?8y)Cu35Or?+M^B%YcqMtRp7f=+e71jGnXUE3 zl6sGjIr~^S(h&CJ}2i>M}BlHB!Mmeymfaa&sx=N-f4y1)`X6k$Y1^=3}`JM$Db1QL#j&1i|Qnw^jUOvbw^9V3dtu=1^adn6MBGP|2TEOcam}5@Qc0$i0Dc!!hks=T#DkP z+EJt`g49=!KvnBI_T~r|-KAP#r1ahovK%jKa%SZ-?^A!jIsSyTZkvqQrR@ZdV)N7C z4WviCdj36P$uw$;Uz;evh>CSQP`c&3uOCNlC7(^DTL%ZsmVY-E1WNY-T-s(o-FXJF zKt1WLr*Cx;gRQet2pGH+(iuVTdc3oXfxj?$M#&O302*7GYHnzGbqQ?6Qx5l@aXBS^hF&m_;^|kB@~I=7gIcG($Ve{nW%D-t2|h=SlD^hGit?C z+<@NLdxHW2S6kvL{F_RGEUdVTxKv9L+LiVT737aV;<~*&rxZ({s6|k1+97I~F_7ca z9=u>~Z`PyRCO5`Zx#B^?W&xQurVOijdmf%(_svL9`on%Cw~T^fMA`XDcyiGBU`*C`J%dG#h{7(z5Aw_-#jlWI!HKR`^BoEBm_%i;DL{Bf`Drejr!7 zyvpwQ3xlNse>?FSWH0wyrX1N{IMcGP7h@RWR-Y9G3y$c)y%t@E>ZYJPUO@t)|2kPt zU@Etz7aC_P;0%Q`Zu4R8X4ocYQi;h||C&Uyh!ZL;&dx9l^AP#P02;1+iKo#t>lhJ+ z&7uqi?kT!VcGwj1;Z1VSUy4$DJ1$}O2t-#tqHowwWyJlqZN1 zAUOL|n1H5{{SUSxyd~M^?=Q4aBPGAR{|h5E70E!0{Qg9dtLk$v`xLTa0r0FQZ`k%r z+dYtcGCGJ|9L-#VcTL>hAdBqnI*k__L~6F`*+#^Qs+%>5ExYA1x~j&)?I9kALG8;x zaFokb3ZFX_7KWWj_d3WpSD->@+X>7_NctNZ=?eIOPBc4A!l@2-emaiBmLpN{Nb zFyG(AgP$N(uTvwE%!*GTO<@v~hDU{LJh6Y;BToM!OxE_9v!Za zFzqd}Md#-;pUn3cZRC|9Vp2MX3-2s@Wm+`|UI8KioawLmEu8~3M1^WzY1H`NA&~#e zP(TrV061OPQ=)6DJ%XhGk$ly0y3G<3g}H?fJ`?x1YEBX#K79DKCv9gweMp}XkS(mm0~U-$vwe|bf+ zAK=rYEtV>lzmP=$t*K(2j)HzibvoA;5W9Y8P-;7}fx*X2AjEU1x)7y8{gc)erHut)3u!VA9M&nu)ZOIRqiMGmz4Xb-+{s~?%@0463k~m+`Bphe|b7r zVDeA20HszTkKaIQz|Kubo}<2!qyO**Wfvsjr&POCK3U&NsvJrZ(SKUuuYZR0_?ro6 zyNMLn6PL)~#iQ#c@_)Wd-NbNxjUh^PQ(^+Lo%k~yfB6>G2YQ@TcRD?l{~z|=GAydK z4HTA=4naUfLJ>h)x*1BOQMys-madthQ4o+;8brFg2Sh=-JBDr;ItS((w_Dxeevf~? z>pDNqzcs9fC+@E2UbM7nOyN@c|2golFI3DhHi__*@O;^C_`orpk1QRZ{q^;KK?MC# z)B9#jj8f`Vya!k)^O-vTK@WdB)q19Pmi-ROE~fLogrml9E%T(wYLIHtOqh08oHi%t zm*r#sK(9|N^DI6yv9pS?__T;;58gjs|N3XHRFg5l9>;>{7WR**#IHyGNjs^}P#bUG za7rl_u46bQWV-rguDrRL(u$q?w4h_|2kX;+0Mxx%?T#W+a#RsSbcome=_1PDFMKUd#lGA&?n9a z#Y`0X9ae}T-WjvT4Dcny>DE}kvibU_Sp6SQ&W1?#p`A_LHZ<=c`q$R~%Ff^D4OwF1 zh9!!1m)-eyga*+~)Z{*X#UA3{m>F5!d>>iLNbCH2v`BP~_R4K3Htwuf|KoJukqV$i z*0o|~u>Ibq?;z8({$B!?xqnB@VPzn*jXpykY=4LBB&3kJHlmuo#CyMkP@n6_BfhB} z3jLiEzQjV7{@fvtAC&r=VE8u%zoLTn4f2TSPvUBS>x9>k6(bUh5{~iT!TG=TgZ>10 zM8Nu!|0q)YJMG`TgT(ktJ#(dB<{tk+H2=H0=^v-2l|n~iJOa1d;)mP%KXy;_2zf-* z9Qo=0G3E!C`oBbC{I)}yfa33<{QnX4-%EkCx15YHXT85{d26*e#1n}6jBAGxm=J7fVaKXPf`Pwg|o zp6Y{Xv9=Z&5utugDUbVI1o;pV_j#)TO-xMWEp=+8q@^EScpPF$VWoL`t4bp+WO}5i zn66Du#Q&G*yiWY6_e*qiG`FjTnp%d`L$}Wx_~gL(u)l275%s3mo1`SVcgQM)7P#%8 z_hX>6%xIj)vMc2uW;kv2S8-9eA#L@2J3oX^Dk`dl1;vr9;IuRv;mx7&JFBUvAnPAB z>gYNEGzmJoL(-?uQ)7wjBj#olp#_KX0ZK}RLYt_~m^_}W{DR+CS9y$re`^?Ouft8^ds+GC9)qr+QC)3w zPLKJQ1XMxsDR(klMx%1^>B1!Sey;jm>ZQhFt=jQlux5Qewb7K1f5`O*isi2DTu-i@zx96Q5Q1iDFbbz^u5DUJmKkJ*GPO-AM)Yt!j0b>!s z*0yjudXBt`xlLgJzkB)N{EHRLg znYK1_1Uz_cc^Z)J{^u@L(gE(igo#kW9=jA`=I0pSN%4nH{ZmH(`mo)s=g}C>n(Bq3 z#9i-+j~W>^`3zczxACRKByF+G|FF2RZu$)P5;`T7&72l2z>fsHd@;b3R0ciQ|8weM zEVp3)TSPu81*2?YyFUIw3Gz?nJRWLPP^b9)a8F}M?R{}u!)e$hg9unvlFE9tSK%Ws zKU!{v*1l3h_DvLqrquFTG_xcENGim+eASKy%7JGrnjOz9&ich8>HF!COdE{6{Z-Lpck812Jp}k8XZd}{e@=G= z)mfevj1>rv>IfI5#Y#J4E6t=D$wC~EQp{CgjxeC9J{im_x^@fuJE3Q%0;K&252`|= zE&$+tehB!Wis&zajPJv~(MqZzS_1A5%NAa6s+S9jM|%|3Ps-e_ED!cLP277f{5pc$^Co z#XicsWk997<0biEm1dpr?uVCQaSA^|V3r|Gxa{>t37k%=eRmZ14CCVB%)p(SnVH*6 z0exb#=ZI@!Z+qTUeh;v&;;h=^#-Gwo!CU*G0%s1sgkDTi9|O0io8SG|;ooQtpig3t zMzlWh3S;nem1d4dx}?$Sg)fnl=oI?x#l>YgC6{C%U&6SJ-x}PU`A>TD5A$ZP23R+V zS8IYhk+oLrtEu)oKKqjlPEPzk^u z9fE3bf9Dtqe}~$+K5sEP<2XQzj?d4?c0*iO@yKt&bIbe>35;a26LdJZ?L>J)$Bdf! zKS`>V!HA3YWF8+WnpxvUkAvJ5?cRV*x)KOJ&oU#$0PE;0m+x%<*a!6;(PnR43&boD z$}4^R>_4Mp0DYpJWrXZlV#wM~4{V_aoQJzY{%Iw3f&M(cNRpL*&?ACC8FP27-|5eN zVPT_iQu}{0S-$&IG5+MRuTRWhqhGHDce=0nsw8ZOMqf_5kmJ16)y&k_t1o`jTN?sJh^->G@1wZET;dChkxpVze*|}q8;-cpCU>j z2$wE&j{)rk;G0VP$2$M|=~K%vd;gXf04_dV_a*V#Z!JZ}A<6OfjUW6q=Bb^J=)J>V zbID(Khh!fB70FH@=_^6T($ugd&a5Bh_dmq!-&pL=e^zHj!j(UO8!HU`FSj6nHS*8D zsXRb|65-Vij!=B zl_}ylqpD^%|Lz)$peiF@?0jA8(S6qI1J?bCg3F&dLBe|2vUgemb z+w7~^_djuoe2WY+38T}XNB(A11s_G(Jn^2{FAVozEcE}p=D$(K|2ft~_t$g& zhN;ii}LIj~p&q|7Fep6m{8O zL$#LvNq)Z*^i-)r#yqlhN2AJqSjhiljns!iuon1(L(_) zE@6vHOR`evU^$%lkcX1jI8Z4l-tBEgYnL+Leyl{nt0L%X?I(|qoo`U3J(3T77A|_= zFG@VhSUI7ae%w42z`XgwlghQc+-@=#KnY5!P>IdgVz@YWiXu5XW-KmbGVKrqso#2k z$JyA#tg}k2yR@#{c3k1?ShVs^T^Z}2pp2$%LRhh&1b+TEu>rDiGCr7n*>vwT&RKgo zQDPOoS|59Mn4X~?k~xs)NiOgLpqxWaN|7s-$cHL^o5S;x^WENt@Z`v}=TW-|IG*vezG{YJEOpJ9bB3 zurlW4UTE$CXS55PNkm0}d2m*6CH`Q`84m?($>}-QH=K45GZJ~f(Ht4c|CNQGJ&1bd zzbiLzCa`KZfJHH>QV!^%+W#5580C=s$ELqif`RZY;--JTM$oaSXAOv z%W+uU<2MS?$NSgrW=V2=vyia_QHn^MX6rGhDf*0lL4`g{*R)E#3hEF0t9WhdG_olO zxEI9pVimWD@Ft!@292e@eCdir-@m&>(%Z-yXUL&*cCe|lxtrp-MJFp7%~bLLe=)7j zmc=C@UZ>g)j4XA4RBg^3wvXnuCh4mx&Q)WnX{FX5!(`DskQdJ}jjOO(1TPjzJ}uln zOZ_-@yHv7{mvw1#Fz`#diIoWeYCBMG5tS;kzXuZaJwmtO|3(=VdQEXC;_nGx0+IvFVTj+hUw3{|(yuY0 zbu|85@%s~i14kjLqzPa2hQ~9*ngjSCGM2IGZlU47OP++hXLDGYm18lT^kCU7l1y=0m~&xUjzW8PHwn)`8c%Ne zYK6S4Y+i6~ST+Gwr$KKUSmB&5_seF+aVShMR!=gyX3V2#okwgS{m5dCLZ;R;29~uF z6{*8BS}eF7lzTAfsX6JDAq{)CULWg`zkUhYugY0lIIsGUn{_zFL<^$DfQ@}Q!O2<~P-YHFHPXv@K zzqr6zkmK+og~ZUYH`NgKeDU>ThMN7JPnA^I_Yywpjh9#z-QAov+XxG_pp~hxWZUXK zS$rQz$imC)w~hD$W{^b+H>6w|Ff|{mHVNv2+q}xxhDa0KQi#n|oL@{vB+#-$4r?}* z`f42$TRMV=DRIl~Hnr&%tDg(jZgdKzB~?N%gmo*eC+X{4U=>tng8l)Oi0qMWleg_G zkEth1!{UlvA#hHsG!}!(R(#QyuL{|1!YywLhMgCaoWJUc(;#@KG@|Vo_tvUH&*=mo zU!rdy6(q7YQsIXukQVM_308ZhUVprHTnc*6zO%S3REVq|vOaCst2?BuYR_a9qUU0k zPp2H>TbWVlp%77+cvpEEHwrzMtAvfwJzd_-p0uqVq8fQHZ^MIIZgjY~jcJxep zS{pTAxEip(2z@p^eds2pbfL&=GkM~9In&rDH z`ws%G2IH=?sUk{VQ4a@Nr!m`saomNMO#0e0C^il)izj#$d$ zt!~EjfE@5wM!n{RI-iMX#7M&wF9@`(8lj0sK_{)D88!)IN0*eAq7Zuhyn%_`p%7Sm znxw@*x;sgY3;ZoHAO6s8652YD-}%f-C=Y5CXXsYz9~1||cUlMri6$r))5}V& z5xWUfu>^ynQ7>>sbl8?|=ga1c&idGxQ?@-j%)xJ>0=>+86k9M`!QYkxtAbIPXpsu%3vLm3-lglb$|Pm&&7oaL;b6~#|LYbT zrDNRI9cWegn)JOJvwpo`mc2!Y=(_@nI|mg;yG%8g9VM-`>K5uTwYDQuANJw!(he;#E96%5V77_f!lbu4X0p;~ z1O~u!-2NUQBK!+fx5h}&s*ud)1tm3*JO69Pp=g-Mg`!*NNf*2OO&a}iU7 zpDXe*Ok#Ei1rKiu-3#gx$xZ2A={^o1aY~z9b&a%rk0KosTNI&N*pM*>qng%$byta< zjZl4j7-!KBh+T6en>^$*0Q%THrAG{B?TVf4F;MEMS2H!x9DX>C0g)Z*#9Vh$bu%;r zg=5YXFm;bHlmqQ^}2Hc!j{=Y#biCusfo)y z-prFPMrNH8m&w+kKCAv!n;&`)siT%iAIa~FV06Id_JT{OkjhKN6Fm`Te@UiNVijpB zn4Cmlyv03|C6e%oCtr)+bi*U_d8U4X#=yl`&ymHvb(BSFvO6an?xMAE@B4W>zWO| zqtJh<+r7GTX*Tg-#WN$@xij-N_g zXv|3HabP_gauOr4PIorXyvm~>Cu$sC((aUDg=usAT<}!$X;#Icddl_DbgF{0gL;Ee z@wVgQl>#c52cCXb_b@}|`LU?RP41nGP_`NLqOZ0DwM^OLThJALUCkE=^Hg7#RjdB2 zex6Q0RTuiZ9Z~G{8=0wg)1~k5Ry`Aex%#~#gXrGoLAh6b%~hlkGtSZS#Z;jbDw!dxD$UfiQ z@SZ}Dn@Aju`pJ{QEmzsOR*R$P(V2^nGi|j>kkJE=^^3kP{hrehl~ukI_;?7rRr17`e(11z-hwS6O@YaJ^lD1pX#D*+R_m?A;KI_yYDti6k-02kT5fy_r8=U0Mur`GKi1 z1lew*Hv0+$793xUj)K14=)FHpZVgW1mgL|UAcAMDUt%oa{VK{$fNL((kl8t^q`W0O zOmJwcFF4V|y~Qz_hTfqnSZT$2Ho$q>Mo~#3c;_RtpCX6&3+a^XVI_7}kJn-f)qO7h z=XQBi;&%1N69ncty7elLSC7lSUWkX zCZ06oV_Zm~QD6dP=?O1i@9&XDr0;Vfi7EcJxKK%K!4&PpV}povs^AnL*YNbx9miW+ zP6zCQV$Q8zrw1E3E?DS5kMqnh^4f&#Lm?XQ27y=_ReM}AIKIw+L5YtFeuj=1y!S}F zD&>J$1pe&mK#q;i7Tj#P%kbVxlE9Ry!j54f$_*H3uVK{#pYz0}gGER<(DwcPwF*C7 z)e)=I(96Nuq6dJZVW=G;bO5 zz+m-u<@XyU<;nX!x1I)h+OIpzfO(H|_cP$tC0P?aZe~d!5V!eqSzyWD{((C$TANP-7`H6+E_JCtouX|0ou ze_Gq7>`NkWf~enfwt$df($#h8nu7UG%+-GLextXOAh90whU>Q`j2GWr?gh8^q%|9# zC8dp{D^WdI#R}7KibLud80FU{F|lC+wGDdbbq_GMKc}-Y)n;&}5O({gLB*>K#Cp8Q z;;9R#yplFnW?z{>E1T~oD3}sA5MESae{$`gyUG#pN9Y-_gYCu*2O!=TvQvg2Jx^#& z-?LxXJ3e&R`=STFTB=B!n5lf&3gSQzWd+9{o|n$L9k z!fBT(W~T{xSZqR3L-nH_pRy8{*Fq*2tu{TzC9sJc1HB#b5=u>nv`aI=V#LCK#&}>~R#&r+UT1oxZxib?smKb_g?tLb2I9;>R!I)y3^*nV z2g~7~KRASQQb=-RNrVvi6q}s0A((Qlby7A{Vp6aHlMkN4Yd*W2SZYLCv5Ac~gsEor zR<$HW551vlppnb%1-q-CuQ}JR#pB|l)9|+qUWsT%1B#2D35-2nz0@y#Rv?5IMBth( ziE&-?;J(LJQ=xVLZOcT5SJ)tAYASW(fXlVrJ*!rdeU*qPemH|kjyAkV{N_!CMXwYC z@aM5-u+O>t;REZ{4pZ6~sJMwXJp7-<-aNNT>oulr3`u;x|1HykbeY|N5ttKBP{L~n zu-~q~`9B=vKd7iF0^3~X{Z$mN{RM@DbiI_F;dCmkNteyaBExQb?D(@f*Kjt6^&KDj zt9a2>7!xI2j1aooa$r24&{Ra8a%!wvxlIH7$w*wezB=n@nB|rc3$m$c`77D*Mt$D6 zfy?>zekB3Ll_Ke0*hfcYHe0Sbg-ORHdb4)2D0+zy@EIatc@32HTHty0Y9A3j=@v&4 zuVWg%kyc&W0UpLp@5fL2HzxBf67jvp5>_coo5w4ID7Gcga5n8RGHoVa=vS|jtjCLp zhmaJ{T9>(<&h1n1SOX%WS9@IIMP{YAGTLh4O{Bm`-4s*y!h^%kVwI`0)_b2X$+%tz zfbLbs_e#BZ$A92PKTQ&Ek}5pT9)FI(wt6vdOnSdiQKnWws4uB!ZO-qU)U6g`pJb!h z)X@ZLYscfldwG?%K&MLf;EYr=>;S}ASopCscS6|@&*?^FWH7;Gy0&!r=6xpwn|{g6 zw4#`Dd`xPFLnF53J1)C-2_o+^w&ZjQQ<7|ih&R^>?g6qh&gJ>~dZ)Ta4S>)$lRtU^ z1i|`FSx7#mi?hbu_YrO+fbLedKS|d{KY%c68aPy*&g_}MvlSAUYl}?R`=1)iF$rdb zsvZb6AhlNo}qo$~0%;C{z`fnLQn}Ja-dGgUwDHik6!*6vk zbz&{=e#b?KXh416YdX>08dvLBbOiECa3f)^S*z94^rS%In)(*$Xf>Ip*o4_DtmCIt z>y0&~2oZY@S)|KfNom>UWGuDT@)YSDKj%U<*SLb{QD@Ng))<<=BUjO|nC^%R)Z@C& zkAnYsYjEbZh@p8S8RsZI-Hs>uZqeC4o zvN|&0x^9pdW5G$5{HRfUWUvc=oCbUpvUA2z>8R5dP_#~L&~x6v**0ChWKXN??t2Gb zHNIG7H^+Nx?LwtGxuYv?vpfkh=yV) zp3J-<>aPBxq1bn4G{L*wJ5_N6OdvzGc&dmwiQRATZ}4C7>A*#v6k^ae5jT>#Hc=5} z@`^%NFC}qg6YD0{PA-L=UW(Q*gC?`CQu=a5_V*KJX;R3q7rEz_0UaINu;H3$;&CdaJ`@ResH?@?W+vQMvt4V z56N$Iq`p<$O4neG??{K|V}EciZQ}`M&B3YDOJQNl!Q((-i@!HR&|*|dbz;_1+`|6$ zDOvfdJ!XIqCKWl*;jDcH%DP76QZoXJ9_aayKO2^IkINrKz|G}nih6=HNcP702Cc71 ztq|C3jvY?dx-brCtc>;4nNp9%6!RfKQ2O&Dn(`LK)r(})ZP$x>jM}^B)0!RyolKXL z{6~K@P;Xb)KW#LO)Ddu%w_HkeM8$ria^-e}RI9NL_4g{4zb08y<8irNMEZgV*0&4=*tE_%CQ~Lxw(5YhZf9}( zozdQ@fc;K8#VVeSDh+vh{D_^ku2bIUBOiVHl~mpCwdvoH?9=%`Uik2u0{gc9FsAQq z9v!pmcxDmi4I^nC$Z9MVl(we6 zBENbS3z(m8_IUWk+@o)RV`Q=~LG?BDzqBON54-<8Wc;`MycT%>gm29{GAjh8)d3MBxNh? z6`{H=V^QHVYb3&4OR3jBi!GkcFZqesP1 z&FK4X33_!Qj)=FIVe=fcI+?<-AgMMLb@+Pb+Ho`(L4V=tAej?gN$PQRvDOR_K46>U zv=K9U*=ES|(P7&DYTk(T9=3p-l;?c&q}LOLwXpK}(cCVx$DdPJJ-?Oc(h8txB3KgJ z+#lfk==m=mXyN=jWtyFa$|Nw8Wk#-B`YZ`{STvg_*Be*PYS73V>1E$N95=2w8XBq{ zsN1}dJLa-EK`AS`I@}N?vP{h7+hlvNYg*Z3kBwEA&Om;yPe0?Q5t)41EZFQhcrR2h z^)!2_29S+9`#BUJ;tF;t&J75^&G|r@hK+IrDth`XSvl;a2Y>fP4P~r&3uQjEei|kY zeV^d5#oR2p@_t~o1@rj6%b4G)O~$woR&IK{>sO+t2%?HPl>Cdy7K(z>DLoef-@c@(qW010^ z1n5=IgOU23iixf5ykOg<62t*n_huz!n`a%Ay31KIa`6Njp4&cUzokwJ4E``{C8LgRFu*3<33JbXG`7E1lP32WFjgHt%Q43_|jE09Kc%^oreV{@#nCxdp z7#!Tpo!uOFi~zQtrRHAAEl*88!3oA>&AyY0pspUpK=zsxNA*RuUJ}^$!gU2T)Vdx8 zk*JCE?cfS3W32Neisz4{>061NzGe<6nl&-uQ-61ZH#_`d_37cPi+Q2VL@k$t7SnK} zi7p6L4!J$zdo*gFE~uvn1)FAdWC(a$gLXKPk(E~^Qm0C}4xrn9#fmH#hy+~vgHJm5 z`nlEHu_lu522%FJMBT0?ih)J7Du!T4kXp6rZ->kDUfR#c29`dS_Fo^$ohZu|9DkAj z2ejfc0bB6FC#3#62)6F1rTo82;qMvaU>rubbfXG(Dlxkp*ee64oR6wQ3$D|FHlXxp z1qHgKRM2{tEjZ%9X^1hK3gu~F+W9XAOI$o*ofa@8y) zOd5H3a*`)wsnSB93UAUYyCY5=$S9G_*8Qw?5neW3htnN`O^5aPzl2YZ>L z^D3T632#%g`T3RVi_C%Elt&bZ2iahsW-~+J0!Vp%j=ZiLex?f@6g!%l&#JVEdg_s5 z(>+0&Q%h{6NN)*m#n*gq)>H&KAALp=`^<*UL&qHk2|Yhgle=9@^ZBGhC?)284kIZf z+}uwJ%6z6By{h##=$rGaPL!RL;zA^N{lfDJ9IT1M`bFkfmX*ACs$!ngMt{M3F;WZ# zL+9ocspd!YOu~q>wg{tj??#b3A_pzh>*Ix))a$z*2&*yV=knfDvvbs24|^n>9uhA#+iRE=UP~ltlqJm(@q#4!-x)46a z*d}Mw--_Fq$VqaB4csoB6uK(H3FpH%Z;7nTbQm7JetX{SkRSrK$p7qhWLMp zXmapLq8vo+R#BwyO+MRIz7KMYauP3xd2PoZTMww@AEsw1-r)MEyoci9Di#!#^05=d z0d%=5zMT75GT-2S-k^U~PVZ6!0tHw%8EsW~P^a!YS;h|5T8COPfoS?yQdT{s#X^Xw zaQDA)U^Wh_MM)HX@MVapI=@!fuS!T$z0kL-Ez&P`YpS+RUPVxL$4JW~Lo>~QyIX|FCkoI|}5j!yMd-JPhwqe@%T9GK&ktXAR21DDsmG*YX$ z6=S0q!YaS2kUZu$jm9Q?l&eR>Ig**KGsW&f0nF0q^gVtTYdX`8lg>w3JQ{G(Jp%?KkeG5T&}~)H4-BC+PzYRwtU1S|}zra{0TE@doh^_(^%&%>&%0p*J7& zeYNP&-uKq;G=?@j%bwJf(cGnNnU6?tPI$l`S^vNSo-I+gzOfx=M^;oS85BMN zLmbpXR?d)#^Qh}iMfpx2R`{x!h~%hcogm2AYJ=4}Pvz+|PXD9x4Y9^~*nO%M?Kr%2 zDWYk@bHe4b{XP+4=Z@iko}4?7j1G3vw)|YyQn!og-izhvzA|8&!QkQMctKPVZMqzp z)rj40Z!fYl+`Z0$%6>XbWUnzw_(j^?c&NxlJOW7Igl*Iv&wF&-SeRyDd8Qaz=ip}H zs%hL1Jcd}r)~q(JK+D8ok=t=U?Or?jBw1B!T;dzdBTc~4>aTVo`pjBzIU^WE_E{L~ z-nT+2l>qbs92$AhJjxnofci<`->k_$>YVh}QEvv$A-_T+?s-`e4xCkeg_Y8y_hzS@ zlooVwnKLqjvH84WLvP3VoxG_Ep{2Uw$;9E4(T&_r%*kms`+Qz&6+@bgl#R%n<;obY zhd6xd<|n&^c2!__oLC@3-040(+Y1RFuZjyy2fF5qAXrU*AmMhx(9tj&!l$mVY809f z0rf;YdxzNRkehMaE1BGsB&TJ!LG`V4oj&O=VeJbDcUPcY_}XGO}!QZsr#90@B3`*V%okE@{&E+YX`BzE;d{=X=y zy`=h8-M3n>x5ov-P^`A?a5mWrw^5&T4TA>Afde3LY#6qS7v^2=!)@Lx;M5s|UY=0X z04C;93z_n^bhG*LTGtx~4?k+yJ8q|wx-=b@6QK6pbTE3&e7i8U$b&MgHfKU2ezJ|+ zvC(-U)J&#TuE>Ob!zQn(#v>4Xuy$*5%VR1<#FNb-8%J)M(SdNw<_U6#& zTGY%N_H2=+8=D&aJkmvpnpn!7L-QKOd1rnD4}XD(``wyeOnn*-ZkjH;R)!R;mXO9# zd{)}_EiQdWHm7%?t9|b}UqQhGYL~ehb1$WS#nnz|o%NO0VHg3{hB3Do~dX&u@D&lAE6PR##71ENeo| zZSnY+>LIV$Yxr)HeDdBNaWhy?T9Ix$ww{@(P+Te{Brv0zAEp=Q{^ z!z(_eSm?ct>qk%qI&7?5;4Cxk8*i1^b8qLLxjD9LKI>=fC;jldiw{F~kX8PczJMJ( z29&gWdNw`Z9HXy)yMh2|k`!{TAPe;SQJc$(YUyc*T-L@S9Q(6;?IPN}{#s}HZ+G;^ zTVfo&d@(X5p=toJgaoJQ@08Da1IhufQTjf%WA%sZ|IRH0}92qRmM( ztEl4h+x^}m?*Tdm5)@c!qKxku@_r?k|5=KxLWhygM0*|YqY51lzs2t@5(CIUl>lw| z;RdYVj+2_hiOsDpEau4XQ(C2v>e2e!w`pC|J7MY z<+XPtLFLxibN8Sy9i{EGXR&OPo39VZMoOhsH%4k2B3`TT%8&fGqmrA41ToS3&xtpl z3*7rfIpepjsmY?y(|A4bj3|I6nv4r9C3q2CDeo|UiY(+RkzJ69@Fz+L;*c6jEx`D0xT9Pl?|_Wg!5l2M z>33A{T!sE`yS$dI@2C{R^fnsNxNEw4S%B`7A#831ypkHS+nYK?(`NFUp4%7sMc%BNf?S zE(*0F!f(Vqfvvh*Pxde~s?XZy6F>SUK%UsDljqJp#OZ{%NrkH&Mv7 z#{gtiOC{p+5m`8BTcBG}{jrGOo@_2~{EnVtkAC>*@djT%^+J zX|ksN7i5vW030wJ90(_Oqq5-Q<(*xR#+coktMWF-cB4eS)wHp(CcxWibeC>1S^$nb z2UyC^jJyMT!03YGIz~^Th?VE@$_YN7?N}4%KtdLXfqrcM6qkGxeu^8x(~~4Ze%cij zeC^SpNHeVASs|t8AGa^656~Y0st*e9oBc}e5D}lawd(0MTKc8z86sdZEM?9f=C*U; zhwCHGBuYA$o^$S`hc-*=p+_S@hG)~$z|IPn;q2R_6;?;8uK}{#AD;1k-sHqtT&604 z!gom_F;D%@#|U9HIj?nDCf9G;&dp2~m9guoNA}oa1x84o$Jihn*FE!5gOb2!?}yX0zNzE za#>t`Q8(Kv%Wfs)x?R5p?|464r-gFcP1%%&^K2%`P~FOeXTa?!DEt^`c5$9TruM>Gi6&uR_e}BpccKw{W0WE&TKQHl^y7=W7Jgy~CyX zG&6bIsv_r|15Xa?l|Pq6F9|;>DJ<;XB{4bo{BYP=8>*IwJNb>tXthxSjUH(PFMXE` zKS|Dqi6u1^uIWfV*~%(p4ZF0ad7Z18Rat=ypHWR#l*~z<=|BziLqzy6ijc1 z%is>@sJ01~+n78rykSZ={b0>A|ETqx%eu328Z;tyF@Fuoclq5;D^(_wY?F=8i|*f; zu6`^DfhA<=ZMEqU+Q|^uf%ylO1-%Zmj7PZG>&eH>@(z}d7HDRu-(?XtBmExFw0CLj z&>BabTFZv5sRk&LfldV|Sar38k|win%W4PluK3MDE*J7Z1MR99%@AcXw&L;qIBBwr zIvVKn&}p8RqsVJ8mYq{CY{nZW_XwzVA0o@1%M7N4#;ciSw6-QH<_p%dXdGWrL0Jq; zzJ@@?x9g+*Q%AC&qHT=U<%Lp+4Ar`>&1Oj>B-?S2UgsoeZ|62}^USL7wZYvzeV@-z z(ZhIzXtp6?g2%;hg!>$!oX$I>c>5~!7$nUNTCN@z=&l^O>_?Z3G}>5oPE_<7xNoRJ zCO(zWZ3cH<4dQ#eSmvAeH3{(AWt^a@5G1rU?L5dU6MoA$Nzj-~C#(E8k~ebwJfqKN zxR1TJaW8F4?2Rtt3!|+-o1;9aD9yE+t=8S`cf+iEA}3$PZMSaqM~%YqMUr&xhS+mi zZo82oq~E^)s*_}G5h0hG6n!f?iG<0rCgMD0#_n)qG{jmCl2^3Mb_k`ZKKIxdC@Emo ztDP9Bh30QdUmUI1;IP=}WKH@%ptD}=14TGL2lfHsOPh8!=Y`S_HebJxKN&xnYhEOW(?4bwJtV z(DUetkG!v#+P-qRlE#e`lvgQ|$F!d~*Sc`}f6* z8qQ0%W`r_Nysh$W7*&o&M@5;+Aw~iiLUDz9Fhi2o*G@BxSdPyb;gnB`wPJ{(qd7-e9idcF`kWF_qd|HPvBl(==8`o&D%)Bqt4S0UOYBpY$1zhq2XLq^Gz&7X{{G#uruvP8imyJRe*)JXr&ZkE}PP>6|`o+JQ& zVVd73Q{h-!TY-iiEUU9`Q%?)l24AsJ+#hN=rzBt1{OnyN3LiMW)i7TwE*&O;av!7I z*WZV?U;r3?Y^y(U-gJ1TI0>Bhj-}|U@{BlaAsO;Cz`km^o-;9RBRNd2!)<3N=g?Of zJygtNRV8vb>be=HJY$$4W980@nOw*K@i<|+Q89(_zOv3J0hLz{=f+r7 zP(_FNoaWYSuILnS<1WHIO+Hy=z%SloiO*(Y3~amTF(6a*2k|B&ChAhoQxh}4Mjnm{ zG}yf`&iLxq@j5kac4V=Tx#+{;JNH6qNE=?gh4L&)+Sljq6+0~nLZ)8czJMR%X*_`; zv}^_|laSw2(Xbk?e+RLhu5&3blRFx#86~UUC`!%q^;f*f7p!dqh`DvSUsE-G*vl?c zMBN7TbVjzOcO)1ORMf5nu26%)jP|*n8-+Qep9G_$6$UTP;^Jn)@6vGF4176083tw~ z&({VGS;3RSA*Jmk4;dlDCXSId+&*v8@ZrN+_?b)9~Z^u_q6erNuC5d*zvtn10DOQFbI!`V8eN8svdwl`#= zV>rS3mHe$bYb}Jtxdv$v6tU)vpd5O^L^R#2?rDy!pfjm~p0^eV>7|My1TrA_hy@yu z_2Dx$iN1$~HBv>8dUzW0`-mxdmQt9`JsjZ9{k|)aXi%1 zjf)FnuoLGQC|{IjiXChqmD5&&PBNAVbGP6W(EbDz=M%&+we4z zSzffX@6JNuE!(0xK-e;~{pGkO^dz}f=h0GOQLQlKI^rJr8(ddwaIeuze(+XVj1MM#ivQ3E^!i&;t~f7_V^ZZ2(Fu zveup@(kt~T)^@{1tr5wkzBuSG|FXq!<^ZJ~DSF2Gd>StL2m;6y`pNNgi1f;~duGkT zr?+0?bQI=E0mE?RE?cKZ#ffUG^_gn`!}qr#`)7B=r(b9iIAZhDOs*g5dinaz6uEp@ z8Yd}oxm}03rsv+JsYCyeDq=s19}viQLy!^d=|KQI zu>eW?BCFumwzqmjAKl82>u|-`!mL^8dVj3w+#BR8cSo~!C5RXt-IRXRPQD*9mB-Xs zgic%GX`8SZguiPzCB}U#ta8_f@`=PN32{o|_{ zIFI9fyifB%%-H@E16E{%k_#gRd$zy-;AZUEE2>efva9U#q7_5$4PioZD%fit0&+b$n7a!ZF7Zv)_@J|i#vhqn$bOn30!kODRUC{hohun-LRr0z1 zw^3ukqBX-^REyV#ws196+HFbc$#d8YfH1Ou!*_c2x+XQ-blzi%`Y!}^H!o!FHIt1Q zFZAYTIGr1R36B(~hzII1QR7L5q_|HyrIZ_o^it;8HS*UNJB?aOL)~Nv0<&+_7;dp! z52U;k-Ii*Cz}odRRHl4ISLlwLLr%2QCeJwwT|pcC(w-h|0X?IW zYVeBvCL&KkK@Y)MZLDA~_I2^s=A3Nv0N;{{DL(@*+LckSJ&bk)!;IvjuCTRgvbY5h zuz3&LOG$Kvum?t#sZFEPN@i6fw$_JjPpM^tp$3%&IH`sY9|lDfJt++`l%d|cuM-vW zT%k6&R8u|!s7jPGjyk9$1A{lXjp9prPgSO|vb=a6cecDIvLcC?tuQtrSf0IOETAv{ zt4vD9N7vgsOf^gK>Tih? z=|MbIdSlOKIKD3gqVni>80jp0BK3)B->2-PBO8r=<<#ca1sJ>!5iu#KLt@HFJSv1GX7-8Y%4_#vFpm&`I=1VZC~EH z`-@X@=hn(p`sOc;GMQc|Vv?06%)m#)>yYci?-Vd;QnzvxxUk&AoBnLLEERRmx6A>K z8Bg_sD^p9TbjhZmW$WbCfGnv|(A>D`hxnoz0@UlW8yLt05kdeTeQIm*-R8>K5e1=w zkIL}!l05b?)^yR#r*Pq^2r}MtavfSFrWZVNBVG2T{hm^@yvvG^PjN;oQeG}@fCYbU zJO`fZPF1KMdlwPln{i39o|DjkW4qQtX$h@LB)l7!Wb!&7KL{RK-OhVE{j6XX3E))rkUeiedN=*4J2o&tVb3TGWE(s(AHZ;X5|f}-n!#M_ z>Lul*Tjltbk>So4mJ9chXr!}Z5u;iHxl+m$S4P+G z{hcC6O2H>yU{Tvl7-0NE!a@8wQBS^_GT}xpT|Uz=Z+;oD7%bn^es1zuYtj9P9h9tKm-h z=I^+O6yyklw2CuAz-M2s_~>#~6g;*#%QD40sGjnykUiHwnhdKKMh~J$Fp{q#ieOK8 zHX&M#8RP)7_}>Y7{G6YBH)7ywswSmc2a(qHqj1P9`1a2AtUdB2?!IbF*_@i1_AE0- z55GBo_TKBww8nU*Y(+1_U<)_(9QIFUC;@~4GFj3~DOfvt=kK&mWH}BI;WTF}@(;T* zV)ENSJ^?`*SL#q;RGGB;KtoM@8oR&v6yu)Ta2rU=WM7AAY16!tzuHeNaH4McmZ?yv z7q&s64jzM;xI`Jsz@aJN_E=3pwx*{U6UYWtJUFQ^m1OiXuE6M}h1!l-XCcRU_0t_KZI~cO1dr;lV3cER1X+fT zgOQwu!p^#kB+BIG7d0Uq&T=yg&$G`H6egZ}tI`_;8!Mi*X72>w?o+$ext6C_{^@=^ zW^@$$v<%Dx4xKMgN!S3pIp5fNtx>ON$N3(Q+UAky*rsI%;^v+^=;ChtfkoX3NOH=m z55ljzL5T zh_VzuFBhuC#>+fYmj`0WiRmDjSZ?CrrXNuexX46Qz__>(MESf~Fs$@mjTz07oliX)+gm<01Hr>R9 zr)x2?n;a$ZcK{i#we6}RAw1ZD!@NlVPWGF zIPlD+?A{a_2m}=rK_(Wr6O!#4sHGrqN7C*Khi4r#mg00Jk6R;?25qWBghkZYlV&NF z6>Xz)!{tH9{;&IIeDUyDOrm6PB~$j%&n6hndfKws&xDN%^osgX52d8%fVo}wYt`;b z7YLHP-AN{vK0R*&z;N!zs7CJD)TS$mD`$JD#b#@i=cAWt?u)T6Z;0(JDIqUVEowZc zd4WPf?j^7)U{S@yDt3RTFMAJCkmeq1w+{*Pj)b=2qAZzhF^hg*FRY70^?Us^pgeT^ zSqS}wUa=wkboIOeRlIu*T)g(8I#gLhE=)rNJ;59*wGJ9fcFlA>1vCSm4)6w-g~*&M zV}@Ymj_ZUx<~66E{>nJYb#g59S&m2m0el_6;K9zs=^~~$^H1-`3+Njf z>ex&}hR@0NY^h(qThwsIzXd5^sR^3S%pC2L7+S`Kh>noc1Pz9c6e61MEUGrvK%5ir zurg-J*BLeJYD>G>`|Lbz)iUBm1*;)}{9R!HqJ0%i*BZ9PfT0I)MILuwYYtsQn7LW& z3p|eWvKpx!VvU@mjVyIYWRnw*A~tTWFK`oPKv?Pg_e6v~*J(0sy~YUUG!%rObj zf+V0qbc`aBrl%PA7b!e)9wA5w)B+FHNFOCV|d~}17-0{7Ywn_in$!Z<)-J0c*L@WAW zHZzzZsx~H*=FCNl+krqj`;*Sf!*^L-Q>ij%*16-mYflRD+jPpumD@hAzDl#S9A;dl zH?ErpK`r$5uLYiAC1gA>ba`ky^oPl`R7liz}uOr0E|yzoSl zh{;@@{NWSj6zBS=B9I3&c2w=AM#m7SQ%KD$A=ITmNer19XcN3gO)2WPsm&G8$eNDd z;%EvNvabT7MHgo(Bi}L;n>8Xr`J#>vZa1#?pv2pqZ2i_wu80mUtYEI;NM)wEx>NR< z(2G|NJf(Oqd6q8U8NbvchWw+@b}d^RsL6h250Ns;y+Xg$w?5KmN&_ zy_Xm2P;)LLCl}Q6`tlqIx|Qi9a`X%GOTT^Qo(1sjp(JOT$dLK+uX&TihrMe@_Kh9L z=nG-B$Z*EXm;04g6P8!7K-$139smu+sIDNs3@cDMB}Ps?Ep}K>q>6qx?YD|x9z_g- z-t5k@YQ_sX^wruEsR9V!uXt8-Nuzbm>>K&X_ItNJiv}Vq$24pDgi_NPU&?HRT@+!L?#S39 zwcSiM!a&>Yo@rM_tDuozY<6pApa8r5QWUiyV?A)nb9j4occR@;nk)nW znC;}vXBb!lTfF{mFEG5M6~JddupGc@4#_&lx=9cys$G#E0(fB_{{_h12u2LKch|nG zen*wu7>s;}FB&kJPtKQmcVq7;3mdYZ@Uhay3R7BPyfW7sS}+EA`~R5D1~D+hVIs6l?3b1XP>f z6`L4FyrLIvWRaQXzP-FrS=Nc~Vps|gy7cEhQ`o<*cD7@cT`e!YS8)S&QZ&#L+qy_y z5b+|S8oAQ0bndHVytUK9Ip)WA6T3@j*A&GPw?gtpD%uKCV3eJ5w7`p3I{yYsr=I>? zV|2GCQs-O_5HC10uYErN1t%!D5tlzj1g#1MiLq|DE0uW4&4xfPW8XnwLqKLezhINx z0!Wo%)(ULUu*8j#4r@TOg zjwF#i?L586myhmDW%XF~3Mc7jm+c+c${!9l(DW~RM~nOn7N~yu90h)4u~qv%uDE`N zONT;Gddt>p$w&L%i3wN5=@KgPK4pN@2lEC0!MX93k<{YsK$8TLdnU{M7R58%TR=c8 z4AjBtX{#=cI=9>uozu;+^7tOXR^+@~TDKCzn@}0bG2lEs?YHazm)ae!bl`8t2Y;(% zz?|H5+?XtY+lMP}$tLV|lBq%YXyq47C*D zygGt)N{-lrEHB&Z93+sx9m4oku6Qn)Ul`jnaK<=0Dml&fd@E~~yWd$Ql))(Kn6r>Wg+wZV%=9mp{=#=H}VR;t}SseR-sF(Vcexl&M1+t z)pHgCQv`#h%W+r3f;Oe$C`i|4^?AN0No{sgZ?>n3XhzEmHBOf@=n7Z8B%uBF{Y5sa zCZfsrG37y~8MTV8o{e_v0xhx!owkMPf^85>syAd9==e?U_QeYsS%%L#0-=XIQgbGO zZZPrNqRWa)fyt``*0x~>r3P73JzEiZk@GIotDg(;86%*qzSF_(N;5#f%`bmbf40P< z*9|3Lo~Ts6-KJ7d0g)8lces58NTLSJR4x|vQgdog<|FWi6NDwZ6I+!D{s$T z=tNf@7w|w?6Y1(OfGb+}mw_qw?mB)< z0IUY2g0P6Pf^RSBx9UylPZ;qHH~YEh+hErhXY1btd#K~=08e7$FvDHUk{??ip4#l8 zT>7Bll=XHX(zzim$K%5@^f&0;KF$K7zt^L4E}?lkAML;QhkF(tq|6)BzV~HYZ#a=< zy?i-{Ia$fSAH0LvXh03my>Z^7L50z=hODU>L}sNtCP;bn$agxj$9}(57`?dh6-4{1u@gRzjjO_l2`92)`xv@RV2c5>l48aHglaYfO>t>a{k)L z@m<|tws!;5iOw7Zc%7E8$ZHd_?XYp$^I}(7MnzZ7PDI9#=diddHEIdCY2AdO=A6E+ z>qZHAZmupP-z!86#Fh@(>q-ViC~m&AhPbVMh6-qhS<|PQto@A$^pU5L-N$NYZ>oI9 z`90s{6MH3zp$4`chaToRrN8U_+%4=>o~|*+L3z3l<|2T0obffVuXov^_M9US*flEQ z4B5yNSFeb75ykq=Jkh%w+gAx-?)%{Q6DHLk<;X?IsC)K2xdt8=k)%1}J6& zTaz!f)3n;*qH!~xWBL^fr_g7f$^^t_8$I`8C0-hJo^)LtDK1tr9jIW*QU0I@%Q*qA ziVMJL+PG{h~Z`S#s*K2hyMm;LL*rfgLH<=(|2!CoL4$C7dct8b2&agnmggxqF{M1>LFFWJJ zj>q4?y(D(Ro(pz6y%_8b$WtYWY6C{Ey=3g5Sn;-(9Ghmr0(h_(1ZRxAdByB62a;8E zlKYSg;BSw@%<=k-dq4MA7#S-^ll@;&D+OV~1m7AAe-4DmLhTezvU-fmi59k`W;d@z zP%Z9dV9{RB>Z2rV-r5R4(q6mFy`Tr#edW$!SS8j{Q$K)r6c{9lhvD8cG7}OYg(f8# z#PxBuOxK(<0J$ys^O-8cWN*qo3Ki|Fy7?8r60?9V76(|vI7j&2YRJW%J>|SCXh2HW zSFTRW`B2QmKhy+hmRWMrsFYa704eeD_t=Lgu(C)!$P08D?)`Fkgk(EN6ur=s9nT}4 z_eR-1$}QUB*;X3-R&Fhcw?=cu6tkM-?U@7$d2jRKYikHqDkv7@nl)pO-pViXbwO*C?Qb{79(Bv zy4P~t!ZDugU+%Pb7%Rpx-^1Z(^Mter@$HNuAT4~~Z&QdfZT$rk-bcx?Go@kl41)g_ z_fZ6$csgO0gNN~=BbNQkiKnv{i^9aPg9Tks1p+#+-WL@)Id0-St$uE~Wu|?+D@Apu z@n^Rn?242A0tG|NEP<&T3!|k{@?}&uSLFMYS-f9b-h7Cdf9j^pD#W$b$C(|53jxac z@4#L&uV6Nwwu?@7C#{J)%$By3N}bd|>_sf@+-i;BhvBojRH*b>{USLHdB}W6zLT0r z$XUiW5aGy~N=6GA;`QiKc11vstKNRmYuB7jF=MG@{cd$dL=@0e*Z3ljzBLYstE0A* zMg#nd|1`NI;4(8sW^xVvfR_IBNDv=yH#G)FqXg7aOBoPL>>4zGkN^kcfgRS*3|SyN zsA-+YzqSxmGhm-9#B2CZ48Q~T z?Ad7wXh@G{*V&bTOv+clPX8eDD2k5TW8Aej+5p)6>?o+PTx`1wAjn;8KC3Zc7PYOO zgc`2gz{K!f-HueAUtxE+eDO2OB_6w0Sx^%+z&3`@Cc90yqJB%$#!y$dw78^1sMe!) zMJCE!LxpTLaHVoB;=p(sIb+*1`l@@@prLp4sBj98JD5ZwX|#{)!? zs7JeEM$zs+f$Tq3CY=Mk06Y=;2OP7Sbdm<@KGz&tN`KdL3}ZRu#RET6kxUy~eIrY_ z#Kw?bmu!wiHO>W>Xuv|KXkRQD*^L&JbF@vpA_4iZU4cv|V@AAq)@hmWdFVE+uDd=k$b?(Hyj?oR>xPmTNM zQ__0?+H=jsfIsXf5cGfiB(6x#bkG1`^rHdbxAA`L;{gb~JvDIkd!GT3-_xVN17!Im z0NsqWjS~D*XX#J9`RCKuN5Iwgr;Im#m)h^M@4*9Jxp}?X%*Fo|kz6wYuKr3J)Ak1i z`R#7Xlt9)ji%8?0!{1r7Bai>voB>qpv9Nzh`TTz??5?lR(0_y%1Fs1Z{xNn-+sdNP z+N%-3Z{qY zKRh^s5C^(ohzR*6*d0QD(~ko^XJ-5G*x_y4qYtgz;GNYIQL)~uohJH2E?hU5Oi^Qk zEZZ?fC;(hK2vEpPmzSF@o>}b8dt;O)pfrFSIEvHelk>iG-n^@KM(2-eoF$Dr`z=2B zqSdy;(Y%&&FST5+J)8p@;5 z;Yt@kUpG^Z!nMQ)@Xq@tTYBdHubi}sgL~f_56}AKkr(jO3voU6A)#pvWe|RB^6fq6 z#v?sjI$_W6Pv4a}>}|^lyCZepm4&x{%~bNT$%KL4w5Fu%%>c_<#s-^}uotF=Ud+Dr zTcQh1Hg4QXAfi2TL>kqT+#oZumZ;>qY4UA`+hs*(Aiw(k*M)TV?a!T)NH8sel$P3M zbWPduw3a?h@kdLBZ8i}PUPHR`-9MgG?sI`VNgT0`;2#87<}FbPCo^zt0eEemRov;t z;Y;18kc+_bhr0JwPNJ&-_Q)96S`PrEG|N-j-ET*W-Z?D}*9DxOGXm%f&`xt#p)MVrSX#l>axdQu|J#B=gKn74`0R*N3twNg%&cU~egW3? z3+pY%`JO(8ibc1UFQQAKPL%-cx5XJDI(`z(87okFP}}2#hZP$u($Q#vw%5Hddja&q z&RsyJWN4CX`0PC-!lnk)0FX#8gRsD!cP;4Rt&ttefwC5W#d-1MP6!=e$(d!Xp*EF# zWGztq+`21)ey*S~B;sNPB;I!obK~9`FWKpUarRl|Up%2?nS*U@mF^K;M&?*he{UA8i;bT5XSu@f-Ijx5(P) znZ|4CN3O27eMeY^-)i|LIt5+m&9M*){kBqb&@3ZVW9Yoo->L!+=vjdFf0?&oTM}Q$cIhpLYZ{!FMqSp#@+aZlrHS@!RDJBwySZxnyzjgO z(b_|`76r@pFgcdbJq7yh02a6iK#%l4E%yYw=>3ROlBy0+Tq6Zc&3{~##bw1sa}vQj zCx>bsY)m0Lql4~9dPko*KQWwq0MNHyYEhkK>w5rs)!}iMOJ=d(2#wJLre5rBooIRB zzj#60DPZV2GLwsT+<@l`jDsoH%#Bm8uy3Vi=R&o4&uht+xnSQi;w}J2LpQ>!R5t}E z!H)MTBX+k;Ns=N1D5+XIGNmEu4L-m-ynf<6E)6zVL#j_Bz8eB&D7{`a`V zeisV?8m;>h_AHuv08$s4ZE47thaJvg9IOf%B570i{Tw=i9;pfQVA4OaKVB2H^q|Xm z?~cz9Exg<7px$(?9zr z6UpZvKw!PvpI=2YV5=Ca5+g4j0$^7!KNmAu9-KuOsa+=&P~+|gk_NCDZms#1y2Y2w z;&?4NlAjW{-1`ezW6nK;iws<=oX~S&Uz1zNOMZTU$fJGk*p*X1UwGUI)9MrBVRWz^TW#mv}WE|a``Eeo@`fsl5CxhxKk zx>byO0nA|Fy8-lE6}bt^7l;8)P1q*Yh5QOjn^mL2@&h~}^0?mx8_H+(df)wOU zp8&i8gL^g_yN_`rTUTe$`u(82<%SI6)9Gda#C7VV+LO5f=o`F<&G3 zy%C4e12}9fIto$q0|O(sOmtZSN07@!e4ZG9=nFN=W4H9#zzLfV-U}4wRx?!Y=HIO} zr-Ke}bvvnay@0q~yCfZSv+8Omm1yMC)oKuwVMlQbG18_Ma^BQR=aWCcbY;2G7k@yJ zp-($i>LRv5T?O~c0Aok<3da0$n?f1P_jetOXI3z+_HvSR`ba~j%K?*#-ZdatDUnBSA4pFrt9Ts5OjWR0oB2 z@#7o>nEp&mK(t!BEerk~vJ*T__zz$}7k1QU;%o#tSAV$z{G6P)=2Qm0C|oT;AG+J1 z*nRHveqPRnB=%D+y5wagM1*MMtfp?X!J0tW@MF;`>U>)s z4o`*dDZ53|Nz3|}dY=^l`&bUwy&N#ZVX%LI^SpGa9<6Mk7j>d1^21t7qL{%vCozO> zE@o;qvAuR$w_)+^baDP0c{KL>7c>bAe^zE~1jrM$Y2oR5isiD$_Wb+HaJCv77RD^! zMoO{~WBJ$@))y{M7)E}W4h`OTM52(_Ny%cq880d16O<)=fI}yW$1V!AN^PTf zTjFyf$a+>Pts+7g9=(2=noO5p~j)Rn*09$pdR&%C0v1dP;upm|9^AEu} zyN~QV{uny;@SGq$nPk6dPJA1*5$^ zr8zlwL5!)YRNlrKH6r+lz*22gOkD+sKkNMmfD;7~#9&eRG-LjDDo}(@_=XCwD0pRg z+3og=&##!puE{Y8?TF`Oo1oj?G)wyqb)uDx@bEwPs)8pv(HQ`wZ}rwNsH$2^*W(E7)n)$q+od#9<0`Veu` z5k`P=_@MKlHb98>1~YQE$|bTtX-hj0B8N9L{-aAg>pqZ*QO(TxRQShEb8;Dj-q^O< z*$QL*Ww$8~&5H$Qx1T49IY%o!JWp#f?4Flnzd@YeY)+h(g9p<}$jPv6#gAynE8uV{ z&|6sG%m3(B)0g4ox#PLjG*%4~9)0rZJ_6yE+-z}S_mb%a=adpFZ@RAlzHu-uoP=SP zton7lLsrKV?Q+C=gOq8CPJOeAsRZh7FGYT(5Gad5w19VvPv?&EGp4>>NaT$b$b{!x zx77k?DT_u6U>3yREuQ67+qYeXna2w`d8EH^9qQa1vWX>smv`xUy<#s9psbWZ0n9N# znA+)!Ii@L!ABJ%RMEqA! zbIi{Tz%0p2!<6pe{kNOKox4>>0u>>Wp3n^}BVXpK@76jyi?&jhzHK83AXh#sX{H5K>A`8=swPO}yALuOO(EY2V(9oR z$%&pY3VWvTRsKj+3(@C0OWg(K-c&J%(yD;EXyTkbAY}klo@}?-sc%9h=NzGfl#aY zNlgjkNVD5>1iWp?`Ba>35K)k*Hqhl!CDY?9t+p{Y0rAGO0(c>ppk~GQq&%62RPQpI z0t7xlmmiEb;?>!Evp*E9A`*}IR1J`(dFk+{dX#ul0MSK3EoC7X_^ib2Q`d7biaiUx zoEQ*y0)PZS?R^`pgaZZ5;?(?B=+|j9{L3Ed4qDb&FL*}rrEYG%aG&i%@j{M9&7|98 z%U9G@%&)OMIN_{zF+~_X(rWi)^>UfTLJMB9_SYuI}vsG*+0L(dm2$ zo;khF&9DI3?d^@q+OG}o@muZ{yn5RPW(iIJ8UziZ_sA_ODDyx7J(pJ~db#%4L8itC{mOoyzuafDLk}#xJ#SAxN;0Q!sk)-{?z-Lh75RlOJDzx znOQAvL)uzuE_kT^3k{@W^%ojXLH!T9?q{~6BWOzsD5Q4Z1-v0-zk!FI`Jpmd)(1YR zoTF*&&pt_tiBO0A#rrsyMtqlGGLh!~dta}D0bF?;{}mYA71%!B6NUCp>Z;-OXzOs( zZ&=cJ>y{d;d_`(g3H0QeNjwkGbtl_4a7vjRhH?*W)pMVZVCpRT)Yc+A6>xVh!ZjP< zm)e;+$w^hf>h+zoV(UU**!Axy+8t`Flxu%z0O@+5cou-!>vcK-W&zG2W(bAZ-*C84 zf#xuE858;fbf?pKgzV&}d27)$b69sI>4h5sos<@C^gu!dU{CFzv8uLQM2=)U#iw5^ zQd_hdX|h7Tky-hWA3sQ?rQdrlKaS@stmGTeab?wl)O`zJ-1JddISk3kvm-&Jkr?Qbhz`aBLsJwz`V#750-Q$sJ$7|M6X)}vr*0+q) z6m7X#IIkreG%ei~%NB2Vc~JgDV)tR7m(_VIy23Gf<`CouAa;+#eDX-_|6npEAt2IV z>At!`_dUP;^p8CRgoNjVsv1o4;-A3SIJk0zjw}8AMLjFvPXv`z*F|T(&MZbPl<`@F z#bYq9#&U5>*CGzEXFmE1c_!td;Y_QXX3wcUG6*-G)I;Xd6V#H2 z8zD#%kU&#gO|g~z;~EmFYOw097tSrkuJ5$E`AhG-KUoUVdJ>bdtEN62PBz-(WF6DE)F~ zzQmL0w!I3V*S5OLDlXA{=kr>*R6bsw*+^)mQ~*Xhe9yDayQQ@|Ay@JdsM}K}*bIm8 zoIK1SXI(z<4dEnpkAF$l{r#sh^$AiZo+q;U04rji7p6CC31APs%b#t=UAq>{Y z*&KSk=-wmN&4p3Hq9EYRqn+gQmnpeCm2I|6^gOs{Zb);xvw3K+ya1@)c2pij`FZV+ zY#@Qnq0-rD80`#;a^u7}?*eaT>slEu>AAP}RUc;1FBN2#{V%!aKJ$ zsIk}!RjD_p>RgoZVib0J(VMT^qLct|^bJ)Q$!uQ6px4#tEcleJF{-{3ebDY?VkT@jjPW~2b&)O&HF%9o1eCaT#%F#LP)FC3CNrf*kHuOK zxvT_T|4w|d-_qs%Ul_13SdE#`il$=Fl^nRuTCwVvBp{oH70k1aMfL8&yk?w)W8TnM zI0@`Y<^#5^KQGbX)RV2U4H`lWI()>ecM)K2J1?^(nxDBr_A2O54aM2;y5tMb*CI$6I=WA7F0Z(Ib1>EPZOx4qa}P0so00GO$~EAT ziE`3z4r4jmCp5M&o(lyw)su76$lgz(45E*Rbd;X~oX=uRLzPk)^O_ct)#$et0Q2Vu zveq1#S_tJFl{Jv^yQ$lZAFT15HF~#Levcb#?YF-hR?u&tk(}g}xYGAoEnTzxaU5AJ zM@3#n5=vL4fOE^UBxNNt$dLPh#KQt0p!xt1M|ZHCa73YE0`Bw!R0E)~QtL5^YP0q8 zKrgw-_QKd=M*0A_T&WBsf_|%XVS6`jx@?G)CE4FsOjLNNZb|AJPYXR(T^PLU4*M1r zO;#pNN}@4Tf$p=gYC*W{B-7SvR}UQQ;ra@c1QwUiK3%Aq!coJ0G`G^wroEA4TVgue z)1)hy(oqNi;&>xu*9P4a(N4T+(m>|qUXa*2dTyiOiW-MBDWie>sfP!s%R|1zu!(p7 z1}D9J1qIW|>7yKz}g=uJ}?dx;nLSu@L{Ie}E??~QEe>crti&<5ELN6JnNWY(w( zh@1aJ^WhD=?+XIvrXa8H1jt#MF@dc!8tvxzep@fCfe!2K1iDn#%q27#0{R8jFXk~7 zLpI*DKDp&3Kz29?oB?K4ONSf>_#a4m5>a)l&hPS;2JNDU$fL8u zzXC}|az=6ua*vgIDhw4Aj6ca(i7;-le8V7`(>P}Hp0`P(RN07th2Xkw-J8*)>RR@a8s71*IygoprnjuqcktE^asAQ*DCx z)UE_yYzAOFA4D`BKZ(l0OYwh?%4mC8SsOvM>3&|YL_c|dv4sLf2lTHv@PxShlqwM* z)u{Ya&Az`^-vGQXExu~~{y~xgIQzzU1ExEla|ti*o$04=4(; zu!aeSRkn}rjw=iSNjek`Sy_Prx@WPV3U)-AF9eC4xNhwSe}Uu z2o!ym4Jy1>Hw`@H#?&52KvzJ{4VV1`PjuLxfV|{+_MHmgLtc!q=AT)w%CxSwtJ!jn zB6cK$Jd~Ia2XoSmLwN21jH+%`ml)6T;bXCwOtO9rhvBlT#m1mYjS}by<9LB7^z4odzjtD0?;nCnfHcwQbN@$i=lapuhtVJM2R* zzJCKcVbBEPnXL{rH=Gq+S%lC#Gf=n}9M< zJ1;4dUAL2Aic8&35z7<(g=g7Cz5NX9m|+~jM{iG(?E`M55Sz~GRSChii=rL&B_K<5 zKT69$3HIp$jSl+m4r=1*C(Sd!a*`#4TX*X{mRi{%92?}ti24vX%k2|vZ&%Q3kA2>2EM7(4kqhFQ{PbjL zBFNJvSsdGG$hzcB;tMa(hu`edj=`Oq9=M+%v>XtB`+EU2;Hs=mXX|pcUXV-nlwXaM z%u>gMq37oSM*&MIxi_~|tt5L10m6|jHC8Q?l500DrEU^9f3~_JJo`Gm8atD_!6w&j z^H7eddDzKxG2pRsZv=pAqV9>jb4M!aD)B19g>Mbw@Qsj(Tm%gn@=8p@#YJ%)#)> zVj*rs2p9$J!V=}-D*o@z@t>1vfyGZe8{jv)K6a6PGA}8Q_9ie5E~F*8Gz%Jorv|;vky4EhzlQ zoy#wC9PgrJIx*2zo$;RHk1Bl_s{C^^DlTzc$>(p1rT&LU{@3Wo)Bd+fl8gUumG(#A z%$1R4X**8w^YP?xZ{y49n*D={v02fY7oniiU?nkcq>tC~!JmR#|hxVz&FCL|I3XD-z$B@ned3OqWI4fBqYDB16*ipPjL3X ziFG-;S0U&e-rmNRzSyU z?~lCrZ_+td#{VG7V`cnL8a{rkjQ_!2k3Hjm@_PTd?=s9v#xF# z?ru%!Y(`|;!KMGxn(3MTaWO8gIU2h+jnQD3Ed8Umwh*2Dg}va*n_F8x&r}$ zX92AH*O6$bD?CLI%gZQ=`Y}c^=xUC;;ExAN#Y;$-&Tn_d;59s0_;v}H&&I)gW@j^h z9VO}G$WVD$c0TL|YHboV7E97}F6eNb87IJnn^a^ffn43n&~@dzCI{ma0t=@9SMukF z7yaXMU1@z5Z9YTYT~OOk5Lk?X|LV&nUhvLfuIeH4nMZHsX&ZEcB7grNEPp+hNgbK26=50804JuvoI#Ok%W2-;O4Lgo&_-$GBU?`%Z3M5ECy@B*^vMVsNBAA!p@ z7#9u-a{{YZpOGG`d1mFhiiX(U1V+)j1H?ji&qE0h<@?X8`@m!ic0li%(5`Tmlh_&k z5+ADI7G!i0EBqqAU!N3@kQq?Vh*HA8g#Ndc{WJV8%S{=efMvT8Z~y$?zpdk7g2&_i zSwhG1`$c{K(XV5DIo6j02^`zUv3(q`AHT29hu<9A$FY4J+sC0b{ERmbzd5##|9{vA z{ncW#LoR^hck|0;@R!}#aqN2>`yR)>|8t4w*glT!vK923<*gg&=aO@9`{lT$6IJAc2_43#s9Q%V~e{k#%4kd8x503r8u|GJp zhU56)*dHAGgJXYi><<`*n?ZMko|;{Awk z-=wG2zDYikB=o@{k~1ihC6FczCq3my_HAa5*3PB27?g;ZttPvV8)snu;R}-w4#mAt zEfzf47g_I1B_G8ZH?(SC%d6cW?o}qNNZ`QnEfpmVXk`L~UQuHo&H0}j$~L3Dar`kt zdeZ-u_rvX>IF6(e1GV1|{*nL5P3^NV;UvRCqdWgA7hA$Pa_^2efuE9oB9edic?aK! zdl8*R!EHnSMJ6&rah{HD@xF}PAvw&C-=41cm~uDxln2?e9vd*1$kqEl`{+LUo+CH? zz(iIZ|0~H~)wPcK-QbV@TnzqPPAoXd3LRBPMox0UgD|?u$jEem&fqj_dCSSxCnMAR zkPqe}ZN>a64~h?l>V<({an~7hJf(P+XfrF+RE>LGkb$7TsuYM#Xi@NjJCM)b8w@F6#gHW^E3;u6I{Mi%j7=~ zLFzp_K?rrZ_v#33oX@kf*Zjz&rTNph?ygEyLW{POsyzlGO444`>eslMCb+?`ADPEr zPhs$wWNO^+3H8^ID{&j8@3xeqp9`r9>o@X5h<~jI&(*}+|!Uf z;pICR)7fPb$(WFJWF803WAyG~{7*^va1ln<5yZXB+P%4L5FM|cL9fn*kVI7du7{?8 z^!;^RMw4U0?d{yglecza+d5Jr-%^Jey|_y*nWO1t8K+$W3Vrk7h>G$^`K;d{Nxgd> zEaH5Lx{lyhqiV>{oB#b7Jk7Xk_~8}mlnOf4K^C_QBjJwg0gT`)fRfpqiSju*ny$~f zpLvbV@a+gtMUx>-s|Sy+-1H&M&<}mtU?qo}e~(q%x^RC}U2o_eETL2cj*Ck^qowNp z<03r5%}8+%<&i2U-jH))`Y((!>D4!TwoeEAIz4fNy;wz^h9C<;U$WheT)?;zo7=LE z+%zWO;|!;^!~Bc1uvrqV->uF~fhm8Wu{2KetA!wxPcrr0OK%Pvl?M-x+{vew^2N2C z^-`mjw<4J7mbaTDp67Xfd&$X!k#OtpTKAvnHs2%MciO~f+Jvv&)H>pfGT6u&9|Gp& zkjK){(4Cui``0nN#mn)&S_s&2%8W~t_so_to*;Bs%;q~XgqyN~qvQ3kuah)xtK;X- z{yIPsm$F_pTfwyVJm|y;!hM(4S1~^Y=EFuD1F?Cj{PG7I*P-`tll{mS&meTZ`{GL+ ze=}dUBfjJ3&;NC=dw?6`>AXXH`og;LAZ5Sqy)nfckv` zqFjJ#Hw+3>}+b>*K_uE&>egxyRU$rqdnfEa$i34y}kX))zS8RJi0qfl1}RWI}E`{B1;>QPMo!+G=^ZK{J{vy8C z9Pw6PWvg=K6Zv| za7zA{u+{I1vRJ?+WY&B91#P@E-Yvz8>l2?wO=pqD z9(AK9nLap=>~6**^dqfncgh?Wtz0rl=>#(F22-a)k;9_&j^m#5g{%yTp@IvmwWHm1 zHdTE4Pq&md#6;1XtXo^P=SBXlHZk{@7#hfLU2Hr}xVBINyr}D$BAB$2-R}w;_XrE= zeFzJ4YqyIoBkZ!TM^o-Ib+FCyb#HH;yPRk1{Tt`UC-XGa)R^9Z?M;B_qr1PQ)~B2Ed`0_ZzU= zIgUs#PhGd2;KW4ah)Kak*VPc4eID?FgFZvne)+8lkj zfqHDGV}tp?w#=j()zu4@!1w1a0SxvF+fjwZ zrO>)-iHZXZ+*9~T(~(_~xIT#`5X@QE?DW-;g$ZH$OU7#5%SRGpXeaR7-KDi^TE6Al6L%{Tb9eL?6Si>%On}$&zHT zd(<5fexR(Io0;!p87VuCsk;dWa=`?6n zuG__-x87X2+`JMD(ZZd`Oxc7Bqvv@?V!C&CK4t^94=^H!!_vdmG$fZH(PX$HYvDGX0;{5Hld7rPr2x4n z%c{|Y;xE!Yxcw-#TGSRbSvwSc?y`!l1Q~Wd_UK^LZ|ZtZ)0c3gYHT#8=?&U;8Oev5 zd4Q-jj~2TKy#!E!{_V;vxqaMMz)UX7h>2wy17lvJl(A`hPg9Ggz7!I?obdbeRQ%8sL?gqRzcUf`WVQeSavAeB2U4;=F zorT31at>OY-}p`&f282OhO6*xlM4 z8biwsTC|UJkL{PkEIIk-ks$&jv0|8c?hMedE?Nh!NYui+Fj2MA9Ol)bNByg?>mE<+Pbh2X^IMnibxd{sRAOs ziV7kfl->mCB~ql5hz+Ew^bXQ{4WSn)p(BLeA|SnnPz){K;lB5Jqw&P3-E+ve0cax{abHF zI`2=hxKn$smr*iA1&Po4dM0Ccr_3;>ntD;S!q}eRgowjkZbJl0l}vTJw;l3fDrOPR z;Nldo&uGT~y*`+`vzVz-@URxu$&khu4{=wYixIGW$gn?e?zmpxn<|emF%fw22^;A( zDOg)6(9N?xjIND7chgRy`{{7Sb8Ejsc+P3wy@n9%JZj;+@ql-n^Vn5le$S;!$*vO@ z7%;Hzbl86X5?XL8eYAU*>DkmPh64q^VFG$cZ*niaM^2lq!S}7TOT|(-^1Sl*Xp@&f zRoBI5D2hdC#CZ6ney(+ zT3$P!tmjm*VH+k6+|it^9@C3!XA8s$jW4}ENhZcP?$DmQfIZlQEVrq2dBH1*nDCM~ zv_zr=0WXA>$$o-s0ZOP`CmAI9#@+Yg76ALHEV*%HbQp; zrMJRFSF1RbKR{+l zB7`&FwH56jg-<_`!GLsyOj!oY&+Q|KN4sdhunM)db?5It2gf$Hg>m#Q8SeFZnpAPp zPm3=4-bF~(tcWih64Q4CLwvpBSI-x#(5kuC=0(2wv@g(fxVIV?T#pr=tH#)qQM`CI zK$;K||E$e~rc>51+mHH$gbD%oy~M^&*hG9#j+mNJDV$|nJlxf(exYglblc24Gg2>G^b(P*LO)W_*4TuHvo5zC0(~Be4N_lSs_ZZsZ^m z20B+a?>3wCDL6PpeLrYTkOAcSfrW)rotMRHrn2>VWO!DRd8!0_2N z0VZEYd~yM*U;^JL663L%jdsI>oB0xxeQ*InhENQzx|Eo~R4xbt8I=_coe`;)Op8># zY7iF=OgbBL$ct!z4vvR1$bHFNe!9@jZI-|aij0_#w zBgd@6tLarKNe29K5r)ghuI?8{c>DC1uYV?|-cyX+PumQiGQIkR^e7ge zWW9V6hvt$hG1|>yJBL9nNXFXb4GzS`+A@(`!`iE&jj&zrnoV=eR>2g_Za$<_9ud?O zxb8qrO)WR5=V3A-_GzPY?^dm6a1{Pj^ZM>t8b8nivPS^#YE387{bWrJL+~}$2oHb8 zx3}=F;$LYiZ0yMA!m5|8Gm z1PqOwB#^SbiIOJ`%`%k5;sO*}6efOfCeOV}$=2XTp&Zwz@Y3+8fl-Z0Q?S;3@`tf8 z{WG(=cHJ>3A>R$xN9gt~9|n(mqj;}}-NRNqZr}t^Qu(KHYFx$eCiSuV5OaPpZ{p%9 z_40N=HWg>`L~(KZh;VB38_Ka`sj?}d-9vWBP=P%D()JG41T&h&NiZHyh4=PLV4Hi221LmI)L6o5yrJkmyuzxtgUH_b9x{1TPJ^ARP_C1Wj+xG7s;SPJOt#5)Pb`nOvle@cN5` z5wq?$nxk*8;{+B`Mxvy#d)qEE6phOSeEJ0R9gmc%SJ=K_9=2`MhSlK0vY?J&N_Ts2 zwOA7z=dkf^p`Iz@tK%GmANe#GGzFRSpyHo|`-j~MGqQ;gYweG~O!mOL%K{`D^3;)oUrW(!5Yk~%_XFPX!7=4cCQ{?j7hMBSQ7_5YJJIACcxU?C;+MN=oKIM z)i1#?4vfi0rVdu`USF6uHhaBzE5v=ya6Pbjn&O=B_ZLo2QCh*S1b~UZ8f2?gTO9eu z)~FSbzUX!xV!Ei_4&5bACOl($=w`h9&bpdymT0dU53?6rhDG6)xr%F!_7ULvl9Mg%yheX6# z2OImgRj!oEiyW3E->@~$i7h#A64x__3#KrIooPQ%Li3RK|fO3Q=YvkQ)f-*tBPuoGbR?#uyy zYBI0`N||q1E?E3(_0)C9SU9&?g~bkQ;Hz^ZlEjRS$(P%VBAm}QCf^(3a$M=pBeTQ} ziRVk}oEU0>-HysWfS}n_Jd9>Mw-aq~aX@ZCq6cnzynu~GPi$i2_9i?j%RlrynF-=| znTd_0NYZn@X-BkHF1yl0B#89%h#G_LRPT&1-^aVp8E3~SI{{eI-ss)wE5;sK@_m&H zv!f2E8{(7SO6!R~P$R3>pr#VRoxM}MMCoxGkzz~tmv_c@#$p)y3%OpkE*>0?&^RW_ zmQVygw}3TrURrrc_G$U*eLQJSRAc}*WJT1idJAsrk|Sq`9U#*UL2rAyLswLoaQp$m zthSK|P|B!#MHP$jb83#_R?gNm?7ck9mL3~BFb1}b?pi(-*rq{ZV}6vZ!r;xvxI zTz}SULLUXnfWwAs(Fgu4X2)BxF6H&lp$*<`XPTY6bi zj1@eUv;ACCczd99ZqEwoS(%jJod@yR=D~WA~Z!nV$j6HW5RgI`;K>5Dj z=()m|3oCMsybb7@4U{CC1W-E= z*u~a;aPN?-Tjd$@fGou%ShyX}c>vwpc9EkOFgLwE65GR@#fJOrk~&Ow#z-hI6f3ht(v{$~GcuH`5XhMp2_wLE2Fx6h=;8onkC$IQ${R}8Sv2_LsyB@X12b* z0OH}#PAgl2Gmh*d`wineY2ESIejubbhz-90PZ=+===rpHgIkpOC{ZUY+Pq!r;>mar zQR`*B%Ya?q-h8KQ_+G${Rt~$+Z8)6gt`rlfdHY!>R4@hNIqK2tA+e6ye8Y|1dkr>= zkxaUC3P;Z5k@pf~TfZ&~DtkVic!W=;BtDZOrxS5Maffik@Xq{!JkE1XIYU;7+eiwF`;dA=lg+m0z;t46FEwUy6W<1KNhxRdtQtgLX3KD#%eW}{=X zh77`v%m`xijikQ%5?{b(C{ovJgHlNA6=sf zHxr|gEyW9p_N&Bn@8i98LpI#^BQ2|i%(^|c5xs6yp5o)K=-h?4re#tNKWz$QhPE1m z-A~x}V5goLwyt7ld9kTU$(n7`h0h>Q?j~j#rbw2qX`yrm)OvC+I$>`UAQ9Okk2@`k zQGP^Iyys2d%Lto1fEEwWYK|7+*6O@l39^C>GrGX!-o!^KXvJV{U*{=RQgiHLL zo^~Ua>2x#;{b6MbwDp8XIp&Q(WMm+t8Hw+8yVD7qk(9lN1b3Yg+d=)T{#l!Yqxdb~ zt6zH|yD4z)D0ehKUQbLxfQmJj5dMq3e9nis$Q(2Yq5&Q)DW7n-ui2|8hzti=$*$j7 zMk5j&blew1l;jL6)<^lQDrv&Z9Bq`i#*Vxz0LKH53QYKD?=Dl~x3@H)R>933c6`VP=xNHSLNZglR{F}d@c5nB^i)~#jY(m=B;aG>?yyz7{+0x_MyMxvKD0(ymSQNc zgyQgCJnwV(b2SJ0!Z+|qjVWB;Q}1gT;rlCjj!~lT(zk<1`?evR`mU1^=tZ!H%VD^* zq}F)N?1WgyxMpWJAq>pJ^P|}3y+AtVxOTGqW35j*Xpoe@ty|C@!Dm1w@hC<$Q8Re1 zrR71z);5sf69steS?34DtF>z-4Ep3qk=nIGVl-@E+RULN_RFfwnkQWXu^(J!OmoaN zNc;3BZ27V%JsZV|bG((GSF@el`M5d;!5y-dKtN@G)5p4lps;(wW47*NW`I2qtLjxb zc8*&{==)7;#ol#yPI4cf2)T+Y=noi_>#FrEIquK6?Ei$H+C)i}|MU{$&xl_23=VP>{Vh)Kf+@U_G z08D0MQ`qCCWZ^0PxTAPmPwac*LHgKZvG7SlNz5C)LuzF&Y4_!Ka9HkMvj5HY1q!KK z+Us{NL?3M<{p%|W$5Kqs+kd|1^w;Tz0O8E{UYXLmS43~Z2w55No}8d}s#L&9c>%U< zR@w-Au-#gGYwWM&EH&!;+Xg>b|K-YVgL2GY*_c%_jdb~&du|ip%~NCv{&vtiI5T+1 zQ?fGDs?bGJlVx2Qpz=E^vpJ-!+`zS(B;=9A-c+^gE|%9Z7X}h*u*H zXO{(2^1aZ+3xc)P0!=x@03~P@Z)B!AHv~!8w|FZnF%>Di{8%0Ll;`QZ)s=G?D&hkJ%~*hwHM6t&^U#aH#x9=8#+AT7iEP{?>x;S$AdKngQ2awD8t|J$ zCZN#t@=4gg*7)ax|1o`J6o8DV^2|SegNo!4u=XRK9NYjC2X8pj^HBml9DIV%pQU=t zn|L3g^7PxsKOg5W;y#+i$P9?}&1Tas;jD7Juv93>U#Qd<{QBv#pQQNLn{+4upzRpz z`=yq7%&hFd+U%D#aKq(eUhxH?e47Wk7?wC-KTafMm z?aya-WODRQ0Zm>&r&$;YR-0jrMEBc8^Z#Qvn@G&mHJ+lpiR|-O>Tep(gnUm_LHYcLT?1U)KCCVHOHs zYkvDqmb~%M!Dq(fy%0c~cGn`Qd2wW*PR@FgtZm0P*09D#E)P?8cZu+-LcPjw-!`oC zB)zwOM=u-L-}ocIxfu*bt?^nwR*#HgTxvMZ;`6HB8x4z7O?R7!hg01`QT5x0#Dl4> zHHkm@;lH+>SP684vgCCJ5HoNp+5;yUgc$Fcx6LE4BD)ipJ@9iSik{M!EVnR}!GMZ8 zuk$rek)?e62zT0!Zn?2`P=Vnsu~^CZ?V+2O&*5zDuSJX)37F=M(BWK`(=D@}`Yg`u zdBdE#R|cP6;?F~d4%!nLr&A3nkw|G75s$6@D`c$)_^2n(ZESK-lg}+IJkOV1Y>!Ce z(k%soLikCFOCJNhep7fLbDt{z7O}oQH8rBhPG8LvYS{nvl@{!{?&P}Lgjsh;RH0|2 zed}INP9{x3IRk@&Qgf4&n>?zT9lm_NU8#zrO@D97=)8BC4Bzbw`AH>0#5DJw)oUqb z&+tov@2uBfixiIqx_y1ff|78Y9*-b?E`!$eD?4F6X#%>&3lQjS)h$Qnyo)%P{Ojzb zJiN=4)D5z!ulNmoLxOd4#z+4rYf}Z~#JN)O=(vfnHoemv* z@~K~G$#FD!pyH^FI%Z@SSG#Wj{m^#VCl^BvxJ-V^)%^!Nb_9CQ=%Pt>3;L^Ik zPdKrN)IIpM_Z$Z%f3uu4p!4#{qQ=9273&B6`Q?EQFeOeeKKurPUxpEoDCh&uqAxe} z*XESp7Z(9M^E@7N)G^}w*-AuK0FEP5mrd??R)r&Cr=$MR6Ea8NC;fdr+`sS~HT|f= z)IR=k@%f|1q>}+p|1_hN(IO!AG`rMme_Z^_QD-di<<>vEBcLCBfRj=fe<=6I#S>ov zB09(O@z2=!A29#5a{mQS{{tqjsvIY-{~KV|)e$pt(r2wq&Cgp9YuWNIx*M`iNE%MS(N&me3A`u6z1O2`5VKs43h6(*m-n5E ztXOAGZ20or0q0KASUPxu$^rhk7yfGHh-y&S%tB%gXZW(l9c z#0G%8Y{#_r1V*JrFuJd=%VkKlify{)!MuF+-^6;@YIz z=VRKLy(cbQ4qXaqsBRVAN!9@vBhce0PnM^jz|9F7uHe5v^5x4*-}*=o6|R5$6wy7# z_{>X)=rBHp<*MnneV3^h%LXQb`{HAX1vo9c{}}f~a{{83-ES{XN%`_w!0E!NP7wR| z9+2g=Q$JHTA@m0X0`3`YytPV|z9`O=%rzA96d z%L{k;r{1r|B)e{H~9SJZ%ZMh?08p|D#{Y8oEDzBTdXvfJTX~`v73R7?=Ga= z{udGDlv;(J+9SZBoZK3Eqa<=jzj}@Ncb4;_ZkytA3NY(UVAd#CqE)-f<@emTKx1XX zfi@$twI^WE?<}!Dc%IQZ;U%izNk8g>a4!9i;oOErjQC_(vi-;gAR~2*%cA-)#D23t-?$FV~gdBk+He=wXxw`Gr<_FKC|HlGJZc79*+GHaI=r~ zi#^e6sP*8?!{lTr-kTtx>R4HeDJZ3?}$5BK#pspk$(F z#5yb3;z)ZzS(kNi`k-PdznfpscH)*BslyM_f;0Z7_wXj<{&M@IH19=e6M@$p`Bk^3 z0|IOe)*s;gw;%l2uXiiqTc-KM@uiRb5wk|GKPbi^!nx=hc!ZPn{$xlC3J9akq%LO@ zGdJ#4Y%TQ))?#vVitQR&K5G>HLt}od^V>sR3jW>X`vrH>2dTKftL0VM9W<9%qQm8A zKK?mS<<#>|D(orjbG=wk!n=2;-0R@^U^=>MPkO)&xJgW^*&6@nd_c(QNA&gYt?G$^ zJ^9&-EGMpnH|lo`|MHi*&lfD*2<}?B(cZO5-yDF&htPYj zCzU*zX1PN`iWVyz{AK)a$WKg`Qm`m+-4Wl$B=An(L2&e&NwFeUE7vBRw)$%yrpGy3 z0oPW9Y{yE3xu^~Fa>$hd`8ypQsQJ_EK2 zWMXAEf%G2GBUUZIC9>Q?xtK(hDrH)%MTgAFzX$^D`wON-)O^b+lGZ78lG7=*k<+Po zDs-0HK#$-Wr`0#@KO34|-J?sywg8!J3LpkrP|yLyGxTxTH{5AtUh55(JxQ{(lJq7j zv$H!o4q|anJgJpMHw*3}w9Vt9;`d_B)9?Ee&<4-%4VAY^Y!EVCw#vQduz=yqS!kkfo2`9(O^Opp`^V zJ-qBwBJ(G8-_>Azd3GRAKW0_0m_;8lzO~Sno%b*zr{;DpvY@6^nb-Ud#odDWuXls9 z?_Dfe1&L>4ay5!Mb-o3L^^lnAU<{%po_thl>!q78Hz>aQ>f_u!BUP&o4^_ifwkCH> z{GhR@SqrOyDrdgTyP=zi_FI9QBY4&`)8?G2HKhWFeC$CWZRRiJ8T+f2DUUTaKw&5b zDAMSD+y+eXQMWEC9^oi$(^pDkY9iV;5HVz-V>M?Xp@_D^tT76-IaX|glD5~bCM*Ox zR%_&Iqz~BGJ^hG~7+hcbv~YRoC$sb)pcY6GUWwqK;cz^oT1zhs&$Y`gZw?z1s0<6y z>D3j0_3t+>_W3IWZT`m!m;7td_gPpE&41psB-W- zf4qDEQa8JVUO2FGc4NA8fHXjmC!YTmRK|sJG5ieWtx^;j$k>gIj^Iio)FciR*nENw z;lEXQ-^7jYMw7F;^9P-9E=00a4%L=1HHT8~hM7%CX!l-=MNXp(XIPca%LIaE2%RGQ z)55jfI3N4yW^DuU;OQOnlyB#o)`~YYM?PtRMh#U(U~wFmumXP4_Vj~?{()oQYlAv@ zxig(INivg6^zFXodBI6oqHOXZL>1LStBg{k`t)Vx||{nG>eq5L5&?SuLz z#fk>Geb*$H0tI(7F4@LtaeV<-XX+qi(r?Zn$0A;5&;`=G^i#{G(h}Tlfz$;Z zpRC{$S++_dHK>pZom7)bI=(bjk1O{@odpxA<1E>Q!}{49RL0PLRj&PHOP_9s3brB3 zg@uwHwDK`tSTilxS}Ew$wE|lk3PfZECmJE$N&|HdMrgKL-Q=s#rpk^`_MU#u!wi8a7(#z>@ zll0#x)Yq^kV7~oOS;6wD_SG+U7!!g`A4yd!Ow$G;-Ly=>~|huP1` zg&l_bn=x~Befi!rDx{tac9R}NTYKH}fa*Z^_1JCf}Efu+?R`A&|H2e6u%{udr!kYj&jD z_JVEOgaHjyJhF^o)LLwO!6k1SW|Q8DnrIHXZ566$le}MAG?x+e4jap2>)P94d)7?} zZ7%q6xIZ327o}zrhSJbTe*{%y#g=CG1^0V0z)IC>sV}B3o}vg=;cN(uF$*j%3-2k? zmbVd4U3_B&TCwiq7_b|F4kQ%la}Q+PZhffkGGm~m20mBxDPkbi@^Wqz-%z}w$7q&l z`gHdD#dOL*#{Q(H0ln3%5^BD+vFIb6VgqcBe+wx;f zsrGy@1+&w+_+eSKdLxqq}A| zsycfJp@yAXIw7?)0ynrnR*uS03?Iu?=3TsjL`rowY}9Lu85-SGM|_fw!<>l|6jNK83wzVxi}sJ7hQ%7!{!ckzVUCY8RMe$Fln>yf8_Xe&0I?B|@Ni|Sl67DbkD75P!}?p%<| zozsg=`Jf$2$3B6UGa!4|vSXP%T;yPz`k;V3GO6ynrH*9GM(g9-142E1Xf80fjC=L7 zs-_N-tnuSQ#t%ybYxt(E5ew;#!Irg+o!Nh-r|%2FiSu&ba>!&E{3kuTr2mkwYuVjM77d$Cv`ShXQiTI zrIy{JU}LV_4z@Lq{)ZPbKlHHD)A(Bj8?hqVwBe#;r8Y?h$zuU&i*lyA)3yo<)ZN(u z>Cr-gTbBXy7{qL@&|=Fjk{sCTV!o@WlwB=6lwi4~xvI1Wj!`p7w#R>rbxGiBR<1EF z4p)m^#;=4Ojj%T?^GGcM}9BX$<)ga^UFm+Z*?Cp&RMlY zmptikW=lO-;Opk*Gu!1h1sNhWA~gc9F3qL1?FSfvb>c$kCh`I|rpb(B#9`zuYb zT>Fxs%IC48Sx6l)80KMpJJ4%xLZi_y^*Batc913B)=xwa8aEVo6kCUFY4dZY%sZ;ikj;Mw;!w5D}On>19f z_qL7Zb|PU z9Nz%7`zW!BQ3O2rX+h1leP&F~rN}1BAj8zLHwzsxOp_d0d!TE<6#;h?xnbs!T$H+9 zUL7;SFufYA+SREVUzQ&j+Wc@>-BEhN>e@w)t*uGDs>9B$2OPDH63K{~Wkz<*D;d{e zL`;uP-=^xmJ2DIGzNj6wu@(A`y8MA-{xmeLYM`&~yNtEVwD71!xmv-65t+bK!(l8e z-)3Hi;{zIzYL$B+V{ChU%>%`Z%@>y??d!@XkzrMS-K;o3E3Pugo;BwK`4&?+tte>M z+pIlu`=Xb2zH5H|fK^lXsZ-P110)JeUr-&b)Lg;ot#jHE_Dj~PtX=!NwOK)d7n?TT z=?kkT+obd_ee0i+wJk<*vz)$|?~s`nVcEZ9JEPgI^Lx1fV83-X1nxWTPXlu7IZTKe zYz$Mq7HtUnS4>a9Dv$X{wIlCiC93w6a{a?V9-Gp1<#6I!E=dWk|p6miw?#x zeQ$HafF%6$z2N7U!I)L8uigd>-@ct2^@WaSew}qSc-i&=ZN6Lyn}0YTZKiu)LFBn5 zP-2=Eog`rY41kGZID_d=k=1@hrd?H>J3Q&u*FNXdV^I((N8klL_*RH^oV z{9GyM+dp=K6e%E6I6QQ6CKG~(&>zB%xPu^*@oYTxq@WAMwumqcKxaqf~$sc|bfkec5y=%U_49FN~u_hsu)(Tji%U|BklzHM}}M8s4Z} zi1Gn0`@YAr1l8J!=X5|*2vj0^ZGA(0XP))1jmCX|Oqg3mmybwf)P zP^|f7Pv6i=oN6!w-T&*g$s>AU60)>I=Ozi~&QZh9=>XKh7=al7Z-cPtaEOhR{a<~o zGRWdkSar!Q0?A^D;p&+NBVXDf>k%`j_R3ii4J-f|X+vt)$Gk@A2IaM32~{2?VxRJ` zxz)2HYDnyRnB*lQHaW~v;Q^Z1Mq!&(t4bkLZT-l=!MJEmOv-2w(H>qm%cx>a>|tpH zwDH$RYTkCh-4K^K{3-@wr!X@mlV%QSRq{mq5ZduCy`0)6ATn8dXP&m+#{lyg?K@gBz$ds9y%BS zgY*D3_Ac?^R#fPq2et9GQcx=K;b=m_B+wlFI6x^5<%+sNx!=$pVTaBH=JR?wFd1oo zDpY;_^Xi5Ck$)gqF6~!5vS(2xiWVkx_{ZQ+BeFTzm60w-MFC`eUqjb^{I<7Qf$j~g z91K4ASOjkP>|lOXm>+w&1;}vOO2SIqL_M!eTg5*;LEaKc9@y@ z&=NMuh1;0TWvm}sh5Sq8hS(86JVXFV%pb^UXuHZvN20H%Xj*AKsuRVK!%#-~9M+Rh zOFv~&V_a<K++@f8UtHZUVv{T>Lo#vjnD({!>2Rqiuc3a$;Am)Dq&0HnE)6SgLzY6(%V#1VI{m<_LBeYwnBW8cYM=+B z3P)U_dat1G6i}HdcfwI*V1xQ`8Ks*f?YV zL}>#A<$a~z%Vbntl}syd)s8EG6b}Jiz(ytG3V9&C8oerio|{&+Ms}55`LxP$ z*^F|nnsAk$Y?nb$39AI93Z~!DQE61O9p=QkNtU^ z*_OHK**{I;+CXiaYPo8aYC-J_ZQu2b_33ql^)Ktm>myD4t}Mi|#4QRf(@xp%eB7== zu`EP=M17?7CgNM+m6Sp!F^dmNhvz9L%jes(?^Tj3NV603I^`>6Pa>o%txK`Xxivk? zpHY5SQq}P}laCd1nJnD|=dk~xCH zeF?!~4r6=cz#D>ntYPMpbr%}JOnn9W;-_@HG?+{&xt6r1Oyo4}^x;gL^yN$;mclgF z$@$6UwC1#jbi&NA%o(;?&K_&gmYdS}Tzmt3cA_bl*M)BGMyjByQ#1CM@KoF_D`~J7TrZvdL~! zNLE-GQ5k`a$>wjd{A+E_Z{B?;alFCAk?N58gNc#JKyOQTsK&KM(C)~N&Q9H~6;C_r z+px;8r~9vt+&A5)!pmF%UBO#{M{n?<&m%z;+Txaxe+_F;g?CR|A*%8AQ z!@asA2Mz%$AJ^x1_(*s|abv1*6UmwwA9Pb}PR27S4pzSJf7o8NCezZiSdWb?>s5{1 zhq`0$B6UdInYa1$F+mA=DJ-n{G`oNT|GkRA>6^ll84`awX<_NO#Uwcy1*z?vO=0q% z{p$#NSb8)#ik-Y;Rw{i(NQn=$=88gGKWq`r#{<8L$rz2-Br#`6DR7nwCueK_3t3ag z6-R?xA5Uu!K_BLi?;m#@wN2`lTc`S`l?&c%K5XM`USAkQLv~!v9F9sR(X`^V_#0pw zu^P{vlblqXP?0!8wECCJB~+10+`|8g4;4&Xk}NDMoMVOkZat=GPjt$>ZQ6KR(6&`8bY;{_bZQs-I=dL~bP5Nd!W22neRPKWXm-Ax^?`YN{ zFQfC+5mVL%C$q)&^h?r<)}24I6N9$;y`AXZucMGqq+>>(TiIFW=AnwAy*-^s0bE<{ zC}tc6I|DYiu~%x4j0ZKYEV1l_Ob^2$Q`hr(n!$uWv2IFBm2dm`Z8Uv2eK5UU&AnE; zbMkOSzq%qYtkzBwV4&J?w6#uW&78!WYO5`&MXR-{b2B&?Yo`YtNOAA zz8YisYh7UL?wJHA+BFlIJK65FQ>*UfF(r=?WhrIJR3}2`u2pCwrS4+WJ_=;ja&FJO z_2C-kAbC8UmR-$h$I01&?8aF8!jrd3`NbD+|R}{2NpLe>te_mM8Db(4R3C`j5=equT>OAR8JMEnw~6x_#N!Gef!@N;Lgy-NeBe0J_e3rUlmrSjbp*2&4Mw$ zK351&V-uzAiajojJ`%pb$IWL?`Bv4Zxt!h{dS;r=6E8Y1-dP=R>2R)kZIuBrc;czH zrTfNLuXd;w4#ePF`Q$djf9%fquKbP$I_@NWR=QQb+Mia8Qal!-_45;Ac}F^xebLCQ zodSvVY>`gl6Mc0YBwDM5fThn!f$hyChEPg`$m_eqH~j?$)6$27C%*%BgbiQtm4UjD zWkH`;b6wY0M>r7Pt$q8riyE2mB44osc-#YGi1~HHrmY&Bi<{7Qd4D<&t}JG$UEBW# zPrd*)g|2y+#GY|Uz&7r0KyND(RH4FhE0wFCfs^$Utx63lgRMPbdpWA-=PU%j!LK-WB znj+dO+^R>hRCH zFHphgVq_et!x=>x^o>qAcSjeW_PK=VtqpcDu696F{tCMs=NUm-qY>df@xRX_F~sSe zV%IzHNsxit@i*7a23^FV!_J0^I=&X=)rePXt>lXurp(gOh&()e7);19A)j}WwPBkk zLO#1W*8RhwXS4bS#NX-JQa6P`xO)?2+KS(E;_K^s7n(Vj^2Kh{G}Nb`+CDGgd7xqf zDB~!gjQ6pmy#@GiEOMfMSTt)5bsv7c#%UPH zk7}qD0ZAE#$HrLbI!A_w8MjMHUX|)&Zn)w!dUMkUVjjS#RRMbr7({{UArKcMgM;Ec zuCKZ~KKr4MN?Ka@Rvgo^m5heqRc;oGcU5`yf?5mobp6jH7oSjXQ!e^;z^EBLP@T6* z(y-hw^nM8n4P>Vsn7abojz&j^wgjz&oei52*CMT*Wh5xe z$*d4v@Y(k)x!53LS6CPKuLkTf|88|Wk8ya*{g}zGF*YvWc+a5RfoH%B)LI+SwVN;a zZJdbc%3%o$s~udyhLPto48ym}F;E2SFhp*vJ5KGM)UMkmsk?})CE^$$Q(jXAzmE>u zPt51bL^5voDH}gi6)#{XBO#awG4yRiW4_@yOv zH(jZhf(7Jo2(gu4$b0W&YEmQdcH6777G4XJ9>c>U7a#fghWx{zx!)c&?diuy%NNq_ za-m2Oof--j7@*P7G7Qs$FX?CJ=PA)`by3fx{~koM8J;Cjh7>_DzDcpk`Q=A*X(jpH z;R^IHN@ztz5vdGPqNPxtfLHIJxKSNC?Kh*Iloas(88?FEenO~Ey4;U47607oaunAK zLNQm>Mj=Lu%}QAbwB4LB?At@O1jc;RCU^wID2ZMp zv^1D6jcYPv1{efqXP8|-*i=_wUteu?=T=wAwxwR9gk+0-q)3D0?<;lV{0gqH(@n%| zYO3Z@^EHmCW>!bT@x2_P|7cY=h}N8~6A(gAVb4s0Qohejdf>eJwlC00l0C)jXc zw{>)Ed}j-GElA^@s!U`4iq03mP&%`Ek;!Gtq9RZoYOBWlE!t6Iu_RBuN5b?)QfW_p%g zfP|003gGL?WfN!WUCFRV4#LG<)GdoAOeEq+TWTmN?W>Fz%MXJ4znC$V2uS|XGy<-N zyoC`bylAY^8u%OS%z$~H+GsvQsDE)$T>_^z;YAnyfi&?d{wZ@GmCfH;S_XFj@c#^m zCp#g$-@3TCuxrLeYHXz|mzPtn-*P{*XV>Qi0R6H( zVlBc?{e~SL=Tj>N^$O!A1J2ByM4_RQ{j)ntWlLoDA8*^lXXjST@~b_(|H+P0u!xvd zbl5)aHbN660MH!*utM8%ZbdI)z26uuj?G ze#MZfd}3tsy}PxcTj;OXH6XvCoBXfufpVk6j9S0_WDNlD2g{6l<3Y#HWsu=e@=r&9 zIjx_?lR>m_l^anq!(x7}(2d&3#f7?Or|nhWxk)x2BHpH(d{2L%}!ug2Ea7C3X{g_`{|8ef>-TFWf( z^!LsxGnCVi#fERa!>)7tp!;E2hkAqJA&YvPJ+;dDqh<4Sif(fKm6dqd)z)yYT^a$h z3P028`#>9?K0^h~BAGr>0=1YBWh#_$gH!55haVwPCVbZbmJ@v<(iEqbH>?v0($f&k zGf@tUzNF>aLPB7SMNGE^tMqf%zwfZ~FAK&4zy>0R>-Rth=m@%lw!Y_zMNq z+O)hxbX6DHjK*-dm=*=a8od-PNJS{iIIV9775{nAi8!cZ33uTA&j^OI9@ZT#{>A{cz92F%yk|xI5WN~Uanwka>`effS zHItm~S-7E8r|vgft2+!z-)fT+UC)J!{SVZi$TzGrbi{0RjCONElX&r6f9}?#N&^qu z;{YpK!-&6zdkOjJvdbGQ`H@FG3jOnhkx@}X5XJx>bM6gnUoXzi*z|1nOXSTULFz2% zB&lykQ9PxRIFXW}41gTKpC^~6j9sZlDexN5ngaK!aKXjRE#v024%uIlb~rfyzNPcN zD~BX85-fM*oL>X1LBSohX9VU99Y4?0rto*ksv2y7WH2uov@ETxz8?sX(;w@&{lQBs zYa`@xS*6r;C@tq;pU_iJ&iyUS#H$_U)3}8MD=&|d3eI9;!d7)E^ynt(R1{Wnm?%Ew;P0vQJ+ohG*@V{dr z@`M}7t%&g>#u6UJTGBi;kxrv|1gH6NBH6edQ3BnMvycPCkv&W(G(B&Mv4l51BNyCb zueFSu?pJzd#Tt4>mcm7k?RU8S0St?o1O#G@Rj-#FS4<0;ezylR17#-s;PLao!$tQl z9UL`^YXoE!&zQiS_a{)buZ>kd$_l9rn8?~95y*Gr zd6w-qn_&{nUFvO{xPQ9PmX^_ay1!pbII~b5fnR4>PO^tBHlNXxgKhkR%gKA{59mK{ zKQ`c+cwyAxPRr71wPDqbXVg9efQ=7h3C96&k6J?W+K_yNuzp+r90Cv)s)g-*Qp+06 zVP>|-&0!*C%F17?Z8p7$-h4Wz@zD*$*-_o4ho8VKkGOsu69e>KrIAUVYidgi6erHPcB;m9n3QmF%025j!Q$8fasIu=~EarwQA0Mc=!6`-XA1 zFN`Gadpv@D=L_&8@yDBi&r4-~e!dWREElYEikp~k0K9H`3zEQQ7^m}5@MO@Ox(EOga()qBg%r5i14D#LZsFM_aC2v2sUjCh=jW2*4;{S3? znzp^beE!tZvV6V$)ID;*j18K!j!ZT`x{G}8-aKUlb}#vSG6Z|?F@;1Guf_ey3upi1 zNv8p>hnD8|BY1QAV#1iZIjXC$Ny+4xS6!u97LWEc<^!}dxh4*{a`V*~;3<)aXCcqM zMBjT*SIM(#bfQ#cq<7!MTbqe|1yEX#ofSO`w6~R&fzAFe7dw$D&4ykmS(KHopF0(` zj_)xnLmTyEnBk-V(85!ui<;M=gSo|T>lhjf(H^?}@PD5e82HzsjJjQ|8?Fsv68*b* zr^PxsGU_OWEG*4dgTt@j+Nvt9Y;z^qWb%HvhjQj;_FS}5M0{2b4kP@KKtT4X@+cX1 z;e7on5s)^-ePVB(*92U~u$1wg@IZp5eq0jN&l2Ks#6XHcgQXn^zq_@P+J;E5pkiMI zuBVzXaiC6PXy5+x1y@;4go=rnmS)6uCtY1zv&!`ec~yMy`Z`XlfQ=MD3<(XDV$Hj? zvb1DuBClgzxr_LSe$mFjfs6Skw|?M9`&i#M(?VqTf@vF!m;bSl3-GhWA|l4(K%G?= zf%G&52GwJm1t1370cDHr;R19)AK=fsOHwP5m&h+!G4w%~c?RHKEPWMFO;4pXV(G;u zui00u%#JxD?n}f`9a7F-ty(h>yzqqJB(9za@sG&U+`G7sJ zifv;_5Xl`hUH;+w`%n~3ELVJnDE=cjP*R@{Ki$NTx{~3%m~t*uE%JHfdRJyXlku~B zC5V&AP`W=GoMO$s5N_JeplY=Li+RE+cojXB(r%9-b#tMuXdlbZ>|-BheDd6p1~7hQQPYY7BoyytCyTmG`E6fg&7tDMgzqu^5b$~Q zzja<+C;Zp@=b|p)e28e@En>ZsDt#+SKxCp*uoU{BG4H(QCC^(^(~GSCi@fuO)5%V^ zQZXcUx4qUGc*3CjXUZWQ+F$nUeQSfyl=xfsEm!NZ)GxpwSUJr>;g>se6Hk3Czc;Md zarGRhymwo%V%_txCoB2B&x-hCYBsnO9WLwBCRiiFrdBlQsTKXi;#8><%8?jr5q12_ zwtbpA3`7iU=%=TrN9(vH-0d?#Gbivht>QYwtsb{-!miv|+jJwa#JY}%rZC^&V zQo5zufjiz8_nkao*_MhYYSuW~=ufC~cmA8^g0@5TB|p~)Yy{@~zK(^$WIO0zz{ z>sh~3Et|OC9hEWH|3I(ahWifa^X>EJ>pUfze=jon$KTJ78QAw+@C|M$u(=`OhV*ln zpWHcZa_H|<5`>LS#lf|teg}}=~uH}#3*`zB^7uBlstDaAi>I6$P z_f5Z!`?6gJ>eKp+GPMsz=nr#I_(_>I<`c`FF$_%zD2^zb;0gq;DRJOftNOATtFsjq z;ZmAtTkAMfw^g7}HBMX+Xzzcc{Xbhvjeh+SjhQ#;gdkgH$EY>DhuA@zXbW0!Ft) zyplc&wa%gc_O~c0j*{a5qm=tW-&w~WK4#1w6%&s`(>tI5l2#5;`eFZ`?n}G?G6(*m zp)No`H|+k1FObr6(EPils(FQVQK=>Rggvi36*4l7&_R5zwWcu!t_dHgu^sU(MwTSp z6E+`jLr%^jE{n>@BTg~1NST7S+RKEpNxAyl$=|=gEHB{8D5BzkzU5D?SVeCZfZgqJ z-#_!P%mvkm52ZlpLyZ+=O&D_TB$;`+>jaZxb?xpc_pd_xOiv}m-)!8KFe|ELkBYUJ zNxYe3DHlS2qWfd~9rDt6U;*Kw%a{U0kNAGSi1Ituo5ti_&_yBhuwrIVKAO);OQNwA z^R)c)xX^!-f75gOQF_#9t@@**p`|AH2UrbJ!$r(bk~6}dFWN+MrYyDg6}FfdP)xI? zbsDxCc#4}q2Wv7d%{)PGp!`7+f8BDc@Mk`4Zx=t@L(0kpuDg*fuFH}|7Z1;9h(sT+ z#4-A2#!dY5B-s%957woTLuzzPP>qxlCdGT>yav@k+4VG)DPKM*lf@6JTCzkGR;rr^ zY?pEjb{4Xj^uBAOFNG|WBs4@Uw`7_^)MzWaYjq#T&eW$@rr|1;z&2xG7=)l|IPRR9W)W(>l|^Iv}h!nm9=OHFWaA{XUQih zU<;p7{62lC(Rf17p;h>uU za8DZvr^+b5nDsmHK8|!ioD;6MF(LDe+y?e38tz+;mGPIz!+2RJ5m852J%D?F)V{%1 zxV7NSQ*{IUNPl^`R%VrS&BaE`YH)Ar=WVU6lG{Zy9K$xQJ`Y2JHyM$jpBVJOpnav5 zkMB{Up|NCGiZ-n`AMs|-3T!e%G-|#`2IXHO$ONL7dYhi}7#-w9^ITb<7Len{ltcmO z{c=OTTRxMIYUC#m_>8bcW#>5}vE|oJY|nK^1B7)m_2M(o_wfanvkcX2X~;yp&}Xht z((6B_^$-bRLY%KlKe)`?kaKq^0U_4)Ify~oW$=Ea(LXvg&Ej#H1aGe!VbSlWnfOi- zV;qo0%2O_Aa?oPy0wRBCq$s>$RDqAH+i%Dr8B!moXU22PAzX&>SHQWX$h$KY zNj`b)-O!p+v0&=+gMno!vKeRs;Jl0ayEfoF##NXQxbD8&?UZHVz&~k};ch0E-PdYi z81*8yNqQJ<0Sl7l?8FC8d~x&#>M%kZt++paLf{uBtDQlkov#`Jcm!pLtFV=%FDI02 z!+7vRw;ZGMAJ6evhIQ^_y0iLx=wScb7iK9%s}+;}Hm$+WwcK~w1-L8Ur|gvNx+qbl z#FT_>o0nLpH%C91EQefD${xxeFl1Z!IO=PEtQeJ-16-&lX-d<6#E$=m8X+ZrhL8s= zjn^>*UuVOYk3s~a1yXjC=o}8r`OwWXSF^n6WmN_TR7fcRm4dxcpa?lEjN+0tGbh+= zysAu|@@DD+EmaKxDhzX`(6ur&g>3IYLp$w;MIL4ywwmWT!KI%uf(dF}wzi z1${7fl_X^fx_kqoDtz&k^xN1kkTlEIYnY?LdpI89ZUgp-)~ zc2Ni?=PuJNCuw`A_RU}yk{ncqQV`#vNm8{|jA`Zi3*L7KWjE$6E1IpY*NencvoCy3 z$_97N*w$nqmX(2}Yweb_@Ma$j&$BBeEa4aSKRoAuuuhc`%;d_RqMsQdQ}@d-hH7uU zzS(RbJ+hCs|4pplOiE>g*1}>&{Ri?cr=>Ao)n)7rrOuC-~}hs;_KdB>(5Na_hM9HtpS< z#$zVDwP~g3W03DLgfWi;no#C>+d%eN3 z5M@|`1HF3L8BNfkc1Y*1N~rf5xVf^DKb_^9`1mSo=8~C>lQDZm@hTSbCa1+dJ6{#` z?kh|1imhrOiq6YdI2J-9XBOfY7ILmK$g4Ppd$I@XW&%ub+zOX}a@9egKr}KnllAvz zVI?+0WunGheyEsUZ2*MI`-Qs#zGv_TBe?Zyt!se>q>wFSeX({unkLV7*<;q)UZiP_ z=i#@E2Gtg9x!uUTXunN>>U(x)cIx-H1C+3lbTixJtXKwW<2AWQ)g?G_jr86Q`9y>? z=&_89+T(1my*nE&ao9=BoolYnx4jBfqC3B=0-hw(=h^=(3Q+FLb0MJFD)eiL<6uQy zZ843kW;n>g_RHk5Tw|)~P>_HLPJdb*`tczuyyY8x zFLdhIMw{e>^F0|J)M_z5m|E7zFgYBCvdWr*$P<|@F zPtn+wEMVq=MvJ?itw6DR=tYQ!$EZe;Y=ODjnIh*0Nu#o*7>-gYMBA#p#kVbSc~QHfyu+Woeu4b>Uh2K^`XkvZsh4{)yqlK4L<1YT$jul?!YV z^0fo+z)z*fRO+`n!AOR{$ND>4+JhE+oL_ph&~hsD=<0fosOKiiB7r?2cwn5IM7hFChCx zcB)QB1V#vG8(MC1|DVY`hlG60`B|(ek$6No?jV76v>=qe0u7Zj(i|J`VC`g|px(1m z=ZLlCum{ki#r~t8@0aFn)Vm~S>n&MERGzw#I$Z9(e(Lnfqf5ERloncyG+(Z?l|6$+MPQ%rNnIE zZSG=>lrPD)=pQu}{ZqJ~RzoFdD)k5L6#+(I8B}CGQ$TeJZ5cCxD`-V}&;K!n9Y;v~ zYBBE^Xaz`BftnY4HRX9$vGA&6}prT8-T=;`+b#@kg6b@0Cx z)BdQ!DRD2ttsZf~M&H>Ibu=sg)?K;=k6`M1)B%Ihc9qd3;k4~EA>ZJDj{;Y_Wly#3 z-g7r2@rZ&FHTu*NE)`!)LKJ8OL-0dF`1OPmXwdzys%i|>_NEtF9XT{;oUUr9(>2cn z76!7Iym5cLZZvSs!`|F7BhGbuU!hViIKK5mT+inF-mYz9eTY89_O0W7lHDlBe0iFD zjr=0`F~RKi6x{QXNt$kd7lZnur~WSN-Mx^4@Bepzl*OG<@qJH&t9)@ZKqpa-czrMu zrLX&T$vzmPJ$tRm5^KMDmiqH9?s4OAph@p(Ql}_&gSR zM_??hK{L1i+aMid4}NInP$F5Hzl3e{xH_>ws+J*L5!7_@{Lh9pM?;9O*JN*0zxy5^ zSW?#ItZZYQxICa}qfk;f&eRa|S*b^jN}>IeJrM}mr)BG!WM6F3W-_HMGY8k76++u@$4m3tnMt}7vmQ^=n^@w%UX*A`!tNY zQe0=KAm-)#>m9Kt!m@n6rH_xBJmP>_k`yO32CF4xo|lkEH06)3L~- zGmuiO;{Enk1^XR6gX17;!@bMBSw*f(kwVx3`;L*FJpf-*PSdRPt zL4i7LwJuKNXy#ZCsN8c2u~|**4n3|b8ez-zgQI8NhK99|zI9zMLVGv84-z1Z(j0OP zzpe#pXJLh-t&wkCbnMXx(xA=8Uo*~hgl>wE>#!64r3Pv`B^QFunj@^7oeMF{&2Ear z$tJ9<4=413)L~1J>l)8C8Y#Z8r59bm3ezBvZSp?-kGeubuJf;BjXv?<)N#pQR<}vK z#moJvMH3K6wI+ppU5a{LL=+0~+pM{v`1-}K586g++yTI<*;9_>s z=|&1>VVc`NGLr9<`j7FVq=4KVfKGoJPCp^(3A8qOcs)!Fjrkc-38=n7B+&<2J1{)i z$K1RWp9h^grxpuOE273m+-+$b~&@%eoy3B=5?FoCvZ z`jjv?G<v948Mdb-H*W$7-;&CIun;K(bfwyJNcL~bhKME1 z^||+Rw6U2eZv`xJ!sRj{s%DtdYlKVfyu*_f0(bOT5f^3t|dcWl`C`P(6-v39|_*TkWvk$O8JDN_%?B*(ku(1V3_3%S8WiSWg;RMvAgx;5`d_ z*?wcNRuXfwR+-AL=vhqOOLj7<6EXAowCUd340srK*Kmk` zW?aPLR?&pPan&N=R|8-6EIwDhPVji8M2az)s39_44b3S>?(2o(cmE4E8jA+`-K%6F z1pLopX5XPG-WGe=`&Rb#L?|cHtr3P#YQ@;_XCu$F;MHc|4%6(2M8EdCx5&?1>V-(W z{cEBZ+t&M{<8r%A?@z&e=ZMp(lut`4u#M1vg)$oXr|%X;Z!fkJZt54UDRdk-DG4Z( z@8k&qE(Ak?YvN)=9!59nM0G-xBFI>KJE@|yr^fM-M!dX%$pp}Iu!Ii7F3-{E2-Ksd zVo}_~xI@2FmXUv_i(U{)F;tCkw)e_02D*^b+DarhS>7Y{tf6S^qIoF7(}QPJXjpr~ z`*}^1Y-+e_(vJqs314=&g_5v};Ge#RY5LuGF|35sj|-CT;W}nV`0J7@5pf^W1Ranl z!Hs$b!KaQ@bWR;4F6Y%?rGW$FetO~?n)wLGh98DGiKN9c#Johj=psENaoZeuoBTXc zgrvzFI?m9_bW(f&0@%b<%I)ir(FBOx#7u_DR>5J6XfoY+SK-zR4W7rF|Mq(@;z#cp zxdjXl1>-6D&~#s^UI8EjG!-col)Ildt%Ou!T6p7Ws_NWMQw?mZ*1s9UZq`o)IfOk| zCj6Sll+7@bdKL1$-mPh6Y_evT-tOSzvRDj0)9$zAOudmw$bO`$^dqbEQkhb=We&n; z=+ya@I!Ia?2SbW9TUVymt?lvKjF< zZv@s_tu#2U3wN=@NZp4lyRI|9y2Gq1h|OP_n7nM8fu@AZrz!I7aF3s{?xyk*dP~Y+ zs>*%?TwMzi2jBL`n^#eBLFdQ+(Rv~Dop;68x1z29xk8la*VR{%KIc>TujF|jzACS< z?_d=%g+VukDYvo_-sCfQ&i#0LSC2IDr}y9!c}@GmLR#{hiR}{X zpo`bMu>9Eku)Itbk_I;sZuaewYT0Clne#Ji+b?9|++K=Z$X_+%r80a*)QSIKRi5!k z)*2ZfakZm1)rYL(h|!s7@vc(&A_^5tS6<>3Mn_u~dX58(<@QFlkc|CDueip3cT2r3 z&20-&b3b7U*Z9xgITQvV;cb3xP-z9SB_~PV1gTClJSGZy$0c!a+5Bbsm5crB#D*}5 zq{gP#a_kfz^TV7DUU!^=i5k{_7(=rVUc@ek7gQX|9UOMqqle;{EtPI%E%gQmJNfHR zBO$0zlvuoj;7CS`Zb8~KYUl8!@%T>^i+L~VOS7wLhbubAxC_O*?|QV(Q+*@n&ClW~ zU(E(~P5=Gs{fxdPSkm>ZDA?3cTyEx3sCM`6%8?w>#9CH@>*`EyP00ZoV~%b4=!PoQ zfyl})T*w06y9J!rgPdi3PmMFgEnqcu;OKg*Xk*(&zG;p1Nc~{3Duj+xd z&hh~VF`(4g-Ep&teBimuEU@N#X5<#M3@uiRjdECJgYl_gA_Z=TH_Fqv6{9)UhoIm) z&ebv_p{qf|Ul7G2DJ2hwp^;M$xMV3+u%lIHjd;D)*{T8d$8NzH2F?{U^!mNRVYBfD zjch6#H5xkRVtS)_hkA`?`!|aQkRuAZ^k$l!z^@JM>e7uCyH1muki8I}ZdsZ@IQ!0qXCCr{x~-LLL7XzE!Yw5FMUrI z|E%srT{!k-)Ds!)JQ7au!k2 z1Z`tM&_;52gM=fDKJ{gyT!1x}@lzZv}C75*!g# zib=}FrKk{lT+=Xj;JQ)h@IQ`Q!sMT39Mhg!KLJ2%%^Fa`Rs;D}t+tW`vh`u2H1sW8 z-&hf}r!jhrH@brypVBwW8*}iI|Lw%Eqrk}Y@tJnCu5mwfD<%v>4!HuI#`Rz}Ix#4K zOO?tm97|VA$!`akEz1B)2N&+;CVVUe-owG#Ny0u=RY-w@H)Ldw^q}cU?4cqF*W=UH zSySS)6sLPaM#ec%(aY1Vzisu2yjM2V+Gd~(5gr{iuU=lDgNS647c_H!d)EK;){EZw znVjFuOJ2}UEYKe79-K^^M4CvkIl`Z_6|mYD^GdF*R$6c0A}Q!l@A(-wIBN=@_X<+_&j*aND&RcbxD7fiQq#W)%<1 zBSGVZA{#?j>x2}Gr)UI5hpU6d$xg_#=J9Gr)bo0mx_HV8+cV~eqhp>x!c-7V(~C+j z7sVN81F`UC+{LCMKmT_hE*u8=x|)1}f6MIOkFC$6XAw_hG!FNdqUbAz^}*B$G-KuL zondY9gTy+J6`q%4!795Ciyn3O2-ppj_yOPoaGqcr@-ctBk)6 z9963p;zwK8x#i-MZIM@*!|tuAb@dGg?*Gp8z%20oKHN{aRws&cx|uuY8?2H!ysr8R z&>7?jzM(co9xiMr5`cOUmF(p38_qt7i&8xsGIu!8e_x?pdmF}N1P3P4rN9luR?)!M z>6=pojD?||=Kkw5R|}M@Ti7G*MgH3-K^dd+66^T?w>*ruD9FaSZdNH^7CkEFhWhav z?lhRY%?6h_J1}!~g#FG|Bv!jV1>Lm=Uhf;jqNz6O$Zw|jDE3ey_Y+H*SMz*7Ir;xS zjrhM>Q$E^t(cK989VDxA4S20oudJ2$IVsmHYh-$q&6ynAz&@e}j%*9r7U|V89JCjg zi=wo|NXF!{L7nw>6E6q!csw&UPHto9i%b{G0S?=h`C*^Rz2VD7MI508@}|xVH$MQcDl(?9jEb0 z*}~Hn%%mjHMXzl0*d3e(J%J1pAu%e7piNu&$cJo8w26!IYwpRws8NF+$1dhkF>)6)8j^<9NXV~So*$qZMV57?iD#KFS8ZYpY;F(#RrbP$@sCN zV|}j)hk`6+k8O{KaKl(m{@-vW944=o_Exb_7|R_k_KR$jJ{}+DJu=&%r)|@bLa!dO znK!RPLfx5qQPP{P+gFS(;WdYeXt?M!;exlau&eGvucgAD^o$-e_J90(B8J~a%yQy7 zia?dv7>f~h?VN@Q7Ck=nfbbb?vJ?={ZOl^Q4Fb)iLo{WB)@jy?S^i=*EXIc%84%2d-B#?l$J)#mR#X4mi_sXvpOycJLl+}p2BuI zB{Om%QjrhFt05(;Cl4ZEd_3vcPP-%tFv5N_Ym+dC0nI`1i(_k|g|Q&PA;DdPTW}5T z?(P!Y-GaNjCrE<3yF0<%2M7>sa2vi!PIB&hzI%W1G(FQjUA0U0s;bq<20sdGvZ*^^ z`U*jgldk2>i%$GG;tmhd?%hE8@#?1^7G^=`JHD{HFw}IoZL!8MosFZS&5nS*9@cF4 zc-H-n;5Q|F9>g|P(CcL{;-l1OCs*zpZ>2xgw~8&PgvyR>Y)?SA`pf^MkQM^%%O(xrHu!aP-6Eur^Woey6X*(XR1sTWTFn zhD6S%ag2R#U}KDawMKYw9<|c)D-&O&nxxX3ORR{^>P|5BPMKVr9x3^qk?nr>SKr9r z3QwRDY4@FZ{ekgt4V1n&uH5j+NAca{B1Tg)^7)VVTve&7m;!3GRAI!;E07&N#RRh} zpq-+qsg;`it0C(mV>(d9UHe>zZq$X7D0Mc|n@!@goa1kIS%+DyKZmVt7H7zA1@Xo{ zmrzMjxes`ov=f|U+R^^{&fUhhM?~y{R{MQt(6bYG%icwR*;PA<9-!#Ef3Fc!Z*ykJ z;*J!b*=)-Vn$#k1vgfN_q>pbJcIPa70$ID^eY`tjt<^JS+zzOu_Uo#rmj>l@z1%Um zzWwA8moR$gSF+u1e&$A=#CF6$`l-zfLB`U`?mcXTb#q>KqOYduQ5{peo#|$eZ`-(W zrvVIu9qk4ms8MU3-{Zx$k-n^@U}Sjp%aA-C?s?}eMduGvyhqA7^dV`B%YBr4hcwp` zAer}VwfB(v<1=>c+<|tOgJt5iMGZS+>V}~A{;Rq-Lq)Gd4a$6$jj!DuUKq*iaueb_ z=tB?+Tf7gj$g4>gNI7fP26oZ|R->})xkwPNv>9SPHckc|qoqw3iGT4a6I0H0@&Xlc z+79%DMDcf*#)eHO)E0={$EsHqwz)Ua_k~9^vuE88rDfX{B<$W?P$Yzga*aS0^usT8kV6!l19rX_noU z_F>&a43Xv3nifG}!uwS6HZSS|gdo849XI`K1q!d{JnwPfN>nTuHJ`EokN9I=&Iw;& zHq?D>5|K`h9O{<)OP!wQR1|YjlBYU5R?7*r(0jbYw@F8-Ra_~Tw) zoY(Wdj=j$F5Y+l`bFb+nT@`U%3f3Y~yja9huWn$Y#p8lpY87}lR1?t-$w0i9^J8uU zW<(mX16%vLM&>%BwZVW+H~#Qy8S#b)h1Q>^rh}BslS?DB?4C2rBfGDb@MWbhv$_}g zP2f$1TBl(Y^}V_?NYCwW0ra04u7(JR)Dx!X0ss07$@S2fg1yY=?Z!u9BsJt6q*R<* zb5e#cd@*$wgt=OfSf?`MqnZ9l8mu~vHY|Omgsbj2n~Dsl1AU`n-3YfSIvkA4YQiKn z@%^9Qs7TcmGuOY?%n%;^@LhQ0!`ghfPsn-i%nVf1C651_=CBwH1Wjra+fn-`BvPbr za7J*4<_oKCRX%QURx0ATX=e3ybG|_6sh^a@dc>FrQEI%0BEVIjBC?RVzJb>idKB^T z_`O7*8AffbFwPAaIQd347j0}2ipk2TZAj*fxO0{|~P@lt%_7OcD$da?~quV>BKs-}K2 zZs-12%$oM7{#unjB~9_fB&Y2pNm!b^Y;c$Hy;$_u`%0mG4TS&l;f zy`=JTl5aS>52Yn+7sd2`t33PS z;maH>hUPQ}Sgp}wr)UT@SMe|})O1I)*&-pp;+=VF-h=x#I)P)ul)C0H<2#yIea&A2fR_IXpV2*Ua^iQ*vDgJd6;K089@mg zyF?2Dppqq^?Pkl<;EZ_R_>^ePovw8*hxhVm|0q(PdZgqu%PJqIJ8v7|X^n!-%RCmJak>Eu$ zDcKDw(b_}DDDr)TTfDYp)bOP|0q2#Sg6O5MfPH)vE$stFT_h9N-2z7o5o4Nm*DooL zF^eahe5*QH<6aq3s7V?U{9FTRnOOl9Z^9_$~I_oXZ z#n!f;%w&@|t4mVmBV>?IqXG{WMEJp<9;SG8Mn}i$!Spq4u0ecWXZVs<+H!p0^`vWPeZ=#%gxe6N*kW_h|r;RU8 zHgbTcPXN^?F(A6em*%7CzLfp^3;o)KD=JbGxG_y`Vcq>@JycL&Rbr`a8@VD{sco1R zMxCzSdJn$8?LYbEuNpuRDKqJ9wY?yS|6ZdCg?IB2q}XL8v-I2}VVg87eKN8CE2^tg zK?(HgX6)@K>w(+E21pBQ0>*Kba_+3d!e!u%w9?0n3B+TNRhNgM-7%j~0*iy-1+=t| z-NV@{MIs$z+u)!U6T531h?p*dCfUehNwQqgrqjUH`){Ok6B-SY{n^8duWhqG2nm$u zl9D8#lc9{cmb;83-RGyauSs+(V;eh&77{IVv)|>*D&-mZcn3< z)f^SKu0QwLT^(Y46D9!#D4e*PMCku>-&)V}fHO-Lf-+~(=mgd6i3UcVRQaNO;x#mV zI`x20qP@>z5Gp?NryjWY;QsXYJO0O^Vn=As#pmF)a4`=Gi+tQ?^(PNP+Z@77K#=~Xwn6@y=k9l%~N*n zN{4zR#N4tYj7YzksgZ)vqws|~TNw{%Z!RqWZGG`&Et$t|%nRBuC^C7Q5f*uo&U0XT z6xEU=tv)JipkiyhivWr&#M0!+$)+Ff!x_#XC#2kvbiid0a_xDMaYOw#kpnLg2C{&$w9JJYMY^$@%zdmT z8-u8jpPt$(@Z+OyAAX|m7-m7*WcGxUh~Y4>ky6jVBNZc{#Rf|{tfajGQ8028lRN2R z(33H~x{Cp%i(9$odN7R=_x+ zir@5cZzZ8lwBgG#8xtNRJUC3XX<)6dNpwWJx^TFVXmi?Fvgb`O5&4aIG)!d8^+c-r zExJC6_Qr%-M91Nd0|UQ4$+g>c|2Fg% zLZDvs8PLMOYu!hC)AjgTyg6pnE0uM<#^g(ph8oG8c~V36VvmuEgf)&G4zh&8+%m-w zs^0@0`DAtBK@RauxuEEQ_gTk8d7DBmk3T{uM-2&8!lN_$hmNmb>Rx<+ zakC7Ppn_s`LhLmiVFF<0LE#Y)ushx4u2wA;it7mju`<73D=X~MA~OTldxbMnV99Cg zuu;3L_T~liC(K-J!)~+#wy4e-iMYMAEi%p@vZxau*!axP_Cir?aVXMc>mg-}pP!aB zRO1HOxBG&lS3-)tycHzz7v&yrPT~1izTcd6USbwu_fiYqC|b^UBF;Mz_Mu$2x!X0k zZD}yIbFiZe-Tz!|=%ea}l?b(+-9Q8m#AYuNFPU8T!7w~+^U%?!S9|Zp>@HxbS(`zN z3Ov8-VxrhmKkEPHO!jkcNFSIafo8-SAZKT{rwo&uZfF=PZ0)}8`ejMz|-^ki~N z$McQFG|L_I?;b{QdleF-S4|;x8xL-rS3nDFGQ3iloJ=P05Hi9M;ZyKM}TCxPo` zb1xf%?h+am2t6EefNxnK1}8??cwIzK+YKpc8ibsxsBmzNi0QlT3^;f_L(n zw7D5&8zqD18>%VeUVOYk#8^tUPyC|rLxf}>RCXyWO*VGpNXJ`q?%3K7e3-b(lC-8Z z6Mlk5F%{iv2GUyOJh5UesBl6rV35l94)Mq#Vnk?Dc?T?I{&!-=xRs_ccrl=1w zCHm3FNjng-r;wytN1T(joKUanl6@+<1OTKAK9^tG_RZX;c*U~^@^;=QxK}LB?mP`T zJM`Hix`ud7^7atHWq;wi%j_cODUrLFi(F*CQs>UbgQ$+U}Iq>85P!3b|&ba2#El8>UPI^5Mf zGfhIrPUDyUDUEB4S}}f-Mz)#?DG_Gy;2CY{Tw@9DZ9S1w}uZe0XW;SC{RMNu`M-(6JH%qZLz52xuhU$m66|6%?qzx#l7M9Z0I47i2g*tn6Yh)`EPQe0_Z;s7#iyXnSUpGQ zuMQ!>kdh%cYR@Dq17kb7`!)P&6rJ~1nPBCqiRidT$+Tm~&xt&8D>WPAK8ww1Q`+Sv zfHqa%=w>B9&j#pVO}}Yy!0$~!y9myw+_(d=au4udJWHQiq{y(I(^PU6axycUUa(JZ zyh(W(cMDjN=8=WTpX>7cS*W$fX-O8)Xmndyk(SUOJ_>_*D7!RT(avEoFo0HRkmx1r zE!^&=wD<+pGnX8^c>-Eb9XEdFn2vu}Z!%qkWS0gnd-cX_s8a8c*!1*-xSnc=3M)bE z>~zmw?l9RS%z*z%`-f8AWtlb#S5^&h zNwYtF<9|Tnk(Am^VtK%Q^_Qi>1V(*@yXhwI4_A79nk*nBd=*rmBPGZ))CWrXr*FKw zRU`o9sTc|-z-!4KL{|>@h)73p$ePZfyj_NIoer^^8s?& z;GlR^(}z$FtF2EyTTV}R2$-%@x$9}$iF0wHRpw-*6)p#T=F0a(XJ-vHa>dG(CLz?R zCqKpZekZm9P<7hPRX)>t!V>xI@cn@;T1{ir??qolr=qvLiZT!9hI*~y7%nqiir7z# z^*Y!X7#Yih(Q>g&6E!ZgF)nL~L8D4w%y$8jB$#Zf%`X5cbCVLmzeD#SaZ^eU$G%@8 zU`=crI5dcH1|mU93JJVX_o>AsgZyZ4HB=7VP3ui~>VKNN8v%}Nkq3v{xBHuW zI_4aZ1rnWQc}900?Iu{j7v<8uHIQ{L*pnsjG4@+f=6}@`PJF=fW|u?fe!zRzk%Mpd zkzh=)(uS4@4IR#^_H&U~rKWU9#z{bK^{Ph+e7iHu@C_HP1$HFp-NQF8UVXJzeXMl> zSM4X=_Vl;h9r5vtTd_g}bPObkTGb{yOjs!?T+n3aR%vy*S#stdCSE7>Y?Ee5)=apt zU-X!+M~?rHhW1MtVN*kP>2-hFJFO#fz%fzEy)q4WEU6_;q{JEl6vqV!HzM9Z_F+t<;Oz2jg9!_NG8~`Vub7P z=+{P6G!*i*@^7xGf+siD({%Fnl>*E2!$>PzTfN4Q+=V)eYF0KIY|FIN3-wTEN8Kps zO?Xq(+lk`H742Y19ybLT5UD8Z#pphbCu#-XX%o+}q<3H-x>Ko4jsVNrN;rMa9^+QU zTXdRiQ&;oxDuh0=uy&d*f7`^JAI0X7<#+oTyzYKL*c7_3uYjz~7m6AswsysP_SFjwLzgtMN zKhN?VCbHoS(aS)}Fiy`n(%ue}dGYQh7+)~7C3T1(v~^tACzFjj(>d~75%o?c#|W~* zJYfMXbq}3c5s!gcit2QmOZYF)_Bt{pcpRVDO%S*#Zds*Dav3ii*)KI{ZGnRx_zfTQ zj0K^!8dhH&i3|6t*n_+CS?>EH{t`u8heN2JNafeX+qShvnX(wqWKsC1q2ew=OPla- zN}tXsFg$&v`Ru!`@R;*kkh-zmJ_TTDAvlV6 z=wf1}4!^#`)Nl}0GAFOvIr9V0E`SM_&{k8NP)Sl5jUE*AzlHG1u~rt6EN%K+TK+gA zhOcUWXiYf0zOFl4{veaPILZlIv)T}bVEX7=7Jzk&|!x}bWk|3DAXHvFXW1TFbkN|xmcOyNQUeXr;6GQ8N6d1Sy@^2q!;Nv>(p6PQ>j>@{8J59 zL24W;#tPxhqlS$ZPY*}p-QkJ7#I{moy?U4&+8sr8illY!9;knp=P@Sa50_T>a98?O zEsC(*9?xw-1HRw1V83}`gux&sWzRn9Z^oWq|B3CM7Y-PSwB>DFjx5$|bH__)MO$P> zDx|AZ+h?@ykS)}&VAV!A6#lx}&%Gu^G$v+St5;NpcD5qQ$>M5&kl2d!$1cWV10G<) zuOs<#U=E%#1hk10buYU9oQv)LjPB6uI~{-jcNYLY;lK{&p&59KR8ZW%udboOq2Rqo zqL?oqEg=OW$)aDq7QyOVhfhr*uafyQ0SumZ|Bfu%5*v{t{vjCGAWef=Vd9@+hv7W= zR`6pflkn6(^f&+Bb`73_(eyKQMCVNPgHR%Q(rq>3=Rjf($NF zC_szF_5E}FcRogp9IfK*uA>;@aql0A(bGX~aMIJQ<);4*u+~J7Zm~eHg0*0ll(OUg zT0>b>K+}*0w!gwJ3XuP^iT`_9Pc*PJJRNRSD>0zt&vhxc__cl`(&i*vCl^RUPi6lE z@BiP!WQum{jh2rX>vd%qlk>0DW?HM`HpWHAhDAooel4rWSn=?C{=CcmJOAA}BIy<; zU)dcQF&$8vk)PG4_G_q$Rn0w;7S0!T?Mb_=D#UQq`t!?X#32~I=D#i?Y#2KDBck44 zzcA!&cvPJWOfl>c&$sW@dXuIYA?C_$QwP@)izM!U7Zp7*)O4+{@&t2`tTwnY32~yP zX>?2ji;l6#6hw(0U2_nM7iY|1Np zcy_OC)Qaxy@^FYzxqXRoM&Zg2O3UiRTY1m?1{}O$eyeso0_<$!PfT{X(NFHB>rrSB==0ChH~dQ`$UK(CRVD=vO=PFBYjqSZHshq>=Kn%NA6&VnAUmFf8Mz#nyJK+9haaVU9~ zTQStOT5c@UN-bgH%>#{PgtqQX@* zpWB$(sRhC}>8I>p$=KFS`7qjhdVKsXiGMBo&(YW?@GZum>Zoh8;c-&*?~>-x^Lmof zRU-oq^8PN)JrR;+UUDtZ_h!qLjmw#bdzgJH+TY+k#5BKA?mGQh=Y_FCjwKpCxn9CV z1%FaWHF2=>DAR?=^?867`i9>_PDn*A<1Tp{iKo}_GQ#q#$}j#$%VTKygrV98{`Hnj z1QivXKOwuSH_*O*kA&;}>hnBATf4!0{>1Z3_+Z09g>h&~GjlllQ@1pn_+`qOOgqHN`1A(A1*m{XyvX1RGgZ~a1 zG_-Ym+L8F@IsQ`z0NaXT3>g?_m=sSMF#1U2aWO#0m6x4eUqVNlSk$k9rZyrm_O@$R z8N+Thz5Xt({#eFwEs8&m1LmT6>EPM#k7(#5x>vVCj5HaaDU04TrU#hPAbI@pF|v zsr>s?etusp85I?g02k_<_q||(MiNj@k5N=*QPIfnohU95Q3hEWY0B}@N0ou1rlw6% zTg$I(Ep&7;Sks^DlE(Is(mt`V_ z1@>O=CGw8yFoKza=CXctQWhWnk5V;pppYI$-zpkVQDZ*S*{Ydqqo&K+2Iw&o@ag|m zy`dQy1PxIOZ0unrDt!}Cyo2Nq7N=v{i`m^*7`ortOG`0yxfHC`_#MTbqb`?)pD2ke z+NP?0FEj|KI*e1i#6t@_B3rjqeHp8-v!Q#JBLPmaH{+*zKl3Q;c9>8LP)T#&pSqA7 zx&;8(M+q-$mY$|u{ka`Wf~0v$3WIWFP+tB-w_j01njDRKaI651!b^{UYS6@r8_WAG zKM5&9qDMj((#IL&0pQ~w$McJ!Q;3n%2*}!)8}+28T?{lbCcAmLXs%B;7YIR#cYwOU z-cg8Sig-|p=C@@uHzwOIF@CBe%0MI4IW)6fD17?mCp6c8@pKHqMw{>{(3K%|vu5;L zXtuzb>;aL9Yb1g3esnsFEi`RTI|4B>57(3xUI!Qdx*|HlK&K2%4K1|%iFZB<|S^(#X$%)U{{I@Zbz0A1l+*@>~QJj-5lm0 z)%>!|kK!a>v}O}kvK(nt2$;o$*(=5eaYyTYnx>NJTFs@}wzCm59-1lG%B;o+FKDn& z(bF`uis7zU_72H!Z%|{GLIxkMe6|!ywk-ZS&F)cQ5)DlR4vt*S%K1fgYelbn!}p9< zjEmj1PhLWw)hDT6njN+#eT)u$^lhH^EX&JTU9A2F@<6%|-GiecDWH@_jg39gGp}iA ztSFOy$|HHOse72W`7=JlgNz+K=7=g%Q9WmJqt4P9kh^}dvmPV<$_dBT1CpaG;|4Ss zdwEVm`A6~N_7c5$KrS35F&6_S{Y5bDX!aRASX1W?r_euXET8)SNg@n$$eD?ie2dPL zWnMBDpxZUNW>|p-f8z}kR3%(8<73JvL~Z$}_03 z@I#57C{Wf&B{5>nREoGUDsDRO-!w>_5h_W0`Ry&QR*Q10>HqU$8j;{2rV*Jh*hK*| zUNN4SdlmLq^#A&yKdIEee>5|GB@(P-X6uqES>tV}x2`HHxk|r{d4UruMC8WA!<%Xv=!lRp~Dk^TyfwDMEY|Cja( zLm*5a6TS=y`@aZz?49EqxwxnTyo8%Y2EmRx#QU_B|2;c!$T1J>zdB|k;+KG&3Z=#2%N8=~dgCANSXfRwsIAhLm zPVxXJs)Mbq{E@|(H5*_8nG<=J9imzy{tRbU&id!fM+t_mB(N*8zvX;CcbM*xJWf*) zwcbHWJ$6ECgeFV{U_)SJS7T4Lle0xuoXDsg;ZHzJ!mx2N?gdmXI4jOXm^B00S@2JznV2CgIETw9NUN5C5#DrA00Bk ze@~yNTIi}~wp8a`A~}0uD9tw9iO*(o3Q*R zGukr4v4dpNeZ<=53i2V55a4A&7%_Z9LxYi}C?>pDYiFnaJrPRW%N>I6STNN*DgAm& zE{$f-R7UvAzlqCl?@&$kYnLa7Rc7&ru;jN*1YXBL_#B%GSWq}=Sh)W{uZe!eojMl( zMbi{@SWZ%XVHjFOgp{1_to36;jj{5O5#XA4VGQPHL5+E6;ejLxR=W32PhuA0a;eSN z?`Ln{HoujkUywpMO?hIXnetQM$h5>-8Ps z8S{=He$pkX9_(D2#q{!e6g~)v;wT6(b3=OCaIIN|zh%hckoFjPXVmk#KY|U1d95P$#<{( z>Njf8Y0PE&U#GUf02SZLU;FXwjpq}S;9bJ@dCQb9ZGA)IFfAV@EL>P0m|ctvDLnc4 zUZpG9%t@sAGFB&sS->Cksigon86Q1dXKiwBPBqNBa@pFHJ7G_3*m#|fl@)J;&q?-H zE|ieW#d=S^sG~!!&}oByfwZ~?Z%Qhc&0-S2$N$I5vm0_6$KV>Rz>eq9p+P7jcB}AN zx1y!ZXfUW#U|pl=lFHcx>O<^+049vq{p-9a2jY3yJf@DjQlS4d`~}Jgj1`fHcz?B) z$=J@*W!_7&sa?Zno7p|+zyK5)ej?ipdI$;~dL;+3^{H63HEHzr{JSO2PvRNcPegS# zg1$%fa!5WeHN?1(&n*i6Gdp4Buwiz4K~J5|5B2cpkq!;>9)JK-UlHJuj1#$yW% z;+1hSc2w+>IlT6wk6;F1ip90Q^mZypaRa}e;hTaX;-rC=wf%P$qsaKe*FDw~GyKL% zNAP}3oeoQ*7e-o*oa`Lh%ZZx_(?)cSp*|fI1b5wVn-+E!ei!4;>KX#)-|cm;-(nU4 z0gM0jDXDOQE$s7q2|X%~|Kr?$8H=(Q1S=jVb^H!y?f#&4Yexl*%@51B2)Z;-zRd5V zL{G3sR%ci72hAq-A{ciaFW z`Ex_XH2pD?{+sQ}5Ji zYe2N~3k6)jC8l;!J_2mQ{b=!aLd9Hv$Wek}U8}j@`u)!THo$`SZ0ls;klD)MHP!sT z_G675$b#M`5lhTDwyR^`ISp?YepVj7*gmXWUa@)G&A+d{_wxL(8KF5DtOIBx_BUM3C%F}20qb|1`zg9ZKeheY88 z$?||`-@^<%CjdS#BB=Du`3|;D(pdY=iOcohL;(Id3H!)EI=`ErT5@PeA%whcx-XIspHh}lnfpWyA_J)e4R$Kq%=>z_=a-1vIRZr)~90?a;T`$~y_r!ocFuydRe|sMlvA*BEn)4zn#q#m{f*S9s z%5N#KX%>YJVhcZ)L#ZZ|Eo%YAS+-;(Uwo`!yJr*~C-9xp&<JquK%BsVt(Z{cyx+WvHz>2*Z>dXgxouVFpn@@`|ng= zaM4H8sYD`oMhgp+vh+tIJ#F47YpJi0#ZXgGiIt+Hi@Bx@A85Dme8aj&PKZ%(dCH7K zii@-)PKZiE6mK@Eh$-R-b}rJ*xw=J8r{uu51L{Ocdif2lBc-m~B@LZ%s{@83UM>p~ zjL3KIH%P1nB2K0w0B+D}a0TdU=wRa=XmFlbmvT0 zIW=1}es~W)T`^I>5|M6d)|#xN@{9jQP%Im5-($r{1@812_NccNX45 z$v0OW?p%-mANUsxfXSnyp+`m~IijyMTlBzr3x`s9bVsS1mx(2+M?Dd;?`XuO+n@V- z--dswgumTzwy?BLvUeVsX5gfLxtB3uANxrNBo!d*eVSj~WR_2{fJ4CClr<{|Wz2Up&L5bZ zaMg965XO)jk_?FFIQ97%CO93M7i2WFP*Knlg3L!}n!`^75)(Mi0-TyR0S53MCl)tY zfsb8J_lx5@M7O+#!Bck}T1EC7jZ#3<@e}0!JKeyDkdi#l1rEIR4r>d`kCsR!@_8&# z&(Lr;89M32&w!Ed%bwHK{bu8rK?VlOWsRnDS=iYf#$Pc28UFSP8 z(ma@;Yihw_pe4)kON(jECIIT|(N;k`c8x*9S-xIrybcbP9+0-|9*S$ux)#ddDcN;i zvdDCY9Gi88FJ+V4f-Lkcnoau3#)927+{?p%XbHhv5vE_jf#w|=PBfb0yICa1S*lff z+KF&P#}qnHMiBB4B_!WYuTV+=d-5MF?{{s204m-+cqtAGvp*{8+tvEsLY#Us5eX%S zwxx-hz8a1HhLTVZ=7^o7U3oDbEwK0&ug4~JU27E$Q-l6~B^!O{j(BJf5x|bMqWLKa z_SE2`=y_u!2fmU4rSjtFq@)&lQ{)#VQ+p8+J)9I`#~De{kueL;TB)yEL&q(z;f)ej zxm#R%!g#TM#P9wX9{^6#8>uq;^pInB?!l3+x!WWS_@|;|aB#@p>O=rDmMH*4y6jhhEwZl)>d&%V=e(G_&3zaDR6&%{-Zc>k35uuN?;Z|} zP68+b=Z#?=g5E>>LXrZRtd1ob!=iR9C{z9s{ESdO#WsrP$`{Hy0;N-{x$`|7{3bfN zba}wlVI9`QU<|(8wtQKSg%$0EySuy26S!Ht@vchMJQof%wO8B;mrq+eQ)OW9=kg`h zM;#pwg>qo^egEe_kC2Ed%&3#yJi2Gq^W@o?DXJu{_D-ypUU{@sJq5kSHw z9Zcqg5hIz>sAY8WtCq?E3lWg&;&}3euhz?0mBmDG< zKANZUv~_sl8Xxi(LkA-t95(sg4?82zztVqS=5p2)7^D$|-}AGrewdWH($f+?#udn3 zy|tk*W!snEFHv|VyOK)dY4)!|A8pR+QSOij4NfOaN!o|n#EM3f(cqHsq@!_pU8VE; zKiZxp7I`Kbz(0XsP$9oV&9w6Kvb*3pbx80bXe!g+GrO2XtB8tZ7#oHazlD*4ndM@* z@2t-2dJFm%Kh^*=W{=0+DR+%bhUb48gQsG%^xbaHq3?PzV>Js^;7UL1>r#zx*|zUl zhx<}+5BOac#`rU=U>v8Y`DQyOy%t_O+%SF*KmO!Ej`mvQ(S=kWc<6s+bg zT1JK$!sj13?($h4ZEm&-$Z19Ui+SK`3HU8(LOcvVKi9;+^wA_`eoGP?VqJuOKUl_+ ztZ@q5?Zjho&-fPtO!)-iCB&_k4m`r8do>`60=pA`9KUGuBO>o6ihq4YgbkY(_;x?2 zLk83z24HGe6IdV}p{p;T%?f6{%l!^PjA*-q`vww~#Xuu&puT+Bm1&XGtfn#aM{e>S z+hV!{cq7Vg0$10cDjg~3T3;sr^`@V*nTWOPP^8v$=otwHG4=eK4C5=jZAb*7&zHD3 zxurr_tK`?o44wm@h@yPyCoYswxjzI{2Q>E#@!@w0Yi_~9d9oyT(>_Z>d5Yb9Ec&1e zpr-4(KzqjCi-q$c-7BNO?wmBb>7lP8v`Mml`)aH=dQ^l_hXSedw5L-V6V=s~o$6A! zd^PIQ$nq_7-Q^DP0T&!LurC;6;Vxc{d{m|A=^@TKC19H&$`^=GY={V{Dzp5HWDA@i zM!-{e3EekG&zHjGn;cz~y#7UBz?_97TBND*xtb=kX`ihN(ZjRMX7D*EF2G$srlK5FUP3Y9 z=DpJ2p}+e!jvBXqz#3X@sI8I!+^2OtA(Jak*DZmZ^8J_89sM3=U!?J~b_7h7Q@2IT z8=~hy2EM!YF|sG^4%5K9+}n1YN_FkN9^VKBpwBSP2I#!P{yFLJ1Gcw!bm8-fg3lcM zUiAftqYE*xPofX1al9@-_@JDWS7Mbgc#4NR7CSpJKWkXfzcd4gEQ2l4y zefA%X^99$OZ%@R1x(+(M_w3uJ?Wl93dIKI~iTsCRHT%Bw72ysuUFUzRp?Lzss`v>f z>)ZBS*Lrn0PdP6)CepN+pndz!3N@IZ?G}SB<5LaTP&nk5&6f^^4DSqZej8kRnX|pv z<+q{R;PZq@jHtt5|6Z9_P751D<4gIIRu6NzR08-t2K+9rZlTx)KFgyGB3O^Iu}}M9 z0_n2v-l${JQ|NaM{lfMFGvL2#G<|$Q>a8b=k0nF9hPc5XE&K-8??x;D;TzChXr@it zQ#A6qk2deh{8%R~kxJ7>)mvT?Gp%TNXX+Oaz4F0Oy_cUO-U?%Mpt`8R=Ns4L&ZSfT zR6aIeBwW|P!N4KYbvuC*_Ly?z-60Hu;~?JzO0^~^#YceVm5FYUrf^Dm_6%@y1ZD~V z2$s8Ykk9FJVmN7SO002R{++9762osf^BpQ!9N}B-b**_psCNga)Op0d( z=WggvlLXal^tuhKw7b;F?XyKCZS-FzY^fm?1936j4U55)?<9(F`WzSf%hC} zAPKZNFs;!0hJSG!tDlSp13c7^4>~T?3JeU9^rkQ2rtX&$cHCZ4W%dfRS*C}|m$xEh zivKB_Y4|~}%v!Sqb5r#@w?T&GQoB{q={FXGAJZWyJS*x63wL-2xw`V9IJNnlW1vq2 zDvob+n5l#qbx)F|)1ES1Z(%6BgK~E53CqrqGx@$xi4!Df&<|de=+mX~VREmbQ3-2U znSChYpm=4mv#VdeC9#L$sGE8(8(MfcSo6;NGFLekK>V{zEp3njlNDGH-Cd=XglD+* zd+QKLCz1~a>a{CuB3gKs{SNjDDsFDIvtOf{o9XC(V5d^^?xR5ryX`xS= zea8%e@}TLgO?Xrio%_>(RgtH@UCS8Zi*U72XwSA%TS}mR%Tc$msnjJAY&BCCuvE-* z7kP0RfC{OdL&1;o5AqVoN+R?Urh_W{Oi#Bwx~`DM z3kvBS++cl|ujz>i#FH%HeBbo01SDjGI?}|m6gOIdBa&axy7nZhUHG`-&+ z6vOS+Lxx;rL_3u&jQ2Az$lDW?;tUqJ@1%U0ked*{x;+Lco-m$ zcKt5vE^UD4o-k~D!S{|oPW-*@&=BA42Rlsg8&Rv*7s-yjsBolT%@C^!GJC{j zT_^xBHaiLt7eDC``8=SE=J9)QMsZPZZ4$Y&mcJuWr6Jy0p)d0Y_;GxOm;+pVBnJJQ zV(@>NeK{X8_tm6y;$;YemGMCL?~a*=1h7$yz>m_=<$<>F8I-Wmb2fi9WgMeHvXg&Y zOLD7Hwk0|Nj5nrnq@b<3JtpqtISu7~{+cGL7BIlv1_(>;91lV45(9mbau}t$si2`e zoBm~%c%oaSEN**8LdLi$yr6XXl_94wz0si~=yVbRgU~x{r5gWl`2xE}JTVBvq z4mPKt+aDY6f5K-Ywh-Xz-9-p9)!D6~n37DEO?cBpwY+X>|FcrRw9R@mpto})3UU0> zdx~FZp#t$uYWq8g>)cY&{fRw(>b!BjG3VUN+|R07*-hnQ46^q}qDGxO^lR{+jy&s; zl&o0pS8{mWQ%ujS^^2p&%>^6Bo2*dA zp{n6Unvd;1Ebn^v%?~QjefGztXcn9@*?qZM*!U8k2K?_^k!gmyj=l$eSmw5kIb*qJ z63cPB9zeF^bbeGEG{vBXgYKHny-ib5r5bH4iAQ_hL~3&M9Cj0tAPIVq$ZMgV)E zuE;0s_efqo#>&WTuM&1B@pJjT-07{7;=u95Z&^!PT>Ny!;ZPnqq&RR=(Q-~x_G>7x zR5vkBi9uyn#Z3Ufb8~*VOkcF{72f5BrM_M2sHM$ageM)R;`8>LNukX9g>G-EZBQw9Nrd#KI#_^(0#) zBU|7aRQ9REL%C!3R&+;D9gVrXbZcQ}@Lj-XQIxxJd+co@J;u4*CgX9=-*NTd@*_c@ z-Y-VbwjV|w%B;dd(Y%;xF)?w}FZ-KM5#guzfPp;kjpRK+pF=a1?3W#lPSe+yS)6vu z7gh>q`e!ogG4NkI$3-q!71v$Y_@ybKVPUdwc z{N=^a6fR4gy&WoV6vXwHDgT>U)jHWVLp#6sTJ8S>88l-DzUz%5oV_Jle_&ecL_b1! z(`e^9h*_WZ9Jy10GBdL|uvwdvzFB6>6k0lyOwUpC zrL#S^GLsn{1@m&*btgmj6|{BhPknfN#!g1)^mGkI(_TFiR9c!=iS%XguB;|8`GLfE z?cKZ<-dy=V5rf9V&kXKYG!iQ(V+$o1Erw$i@&wE%?(?38UJC1@GwAT~;x#IVvH1kH znGEU%0S(7ZiO@mNBUR74{^?sy&;BohAcd9!8tRuH#2{rSLrX=>h7hR%c>=-A@nPSI zXexAT4f6V?Ch9{~A2~7rm__Bk1=GJr-5X*M+na5~x(mY(_kf3q)qQa+Ba)-*$ym1w z^oo%>g*^6|#EAX_K<$mUpjV&W-I#%gJl_XvDo)ghmzc9o<3TP=Npd6F)QTZX1{n4Ot{s0j6pwS7k#eT0WUa2&zgpSO)?Tn%V$=TLFb z?z;)x z-0?!43R^MspP&0(vym`ExC5ceOUhLA1|~)bBHgEfrtnv(7pUyqA%q+}E4+ow_VUtE zd!|ano662&LjWM97ONAnH^bN2xAs~Yh=`+}Z>|`Q5+<$ut9<$rsb+*w*)N!euP2fv zua#R&FW&BnG-{1{orhM5D?XZM4jeG)fBY|5Fd(H46cd9x_pHQ{R!?5S89q{B0}5^)&UJY^Lt zs5&W==^p2OawvXWQoe(C!-`5=pcxZqA<@kU$pm|dmNMs{7|iv}hcC=MpnAdC z_xptkbAm%@vQI5+`}BZ?WviqqiitaZct0^6D986wf>Z ze0>avuiAHg&wbH%oWrN~a_{<~8IM}h#@=2EL1JAz+_k5X9KRvs9CEM8oTQ{)n+dd3Qd}cVOX{*GY=IX}iAH4(I=i zyZh&!@of(Q^Cx?O%G;zYmAdQpsGS7PC(ea-X>0b&FBdANQMfFYPU@*0|GT6iY8=bPT& z1;^xPWLP=B`FiEcZ{B4nY7*k$eAQ1SjE;3Fc}6U_TMn7!KVFR3v3>$HbeoxTHGvUe zr`6pchS(6lhC>8{znQ2ED7MKD3xnq!RFew-9?;{q+K;p)!i%5(aFX5i`?~8HlL7n8 zXtXhi8|~rOT?57^3RUd~0SerTqx3=G=-1202s!L#uag5LI3@enyQFY*;Y5ZxxDL2_ zTOWJ+t#eJR8{|yIuCVq7-5#?8(l#r{k|wLoT04bG5ZpjlUhehk-sF zuw3{@G-pm;#dUgTw#Eg0v^3hV?v#ClK&adBO%7ToUbUWEyL4nE#tf?S^V78umn{oW z-$^PE_;FFz20cJR5(5={5g0c*q{Wag>Z2C8^P;v_zHDg+{&!B_9g0{+wL#q`oCmY zC!&xWC|FyO!&qWK7pFR$`3bgJ{T@LH9vHlR=2dya&3krVmE`%gA(XF)HIu9AX!zo{`MQWV~TpjWDQNyOyt(XLHBLQp8` z3Ia#AK3jm}51@oY8-Y*ICKN)8eNCuv5R6kw)$yf3l|l&&g&1z0=P@dC6zu}Bb^uMq z29!KAb&l>u==$V}Pfr2K6t0lBA_3w?{DGD)%)kKWxRau}xr8&{|We;5%?lhwfAIEiDOrXRt4l3~lK5 zjJ)_$VHdZ2jRQ4)r&vu{4+I#r;WKI&9h;n^G+tBF-v)N!C|omdGY0}Q8{vH7@-@fN zJeq7sI@nei58rZ>GU{UW$9@za$k&3l!;ZTtWm1D|R9c&d_GgwvXS>Z1b_|C*nd!Fd zt}o+WLOxNDNpt`>Lmkw(I3VFW(7Q&)%h7Q~;?DbW+)KM%Ap@xDeJCwf^&a&8u>U>S z(a8}@oxdn^DKpdh`C>5r3#J>GgrOQ}qkLkh7uREHrMEKQDtFwt_Zif4b~QgQb6nfq zbR%7FYG#^b%kKHB%X`0##@_Y2*DLNE=f$|!G5g7b_gn2dLvy*#MCsM7oXzqiX;8jT zmdx8zr`K}F3$uwF@ZO_y%cBah7@BMu@h?T||9#T_4Bhl1V4JIo)ZT?y?OC0s)FP8` z#rI3g=ga59K_9~xUdN;>v5_BU76-z4+CVvpq~)6VLxF^kivdw0HA4YbI$Qjgm_dj) zxX3T%=bifgw+xb;<8FrnT9xfildchOZ`PzW>zxsHytZB?XwfI~_$Lbhomy8Wlh=FfY&+tQm4{@P8~@V=H28CUr5AnE z=#McTI=9P`=7NnmcG)3&ex9Jl_16W7YkK5c7+QxK@apFwi*qbFd49Jc+lP%_S_(K( zI(g{sh-DX1jif&HQLJuUZZ*C($5pYffVY16iagk#jcX3%tLv|u$9o-xYj(j`rSsOb z8ArkDUlu*bM}>oLr-yA9n9d zL5$fSc9W5LN?_18ajJvhz^&Kbcblm0xuyUeaCUt8^~YZwh#4+>WTDRmJ3Y`zCvJef z=E5%>I(Ck?E5k_q=ZI#RG@}&jPir7=)Oz= zu>7z$%|hl~^+FeQ=a~#=8hi$>`cWpwhk!232s%?JX zunp}&@II${Y)*9jR5W$j*g;nDyDv2r50wPZ21-_=_i@J|M;2DewKNXm))@!WGSBW5 zMc40mBWDUhG6E&N?njVQN|U2>U@gHy-%h*}Ts#IE;XnYtnV-*qEYk8!%DhL#B?nuI zN!4Ama`PN+wj&dlPYg89CQ(1v{3w&X;5aqS>0usNq3yb>GR(Xk!oCAP4|M!RxCW7& zm;6xg2YlQIZfIrODBtac-KXH^wlzV^h7jBNFvIa`$;!35wbC3IyNYIp1K&Asf=%^` z+qP!Hj!#ppjMS$pT*iFRQ6U32>F5O(A?wwI*_l zLA^meoT6GC2f}7HHu6h1im#KMPrQElt*yA*cfan#{NG>K-|>eBTX%6~TjRW+`N`R2YpEO)-*COR|@VXD+JIg!u4 zbiFgYZxbH!H1`OG$nVLEo&AftEC|CW(9;)9wHAFozG)hWO=i`n!rcAPSFwsozcBr4>dlriBX{>XI^(#~^gg z%k85N8DX5JHd+@dNjkA2vDhXq4At~_I+uRlj_hNg$jRkO!t@gN6mdNqUFxZ)ui1qL!J2zvHWNr=a*>ew`T8`{q-hn+g@~; z!lvYoO!{(=rf?5{cF^<;KCmPJ*dN1VZ(C-`0V97idX(8;QC8aOU6mQaCUGOv}k^5qaK*|t{|x(pXhscZ{J5C4zF~U*d122IdZeO zT5VP*Z4*C}!vY0-km4)c5ymihPr2RAFfQ{GWu2}JET2op(8s=H-19ZKe8A*enGXhx z3vWan@PcKvrjq*H!|0y(wdzor5`d#UQY~_GFUP6(Uss5U2t>}4u2i#6%$M&A7Ah`o zZM)g>>kTNKyU7nt_u;o!BAw3P0;;1BJqJCuc3PWr?n|W24(6}Nc8|slkj|kpqd7k` zy-ycLE_uwwEAPimu~6vV_!HR0v=PfS;o`lS@Dn4|^6?E4fb@JPNr_u!6K2OyuH8EC=isV_TAJ3 zWHSn^6@K`9@7_%zD@iD^C~oj2f}i?6 z@l^}?Toirc;{3m`wk~AX8Dt-y@FR`6TT`$Hs6lD}faqPAdj+=KFBK9GK|M)b_0hRs z=ty{r0|ZHynz@49E{baNKaeqojV4g)V}KLSvS^v;)eGlw2ijFi^BBccES#Vd`aPq~ zEZ>649PJIBz?8~|!)*YJ_TUe+**wCn8I@Ho#H;vZl6i2w(EWGqY%(C8TNPmty;AXtKi>o;gK0ghXXJ<^gKq1mNz7yEV7^*V36N$uJ=~O zBgXhz-;a2^fxfuO*Q1cAh;saPF@ecmTpB$q&?qPgED!>RR70;w=b@-)cWN)=9by9O zG9y0N#`VS#!vjj?8MAjo=0|?!ls2EoE6h6P38xO&}@3zF+?HQC3`s-Ah3--no(9Tj=G2+ zpk0PdB}e)?`j|#Qa${+AvRZ=jrKvkWwt%}Ab<#z}Y-P@X5&58CWp~|nt0}CkPtM=t z2-VYPONp!yC8^;TpMmn}aa_82_4L_(JE-!RY*#I-JOnJ|&sxhOGyLx-s2Jx;8T)ce z>#qABJaWb}y?f%XWr4&V{K;^MA67HE4SJKcRs_ubsLy)`5B%FbEd2=S9f&r#qg=3n z03lK&qP1~;r@5)+^)R7yglI0n!cqBhV*8KuLh?4NrTFp)|E2xvwd*~%3GA*xf68$l z;|zWVp6fg(+jxIWtC%*i$Y|rSWr+ps}J4k10h`Y=0 zoq-R;^U~%V40!72ZSM00_xY9WHXa`iC6=XZ#5L_kt8bj2wATMc8JuAuRCp8{KWkO}wJAqd1?zl3*ura0JwS1oH*EO6Ia?#v#l=EGSw> zVoZmqMsN_u$BM;&NhEF(ePgr8qx5}-D>>Hl+o?e^&!X+zuC9+9A8zFMMUwEWBwBJ~ zKJfV*r72+Dy~2lf$W`q2Qpij3d^|_1K|qS(SdApMr60z{I*Ykman|LBP>`5{mvEO2 zi=LkmsqeKb0oB#?xZl0~YBuaPGwsFO0byNJ`v)oRM$1soUVUxpV!ymVBPaC6ZqmGI z^s~T__y4WcHid(rTJChRdP|eXmv7O81u7&3K9=Y|O%BR1v8hUR zlwTKhG}I5u8+b6fxfgMpDdu+luPz`80wQ{o-);M6OxMF+AQHT__-7zUu-JpP-GrCo z7hm~NLKtA#c{7yOkhL8>h%`yHK3Z5O_cJ|n-aqQx({b@cs7h!q$JQpvyrZ#jVDPa> zAyR~EXxlAj%qAy(j#YU&)l%s>5*XByQ**j&)J!-T+^??~7iccmhA=vgDzTkBG|TEt z%t>hIa{DAVtdd5LIk%;)r$&fA!z z8^_>+ylhp1D?Haw->~!wC}~`cz&EL-9cRnWofQT047&YmYPgj%pHxE631Y_HZ)>0Njdo>0&V* zZ4GC6bgzxm3Duk#UAoBtJH4LVY?1SxHAMK&uY9yPrmLrB>f%R$^RH359^$Hp&&ldv zcc1rlTs01@VUONvqB^Yg=Qy#ZfzL;u@11sqxT`b>#`8qUfE}!~2h&93TpRk5VA1tin zgL)gf&QwcJI#SCNXN{UIAZr4K;FfCgKKYU~h) z(*~r3(V|?=tPpv11y=^?ZXJsxSK^-^kfWxwXv}7(ZKuKQ()XyUp)ZGf?lgQ^Y=$cI zyH(lfe-IsGUfV~JK8t{-;K0oKh*~{K3ir`Q53HEP*1;0OC{>8wuF&UzUM1SP=oGi1a zC--sImG`Cbj2O5-7^VDmiA~)6hTUp5PEhZUR%49_gZb@Ac zj;b`>QJj~@B^L~2S!9)vQ*hXbd@GcfE(h$y5vl;bAKv)FHOgq;=~&189^BS8IV*IM z8pPd0!d#Rpj^d2!IhzI^w6>N|zP)4o7fKvn%AEpc)1P*wrb$u)QK-9jj^{*`)*9E_?IHgtkLKv=@I#cC#Y7~{b0vU z#oDDHncm9I8Kv7+692*8qR}DZy{qx8P4x4)i~u|x^GD#-Z|L)kujJHnV#ZRy_ovf) zlm_qDlx?7%I3p+T!jCiktCAU14mMh&@q7Lji@ukHYR>D!xA81)^S+n6Ebvh(sBaa; zkKfB0+C59H|DGg3=wmhs6~k7@mMeA+(3EYHNZ#44!%{!miHLOhHTS^KdtC-=InLt^+m!{4iFYLqcH_(vkuABF%x|+sbtPN-Z!!ecXrt*WejdbA0x$i%5D-f%~ED{_ya4=?GH~Gq) zOZG^3kMDYYWUNdrFx*R(*J?aHVd46 z*~(i2^N`dZC~9YhrnNG&g>JX!SyA76`-@cXwmoV*W)k23#;Gr@Vc;@Y`DN`fG9>8S z&&jgWmLB|G;*R|LqlMNKjOh>bDZ)zH;ctk;v)ySF_w1fvMzjt0A-^H*<9Nwf9?m=nm%&m<&SyNupNt}i(|~YjVn!*+H{=CO$0i$+keaU)sPC~{OAQ6 zxN|47tl9gJToxP6iikS=-ZYkqsMb%epcc_%6drt-5%>q`5^IUWQWH`3Xmf(83qg-H?@MjzAlCEAW39up1;OKgl;>*1;6 z)A6Eg7H(s6AUVx~Vk;^^yw{lIz<`aA>TEq+29m!9cY|_0&{gNb^IZ2tEQjBdEbm$; z>&h{C2KJIul;mM8GV5FZiv~ye{YnS}%Ji<#!a_k#`)l&<=qYK^Su`|kjQI4#R@+ifLpcC4}D@?zMg)MSq2=Zp3l=;>{AtUX06U0?r8EQuq7AAvVo zuQJ-Z+S+DoAQn~nuYcj2i70~B>h$WR_dKaaO_}>ZL0KreKL8#do3l>o*q5 zzKX2v|MZYmx=7K8+f4Y?U(bIiNp6#upm@GecwTPVlnd(WHIt?AjG+Og+Cb(0hES zZ25opeYTJg5HY%y!8gW}-jF2s0k&E>AMs)5XE+Z#N{`NcgosIk@3J*N+o3Szd8|Ut zujeA+1ISugK!<8Q0K{XZvAkW}yb zujX`wXV2vXKGMmpwfQ^V&#j2DP|XRC(DLx)AC#K1_-Eqk@?LbWUX1h1-_u-dQV?BU zI$Q?5cWroTzY(7KnldE(Z0RT>9-Ao+eJEr3*l!l!elhBb^Vfr$@<907>QX@y4x;#K zaw^6@vDfw2(lV&Pe|)7Uua2^53W$w_u#VN^NBh4*T^q9UHP3gdI7E(viD;v zc8>w)u-B8e$?^^dpoIEe%gA!B3uj-vl})4XgqySVqe`ngJAm?WMxT5KRaUlJls(SJ zeSrtUA_s%{VKi-J0bL!GsWzuZWF%WB{;ZCAGHI>FPP1Bihs(@EL)*y3nDIYEE`ccI zohC0>0$j%u@%SP^R=}E=O;weoavrc&hW4FF z^+!@oqs%N>2&+`>LLN>Mo#sS5+A75sBknxgnPEgan6uU&v>>?SYTB`fQ~jUU+VJJ; z|7kz|gJN3?Wq*^p!<4^CnR@jgM9`f2y)TtY#LD1(M#si@w0nt7y5eo`^o4pb<(Z$? zdnW#(p5`H9B?+1IcY|>9g}fA>?B_YWyi;7p&HcZ@1|A_81#7f0Q3pz9-PBJm9e713 z3|s`iFuQGL|58xHfgIkv!e3WsmS98@x&Z2N*=7Jv8n!z|rht#Of)REi)=<~v4GsAG z|E7F^hyYmdp~sGfpUBuntC-~k3JvR=vihN&E0W3$sv-^SX)W!g0fp2$t$=(Vh1^R|0em@$ z{qGpMKmROmAeahN#gC0KXx1O*VO(=IGX5YnvTifpx#g%P<%@tvH`m4?KpeiaJi3FY zy`3%>q=@`~>AT}UDN9ce50h3zKEuh_)XM|=L%^&Kuho^oI?S~4$=4m&gQPHjz= z{~dFyu0eSCe+(CYe9jF)APwGf?|7vSH2COw=15|qNDBjyy)@W~dKsE)Db~3;`p|4R z%|7CeCBl4;rENfDj9n69fQ^`?cRr-=ztih71&LZBhU@)-GIq~GYQ_jjybhR|3jg#@ z{}swH_b0uozWS1MSw!zwTYQ_n6H9l7Orfzj@5EZ{%eFj$BxrJ%48xhLD`M zb72i3Xqk9za}Bj9oV3<{HQ`FyC2gBaJ1G^fF^ zY08V{m296P^jgJEna^mlq=Jt8->hs|7#Qd2)m-hRlhw1}|2#CP=%SC- zipEtdsn-prruL-cL47K5Ch2oFwrZ`z22X-GRr+@X?XniuGm!$WI?rcjqC-mM$5Jq8 zOJQJOsDzX(q^{d}H)}O)mldD%vF=}Z*xA_ySnj)&!Bq2R?Zif5LdWfDF>-nrF(0BY z>J)ts|BjLkADEOCCqLhD7i+};vfid>E1a5faxN^U?lh`})RZJmfe&=VtCZyo%Kuay zhCukwr|esXTm|@^Vkrl2KWwS~pOumS$&TO+0;QS^9waXX=kFYiB3s|C z=LW?B_~s`(YS{9(DDdN^nawQ%f8)_hwsLdFrZ2^mONGUq!F$44|NXA?{?flfO*mhZ zt4P7bJjhjUGtR|)jq-nbd1*Th>)hr-IYPQPJl^uU>wi6TwbHEl9hz^VKI0KLh$$P| z@NrsO!6+nPCbxK?u#^sKNx$nm>gBa}glnVe62m`Pc8I>_9nyR&G6fYp3khe(;CloA zwr;Dw0+#EeVFx-h2iu1!i~gsFhw5nuEmTIWr&$@&3u6{F7BJ^!Xy?&KESp1Nf>><4 zsQy1{9qLqz)%`iUW@^wjGpC!SQ&DBCfINL391YyjH!A;>?4du(-l$Bz1kzx;_#t7C~Ohi8>&4GoR59HlQ9=jzHKzaV-q6=G->QaxYxIEdej(_a0} z9&I}v+vC3kTc*%3P>kB+*BU~$;p;pKx0`7sG*Q!$Yxi>Y19YrSuP7q5IPGe2Rc2Jc zNzqabrAee`kcj)7ZVM~_epV)7pRx|6ABHMeKSUx+QF?>#M@a1cU?)}k$icHc=CgLA z&w{H`0;7K=zTpIcodQ!9A0h3ZLH6PL+ZO;HvUW{yP>^`}>HS(itz_6zWT8BP+|sf} z94a=|ni;g5G!UWteJw~ejx*oD(6I+nXI1+YgCRtKhmDif;&iP0Ei+H{lHYExsdyD6 z5sck~Hlm5}o1pvqi{XF>1eG3-6VYrG5g(PP<07H#EoAN9kTqq}QF{>~1Xb{~9$m7j+{QIIk8BSVF6oFD+)Mm6)WBt2^4O)^{B(3|bf;1K@ zgGfZnDI8Abf=8d|PQ>7&bnn{|%O|#o$ZS{&EGZF4-EV^2F%NJ4F2)mjkb^eDj7GVM zSY|tmHhzpQ*D0g|+Gfty-A8iON{Z!y|EO`QGGnpQ^ePkU0P4q zjL$BnPD!9u(6BNp-V}bet>}u$FgA zy!_c%eC+$vnw0~!LsKa$_5l@z33O|?YZiTiXafVqdIv|W%$NAMUtYwADik1cLH$sbK4Gu8>`ZlWIAqSfs9)Av@><$<;lPw3*b?C zg9q%pct5lh^U_KS))Day9-%`$(pk?Qbjo{e)lqXJ-rQq%Uw@ryS>E=qN=xp!uNiC& zmEf8^ecJipF6h)n*zuHz?7pAHmGCE7h0>uAB%46(TfXsOiivCKgtjtuxBFhPycgM4gR^3YK52#xD`L4dFE@9ilWD)q+pk- zZJ>Ot2Z!Cy*4f7kw#JZf!azGJno=yPwYIRRbs}4_L!U0{!sF5=8I>kkQ>@5M#>z+t z1E)rDU&1Ky=N`HfjXBLXl%shdkS$wUO=b5!yH$}p&Yz{xb^ZyMIfnL+8eJ5R82P&o z=!ztX9&?}ee>T@yeb`acqVXVlW1V$Dqh7~kG_z9jjgh2k~*&-g+}E=U+g zzUN>3ll0~)LZ|*glTO1*v*fyDrCX0h;-45-s{{MnQHg*sjO{bK9D%W`MjTi8giM5|I$!ck}jD~B_d1kl9}EV46dq37}F57preoe=^reuwG2}H!|-gu#P2{j z3QE~^I9yc$B9X_H5^3KzHP25>+5I*09QQTH4>{J!9^pxfo10_D;$SCroXV_FhO^6b zzt+Fx_$%+UHkJM&jSS#1a+Z58O#xe{kIVm##y$Wwj850u%^N81}92i^kZuatN2-`;3sG z;gqwKvC$;^G^mIUTXt~S#2Lz=#RXslL|i1xA7OO?f@Bx^_S<__*VH^rTt+)n%vl^3 z)(S+ypNck%4V>y4mux67!~2l@U()?iUJxJ?0B9C{B>RNCu3cN9ee8M2B6AVTq+&$% z4MgdKOTDgAL~y%IUGWqr>WBLc<=lQpmuL@EvP z^K}5UPsi--Zzi(A?Ohy4uAo-@_E?40+#nc%A+W^eZMHWPF~NKqWCL1ATUmRbnRlWsX4jX@wQ;8*HJ9+lZHG2zp3GK zbuKizck+jDz~0ub1zU>S9;_u^SJvkP7B^H5Z;aFtn0}(7Kr&zh| zmqDI6z{!%XP*Iz$WfC&vqy@AEH2NpD0UT)(58?z43; zl?2IJbM}hZFZHU(OkgqRscx(^f5ev=yOm;FzB5#XFyS-Q@OX@0kcUv+?PNym19sP7 zzqD9#+|gx@0*X3KjQ1jna?T`Ls)bvY;|W?~4v>6`NOV*#IA^($Ed|ulxV~k`7M)SD zsuS-QyBq&7SI7TQQdl4I5QN1*jZdX!GV7~QW-5|%l(RBXx3%AbLZ9d8Ez=^=k}??m z?Blq;`TJC6Ui9%u;2gZxq z)=ASDJ_D{+Drl9x>7ecK(Ct{yRJlDq^5fQ;=&W%o=AR-22l>!pl0Z1w4HGhU&s2F{ zodYmbbd$NZcTmEhmh;lnP3{ntu=lh~Oo}n)!T@>?Cb6M%q&)!l4=yZJJEYf^hwdw1 z9m4(Rgb2_rOX244NBQ_Res=5@v|U*Y*}c-QPX(LrQl`lc7*C!2^VUEY|DOnPXyTc! z?dZ`5ogjryhy6%d*CCvq3^6Qt-;NHx>qf7O4MB^Uo12?5yj&qv%rWu{k47kod(5bN z?8(cmkT*j?^kUpxX0f)$#*$tE^hUu)CkBDGuxR!g(6Xi9)_$|oe*uqOnF2n6H#Jv| zX(Op<{QfT)A75@Yb4hN0rXfhQVk6tc_rj8#E{Xp1x)j~xTTCahk>>%EH|$07QT{m+ zp!I$*<%EjV_V7aarGtH~x#-@4(@l(T&F#J8{R&r%D~s1@MB*9)S)zq zK2zsDhvxShK0!bTbl+*yq8G5$Ze_H*%;NPN32w0QelJX1+t2juIWjnJd#gs?gU9h{`R&QW1N2bzZ8;C0f%6?tP{YhR9?za(`}^GdMtRGP9jdbX%=_VB zFBhlB4PJ_u^~Da5KW%ju+Af(hdzI|3s!3b;Bz4{wEd-Ky9v`TW4UbU-*H=zPi9hte z^Gv}+Cuz3HJJ^@T`vSZIuN@I&LH&W~Duzb<7=wu&{#my#m0%Q{M2 zWvmhq)B=3v8X`U(!8qI)@txefHJs%IHX%{guFv4w32w~CT5{vW)zQHZy@AKTblBH0GN42}L*YJCz=owNU^fN{ zlH=M0G}#`iD0nKS?fErp!89~OpQyd6`{SuG>IWbMwhh`_rnOSZ4t`c2L}iRsn75_J zLNE98Lrx@q_tC0*4*hiT2Z2=6>1q_r{Ec$Oe8ocdl!zreJ=4c7(b1D*9HCjA2pr+40%|88((ahqzPM23(zXO7=MH8D2=5)W!RYE(8 zkefhzK4VDaIF$uK;5`|BO$GGHH?65;5Ph=&!=nK+L%st1vd?l8&x*~MLe7U%JH!Iq zDJ&>}KSWSYgv{Dj7m(jg8FBUUnj3L)-Wq01>-o%MD$w5p$%BQ{hO9+2W2Ug$K}VQv z9>3b+B%P4@^^h715dk4J_VwnFS*#2ZZo>mLi4m%Hyh^v{JM3?@PpK)NnjD?XP_X;c zM8OaP!D=W7F7#mRc(p>!C3a^gxMpU};fZL(SZZqA#ne}#mjA|r7BXNIe#^*=VtwME z)}2NQ5pylUlZ3`u5s!jgUw~sBZ)BsC=k;0%?A2|z8wdn4v*5p<$tv}tf1@v+kVCeprGQaf=Ub0?nvStSye0OFa|_yRhFDWh86#l2=;<9@`Q&-s zrs6Bb13#YfNwhYPWcPOenK;Ub1UgnJh|x~#tUW6M1CBo@L)h8)$|GyiuUd61_+!_j z3(-V;ash-B!FX4ER|FNyGHddjeEIe^8X4Y52Y|+SYRD-OhXkI)hqG{hP6CeKE@SCf zJCrQ9x9bq|^bA4Gn!gnfN@Z~HqN|3v9!n@sx4soYLuQg)!F4;$-=X3!AH^LJk>A`H zsv>p~#j-TG%jx(-M-JNjfk;Ds$@n0UH z`DFbkwB(K$!eWjM=s37gGel-lE&Oe+NuZaQW}T|q0J-fIOO{%>97^Gn8m$i@xKf6d zgmZ(saEHVD3G{lAVd2+&#@{%i+z}^bL5=L6L7T}FUF9t{Aq*#8s8&Cf;oe57L%#hL zi~@36kCO^ihs7c|9kmS#2TR6x#&c5H9iv}=5850nullaOToz+Q<3Pln*IHW@zQ8AzLyQTTH=t8G8+?*n*td zYGPm!s`5I;Xf!GkNE;U;msa*oRloLA>+Cs85~^f@Lz-HN8IzVF<}x4&>E$>;&BYjA ztf^&_%i6hx#b$ong-el^l1eAv{o7I+hNQeRN!IPu!2q6bd!Ub}{7_oB=}zv>^OVbM z8Bh2fm7B2QI`TThI`g`HSV#MU&Tg!b&Mu9c7){m^3_^N^r4a0+aV>HqY-p_-`pabo z>O)0RUKM4uO^m!z_dOAZ0jFxFJ4XQpJL z?-t3}E3z$cimO4mrFy90KSu5vfo%Fs0_ODO&7g1{nzV2T=iDg@q-_tQbh})yzDnM(S!4FN< z!zCF%qGCO5S^7wmyIwJ*%4$vhd%z@IfWu>}iq%}#`#yIBH&D})W~Ngi82P|woJ#?* zd-o&p@snZ^^aee{+y@-Wr9qse(hH`LB#FOrbDL zi(0=-`F&mDkYLL9b}lwQu-R`vUPnpeuUlUeZWx32vz1t>7HfZwNXEeSDMnFE>O42<3nyK^st@=`RR583cIvwB zNh;56mwak{)Ngv%Y!oZo_PMWEYZV_5IY@_L^bf&S)o-==@Gx~d(iYqjilN^4Dw8?r z8ErE{ab!3=B-+%E#8BkbENkk$#E2cD&bK;TuB-XBsz;Ux&@cATK9*$Vwo{FUi6Q^?NZ z_Y2KmgaVvzi$Axx{$4+qwMmeAy|3j*3k_h3$P~x3*_Wy1n;j*vD&v&duRm}`C#__@ zOc2czuV~Kd(tp* zJI}8LB#Pa@A21Sv8Q#;Oh~8vHx`?e+`CxaUGu;gN>95AAFl}8OqegFHax!Ewp^FcP4wQ3#O>ajmRX z+2M>S!-Tw5zu zW+TYO@6hHNpni|)Bod{&zkbBbVg$Th+2}G+dEF*;=s87qK6lHHu9@)N`ah-?X4GkN z9kE@Hyl8pt;Pq`Qf}04 z@42Nk4%a|TJ_j8m@T02cq92P193!uUp0gor9`mb@&l5!LWGY`e+~Lx$PncK@*MT?FEw%W#a> zD5HCRYvv%lO!1EN5*jG?Ln&4x^2ZF-(so}FUM>+4yyEEEFUeX{Fdoxj*W4-mOPlyt zF*E?f?g=b*j*T0 zQ9tsEVgX8?1!LQ`hcWl-A4fKi5=^vB)ecKvs^lujaM3Xf%lPh-El;~ld_YX3*tlIl z%7Ee4Nad@hcBDOix#Z*O$6+V_VKb7h zf)$h2*u~l?v$2WLiEsBhHnGTd7t1->6}_JaU#$-Q3ti2$;;9~E=jGD4i{a3Gfq=Qg z=}^wLsBg_6yXNcN7UR?)+hOE7(XlE2**5#FHMjidd5@`Ll}i~KX?H%7<%Nc)lq*=y zP*qvdhg5cyK`&_js|C;wG|)aCn2QW$IkC=z$=z?*^Qup86on?`)1hpYd|Jnl^HOf% zeTGk&$ve!6#iifb8v^iGdMB8OvifDIjl4M3RZO;idcIqg8x03lVToUTwfUG4kS?7$ zT>m5Xh(vNF?$@N-v`#rROKMim$;DqJnm{6qX$MJaJ^`B_nE%s76`wX>7SP` z28+I}70hguOK5-Z#w>;qrYu%rl0-5bpX?Q$tE%;T+vkJqLVy|q{ep92{8tvhz(8S{ zez?3k&ZD1_hlJ8G9 zNYOd9W18EQ2gpGXG{uZ*Uc4$+Jaor$CYGRTJbWPfq6*Y{t{&w#RwQFQL$qb+x@I+c zFxG8T;c~tI(muOy68Ct>an5!d$W7`p3J;Xe8_DB&PN)Q|t;8Vh#!Hm&KR>yYd0ioT zZ90f~sgliY2ye9etwi2o?0o)x#Ml>P_iUYv#}a)%!#m~cpr$ZhYi$1mq7VE0|M2w| zKyh_T)F>e&xI+l80fGj1hTsx3!QI{6-Q6961$WoMHE6Iwg6rTmIB)WOx%a>SdsVOM zRLvAN=WM!r_g=kvwJKGE<*`H58`vxkBm9L)Rqsdm1v*)AC;eF7O1XO0%uACpVpykl z7`yCupB^Yb!z+?(#-8$2!KhSIY6mUW#zZ7vwlaC^G>~o;IQqrO(JbUG(l8vT3-$ZM zV^aWM&XqmU<%kGaNg>r;*Gys50LUZF(H)8;i&R!iCPhQ@8)GKHa>OsZGSpTi@5F-I} zrHG1fnLRQW;|m51(O!`+oR3cg*xpFioo2URCC!WYMUeL4AXdilmAR^GO99P))=#O) z!P8m3D{J4HZUNj(Eohl+voCy>#?Gf$@tM8*8a+UeMie86y&yfQ;bPdPQh<U+3sZs{F)9a#j>es5i5f_{^1Kr2W<#LhZ^qK5EKi+n}kkDTBC=Qr^r&Rlrk)uy%WgDhkM@|ad0{uq| zU=1TX1(cN-%H1x21iUUnMx3>N+FXs+D45f|U0AD1AjE(mI_U8MgnG zQb&ISt*~;z@Zmzv&+Wn1K&JzxedmQU4myfZbW+X$Z!@!DkHrFm<&hgyn06WYym)@@ zMVesc1fm2b6yu!-Ql0wQ96|dS;YyKC>Hj@(y)wtO}vycY36->v-~WA{kT5I z3tef;m=H=TdlE5KT=!Yqj25s|AhB9p!Ze~>a-GWPu#^qfY)M}902m5=>BR2o`ZXO{*KZjjvxz#ho?5zb zo^OwuENS@;(lavH9&J|fYv1zX8osj%ZjcJ67WOf47@g6MI#4ab=kpfOp9sqT_)ut8 zPIsG8&biAWh1KHftbAIGzf7_6u5VlR*DsV2UAd*gt_>eLTJ=`uc;bpba#G#T!Z3BG zhp5p)iLAE#bj#-;CaikdJLEeUA2aCp)yakMrP7;PpbQJf*6sSqT&^7&I0cjz9{2OF z@}NoXbW_G@lF4Yx(eBD1+)elB$Yu*yRHzPZm3%{WP7}5mGh}gj*_imbU!qH>GX!bD z6!4TJ0By6V7WHP{RLrb`f70osTyucCp@DT$61colA6t9RgR(I$i7!lqk1gRa6i=#7 z@ygz3bDuo&C2Dt=EH@hV`+NEQ#UvRz@5@yVMRhQ9^832>h9K5AV(xQQ1esY9L}L-mgYqJYPSd3@?l#hFpdR8txnF!FA!-HU zLq1X><5FCspI{FtJ8_HfbR$2osJEIZhvDYRHQyd}U1i#av{-EzWOp~h&4hS==s%M9 zkaJwm76oj+CA*=_(W*A8T9HpoDofjVu90d(G=8G?Is4QrOJnc*r#cK}1PbY3K6aLM zs0apoB4`;232xR4&@CtbqS^^w9}NoOx$}RnaPm4qXMbdJA$m0`<9v&?w4_;K2>M-V zA-vCCeJ!OUuwDL^Tn{eGip}4EshBsMcmLz9JKFpmDe&d(z^Mtbe`gHL+_oBYCUe0z zSyjR?49Ifq+vif}yt(d@l?G@s_D@MOjt5E(UGT>d#t0y;dn$+(tUIo)WuZKZA>yI9 zw$tn-z+$Ic%C@S0y)F1VxYt7wjze$|k$v6FLjKDHTs|JGcF^fnmKSP7n286+@G;uQ zG4f47m-nx*9X6U+vuv5cK^j^AH~#4QQPnE*1xh|51jMPm1uBg_H51Tw6MS=TA!$ap z0zO0R&6teDf;Xj24bVa`3#;$v2v6b25R(g^wN^fx^IV^!5~!Ax_u`BIH?8guR(1jG zq?_TMFCXVu&5>?oRBacX<+B7zpJYd%0&d4`^DaqV7yi7so9Wp06X#lAof9}fL1!_@ z=Kf*1I68141x!fQV6M>dXZ4Tjl0(qmR?PFzxlh#VeVBN1Vg#d3q6jnyxBA%<65aN9 zvwH!t)kt_C!lP48ETh3NhS11$%F*QB#Dxa6Th;hEM%1z zSTToN`GR{T=6l>!1Xsy7mo?Zo#qOZ0_evDI(#zU5#OCGV#- z;){GRtA2HY`GCmL2Ui)_1{b2vbU@59(0nufJ+S-p0V?Kf#UMA9G>$4QgKT^iN7)7S zvHy3@IetMsXB}h29iGGh#xyMCgbvP{SpAv8o}^_A@w!w=eYtgRY%~y@H*Y^*7L89) zVBV+}<;lCD^iQ(e$84Gscuyyi5|Vwn{x%Nr>{rjmOO$$ngKGEd-(d>zHo z4m{+vd$OGZBcH)6a9K$h>5xB``heyCsW6M5rqYTAovfYQHqS7zBef&35nh4}8SW7C z*t|VSmBfX_A9scLIU9b>aK#ltA@!f%{6EWw2*HtyJ65gIVgW4SG3zvh@JQc4nOEB& z(_GwAwTiYIgcBpB)cak^5Wo0A3;t$FVnqMf8}yvK>1k=4R52vUGa5ZfDPyhM-Ts1K z?F$Nnh=w5CqLW_cJ(9WL3!b0PJZ^JwMtA1@ckCwVtgNU z_|ZN3VqJ~2OF_&E9lcrYv5(Sdah^(}0tg}OdIfWrFX^6z&%nz?W6s;RXSd1emh4B6+wXp%e{X}pXGSYYb zpK8wk5`6Vy$7UKTfU z^pVw5eWe@0YQkjcq)1k(Xg`{hVjSl2#%ll`BGHfknB{1LGVlMLG;WQjDE^9B=3^`` zzc--qh-(dv3k~r%!<_r)Tk| ziMwIYGhC~Yt1mwi*3P$Vp=l>QkuoBZsjPH+`O^;ZM}P2kmm@*k-EY^UN$-x?z2|oq zhkWOMBJ1A(`_D@^iO709^$PhRH8pjVk;F9GhTLmngQs9TofT&aDsg6>C)sIDqFJ%8v8G9SxG zEhD@(a*uUkQ&f;9l6f8*%ofJ}ZCh+V-h1WN8s6z2*nKY7T_=3?Hyw7cp3&WVzpnzh zTNgfHp08s)9ZNVC;z4+Wgmoz2I6YG=(ry>d50QM-Q>R!(a!2r9{zp}*rXGQobb4sG zu3rnCC9y&($UAo~)@j@}`L)Jy=G~q?DP^2bhgJ2R(vcy` z^J->OB&||BbC>he1M+d|AA3;-G*(j>G?QI4iFKjdc{=Q``+cmbUVC4Ac{z~vu^~Mu z`cgwPas#P%9ViBc2xrM&eIrqwR^JhIyA3x z>q@b{`gZz4@I_aUIF+pK$ciA^Onp0n=0UszwImjDKs@s}pI5vVAO$6h~i=eQ- zMM?576iduL*QLGvr(IKT4`Yf;CZ}0JsW`1m@nWHJSKCQcbKLA#lC|@Ec{*kc&8E9gh<8EY4HGOp~k4s9ufbl;xTHfOOy#KktT4guK>?kZQ5i5~qkj&N=Z97UT*0%Dchcdkxnc z7F2O#)<86lWN(>PJyD>X<0<=is*q%+Qo%DUS zU&mO=XRxtpQt8G)_H#Umc2-bYpYDk(=7l8Qdx>gd|1gs}g%i(YJDtYz$e%W0r0q5G zjS#%KyWI@&RH2~IhfX~B%SoF9;|u-l5r$*4C_P z-g{@=gtjcbgIQh@Q!F(GJ!)$}u^Zk_^)o?)kN(oa@`(CKq1Vx`k24kEeGDEiI|cJC z{NRUh!3%swAu<6I&E>_RRh(D3S968Swootzs_svT0hFJ2at1*PS}8dnh(QSW(d_BE zv@{F0YmFU#QYE#&j2I5@56A-5#pkM~D!dv?>NdiENiYC8RllLP@R#>(FR%d27s9gA z@Jx(-nL&94DKuDP>BeBM@m;ibuX8W#V1r;@Iix9g<{Vc%Z$vD9{uVE9D2%qiT8goD zpxi!tQA4;{Pr6jm33Nl>98wh)AZpR=WerlL>vsbscg2iKFQ!JU-N1E_-TZphF_Wh* zeYX_XM5^`Wdl>pny4QS@Q-W+6-9!K9`seveZBIeHWBhT~e9g z-iu#eO7p4XMzcXqE=@WC3YGC(4NbVSVJXXuJG$VVS}^Fsu$|D~BE{wnauLjj*wS~( z4N7uqBtVCmlP)~@?0>g^p+HOp^3VAClzA1E23UDh+={b0TI}zAxqtyM&PlCzJmuw! zW?$wsH8nI;mzvH+cd0Y8GT8Oiig!uaCqDBFS@jKGdL2XU0v*r)0aPBEne)Xk)C%Yf z9a(1qgbu%oPrEf6a{g%;D_|1D7i3Jf)|p>RRwNX==No102A%^zILOo zpPrs5;T_aFL655?0s8e+3XIcT?;hjBbilVNkYdD}Yb&d(j%%w5*Qf`Po)~oZS;(*Y z%d#+rF;$<)(s|EzzGM9UJq68=rBB3L8kWBNCx5!`%@|;}bDj?V(uq_f=bzHiaFU|Nv4-?0me}WR?;Ak^Q>@w5}wR%ldppXO9vBF z8p&69-F4^R!|0h1T$!P@vcz}6+F2ZNNjxO1&C)JCWn^3`l^^_5DY?)Q2Bfb<^Vgo+ zPig8MFA3ro$~xdf4Q%Iv6xv~$h?9;O0&Vv%j|Mp z#|ZpZa5sz_T{Sgiz!~GOO^Nnm19nTQp5NdBN1^NIr`m8OVdQ2K|&Cbf~XOQFCvEe_m*6>spE`iThBjDi!>i zDx&tHsg^nKEc5Rq>yl8IH*XmD%FD)Dsb!I{C3+%kRS}9tEYf=g(PMGBV~_ z6QN`UDs8NA(bTej=}uSs+Jv8D0;ku6&EH6MpyM#{8f@nn8KD}mx6E_Snq{zGclq-- z>#6XXqW0Aol(m19=@7Rd9fEiz%-365b>{9`Tz1@;Xbu&Ij&WkfDs4(s%}LMAu4pYE z%C17=OBU5NP#SB9NM7BBqH4m*3qNID(iv;C`;QHyGk$YZtupR&G$21Zf$~GG+-yceB>FV4drWLR#IG*+VW3{N}eX*RGT& z#4}H^ek4uLdnx9$7riBzW~cxTQRhnwSOPflcH65DOE2H=i2vbJLo1^g%kaAa3HSbC zVmCY1a7m*mk^uCWZZwK+g!_?$^zGeaz7d(V7sZ(Z#bw`98C{I?-}T)){^ z?j~BQ+AK=O)SJpvTUS;}nX0Dl0?m;El;dwtfu4#5BJ?A9eelj5A9&pM^)MR4d7g9f91ZI`hGsJF$|5ZMS}kZ> zbYSJ=HQCedwC_9IkIfaRDPNxj*@8V~pRh?ywx>BiQ(kfHeCjpl_tw3c3j5eW!f2T&)8@(o z%Y??6#%xz>#>}pl9t5@O7P*4Wqd#2H8+6$DE910g8}s(I)YYY^A1q>FeF610r(9Je zdfEii?rNtY7n3>m*XTK+`z7ka7gg+>%*x7Ye#d{Art9${-Lp+?VB^GkHdd7mJqGTE zrtwfe=`1aQl!97AvhqSG6$1uO#E+etza-m=#(Gn}z+Ru#6&48`il0)bAu%WCp%6bA zIjb|(R^rst3iS+-FoC;7H*wK})m(XBOAK=uHhnmDpe12u+U)*RN?|)&i&m$n>k5MF zgajG4pkQ*+(x_CsR}Z$h1kKN)@v=^-bIZz+?sdPeaO$naU9rWW@_D?KIcjI>vvK6CCpy=4 zCc$GazxEdX+eYL0%3nb)R!vEfLs9N)>Ij7%AuH(s=Em8Eh((z3ua8m!RwmT5v7-c7 zU%bn!tM~F2UYlJIDth&j1XsFs_VBR7%7 zXDxaM@ja`nc`u{mb^37@EfR3MpspY|~VCkuz0r+$C3g zD~moGTtG?b04|Cb8NiGBsx;Fb7?_BhUk+LrsW zx!0fP{6Qj?EKXbU`2xK5=`q)Rw*z$7y!MC}x zb!YH|cj0%QMSrGPL>+7>Dw3Mf$tK@@@G{l4))t0#6_5J<* z&*;sh;Tw~u!6BaKsp0|8@rlU~*~i3K11@QFM4QkV;`;Umjw4Z8BU97h0iB^0^Szk7Sp+UY2J}f2IN?^t*39BTLPV2oZo0EG}+>&dQ5Y1ZE2X| zLKs5b5Z@VBiS-o~1?zy$CT3+qPye<+{}Cv-M+ou|N+o8%fik#OpVn;5$&xYwszzq*}>~w?yvvT1}=f`&+a^S)A!?ASm66F5~*#eIy(8< zzW!8iZ+}}q(qTG1zKd70x(Mn;gqrKHtzU$UqmL_&xAgtute=Lz*xaKt>E*a@@WgM( zjEq%xq~HuRX7M_&ByGm+oauE6ta6sp9Sn4i@Sl)sj6SD7%4}F26ytsMPG(gt40|U!=8ih3N;JZeK$_M zf3FPjGa37+Z$Gz$`6Qi3tppXm+_-kx9uOyj@%gE=rmtJ_TOIB)+>2XW1im17ZV%@b zs!y&2{uyCX@~}II!cf&(%fQBdWbK-UChg)etI$**cOVqR_6VnYOuKAIF6N~k6ed9s zdFArX-iV{Zva-Pn58~nStEG^S@-Q3x@E3j|`3z^)GpKUhXET1{aBC<4W03Y?%uj$| zIf%hJv>{}WnXXh1u+^VAcl;FoF#>$7ep&t>EgNju_9Ck=%1c8+KA9*&WpuJ=e?0$L z^lNA{H|xRfZ>qsW4*0;%xqH>7gWpI9ar<$*Uo=Mh3(s^~IH|MU?9F}!<@2<@+2)_? zih>uJM#D$9{~Zi)A=bnKyamM&=5&Zw-w87vfR9;74|!yD=x7d1+NmDKlv3HyHSAC; z+^C|)#~R6P%oTc=rS&Hf0^hV&lgqBp32P+D@xHYqt)DGKR6ggfM2$Y9LQ{l(LdUJQ>2Tyk4Pitvf1JUhcIk!eX}NP_CU?Nq$R zf8$e#pgF=YV)uv6Ci)Oc>SN|I0d23Odf4de*;AoPX*O6xsXC{j&po_`j+{#M;N0qp z)3-*4n3ey|h{_eB?%)%a40DA!iYeYG{o@)E?_bp!rl{rB980{9b+*a&fI&qUp1;OB zs-5z)40_6c^u#h~wFLa{ga@nl{+(LrLPwHe*M4fp%V*=&jub7TBq7HYuQ~a6m&UCq zk8C+R3-c;F=d>ztG?8}OpKM=l+EpaHZW84)XP%%$|Ee^xYv0`?^YXo?3ubSggHv$w zZG&0R6SL3GUUV91Qh92YILG6(?+f#I=U9J#L#s1%U%7vI-}(%Ak$(w{KL_5(cTr;r zepwn7Ezy0sUn9t4a?zP|`FKbF6texYRP8f2>@|LChW%q=JR%Hl!&mRjFYM;sWjKI` zCmrg5y^>G#sg5iak-))wi# zJh>m_bJ+}``H2H3L2J>P|0t&D0m;Zhw9{GdSR?Poe=|4F`#qR>@es=lzopWlCd_^w zEL^IDrqA6klfN?sr4q9CvK8GIysvpye=Yo6PwUC^hru8dlEx8})?jL6%}Al%%23ft z|6=*DRsr&vf(KbN;xH?8h!#kO;e0O=wfIc%ZVKl8N?@zUkJGA$(b0;fJ&3r6vxuXD_boYY^b=}0Fa5|s$9SRLGskhYy1%3K=T@}~3 z^*jDnE+$N)^%|-2H-o$*As?Pf-pLKTEe`w8{%kv(;rlfZjvC2MR-~;cVJ2qfaR}}{ zvAZhZ!M=ky=!W!h9sc630jp~nb6(f`dd`kKaFX#iq<+zdC>`=Oy`-j@U^Aun_qV?8 zTK@ogu+Ke%whHzq|7RK@i5xjTOKL>`9+dRnx%>R0<>?HM(!yVIh^t*}2}`X9OKnGl zAPOvTCz9S|y?XshtIq3W2*Buj#0COBa{+OCZvpoMx(KQC)!yLi8qqz$8jP2Az-4pY z8}-7MlhY@C25w$D;E`HaY;3e?fg$BZ>9e|e6IY$?-Q3#fJG|67Hq#%@J0_e=cx;AP zz;mIV-Xh)G%C*#ojNr5M$=>2i4HR7Pi=ze&W-~if&@9FaI@I#na-RWLy`FNoU^+S` z#su)Zm5Zdx{&Ir;EW+t~sdBS=>cy#T5_PvIAxJg$1TD`1&mK0gpTWAG z0ztO}$sdy4*&m95k1`szWVxdIp_8M=?EcvZSHbHO--&Czt*sd=mOv6}Lm9;7EhbuGI+agw>o zWyr$~wf5NwhNSL0B}3p-=i^e6ogiP&I|qt{sIGa?-e;p|>VDa6R6MtD_h zDZRxJ;S9_*}&_edT&;y-ZYMNnpjBo5&WnbDnu-)$n6iLj%@RfkyNxJaRr-kX`f~&uKALMg4J9sJFga z1~c|@}ELfOf z988@T=MS_|A8M+$h3%~uE1PEC)b$v${m?kjqKL;9BDU`625v2EzS+zuNz zcbfOU2V$irHit1<8LmvQ;T+qsqBhB#t|k| zZmOkJoblw(;9FPX9cC`~_euVJ9z9qAGP1}^rLj-W*!5Qv-wnf7gKTn!7{~7}O?TLQ z*xRq4gU`mF@4;)xJufuA7i^&6Gdq{3!NwJV=uMm8;$&0$eAh4Efd~!WW3duF>8qRe zNpo{^m3VB%Pz{w0;kUlWYAt+e-8OJd892u{Mh8`)rRiar z7#T?vTAo0&)tZ&S$4+G~QaWc{uT6y8Nc&AerM0+!Tps#ImIymn&>S`d$Ng}mxD zgdgPA>U6Sc#?B=?pZv(2O$0+4I-89^nwmjD0?!&upZ0|8s ziE6XwqA{0&cjLAp$m#my0nxFsrp#Tp1_;ORmSb;44x5i^om6R?aB}m#kof)>2h_#l zgvtYB0TS@oZUnCw$8Z(r8%k1utnvjrm;Wy3(-$EJiQE2@Jx@E3?7BJJ8R1K9YzGmO z@q8m09c6$6zV1a`MQS8IJT^BYT+DbgG$!gGoOGNmOc8rTKUgo3#lSHmHeo3ZkL7_eHcuoyd${4+cENP>LUE(x}W^D5n6hd-$bG3 zV!*zMepAMndl^Wxo#RDFZHECnBy2ZS=WTBOG3dq!B*?*mE4W;(3nWQ_J}LUe`F(~9 zY}CQ|L+;?s@m`1RzuT1?tQ6o{;o^)TJK&#>|L6JtU4=9uUo38i9_YO@fS~N&cQQNg zkqa++dshuSeSKPEG)ogkz5q=$ zIbLs?$_?RX{O?`=f8TeLAQFYI$4t5~EUUl2hC-nFAfLO79XsMcV?HJ$hNjbVY$x{r z_dWk#kKk|kc|9HZM6Hn~_gJlYOZ@FC65r!w=?^+k6B=+WC=NdBEfN?2_y23&|F6eD zlY%)mFf?RCMip5Oc*j7uAG^TFOQoi3151M-wX~a-7rlnU$B@9kR>E`rp;|Pn6aZA#Mq! z2dlrX?OYs|4i@GVV89!uJw^K`oFV(0Qnyex(Tv?BCnqzGxm1Ac$pf9+8JAt}lH?XQ zT)-|jt6#Ef&=;Ex|1ppMM2&wx)>|6JUi+nf?pnNQesP#2Xq{;*ydo_*;&q(^>F_Al z@A70}6|3Xrm>PM272YzOhv<4b!pVp!pYVfa^;7fNs?SDmupMRKJsG|KRXaY3{m9oH!8UxQR_sI@`S*oa z?UNr|F%x%k#_MS8&6~|^*G{P=ijDs+(UYW}cFMOP2cFY>=XO$s>b<7|i^ldR%K3fr zLZ8LN`&XFLzW+4|63VI5CqI)hXRE^@ewRRa{_Z8;pl#f|ho=IMLfuN0`X5$Ydq&fO zIK-M+cE0bOcVcZIJN;sD4i)*+|O9xGu_{bZ|d; zbVJN_MhdwWs_82~f2{6ueYjI8?OyD;I>|y18;WikFt)oZR09>nUExYyy(q+Vhpa*Z zhXx`|HLLwVM20H1+lMEVZzdT{NZ>Uj)>h zY-QIg=zW?A$5uxVw*ECJYP)Z6``8~?Jepaj(A`c2?q6ksK=r2iqzdKJ=-iK2?B;9- za)3a)C*CK&K1in|{VDuU34ou^`zJrgy$SwW(r)K}?D`)wjYXJJS!;9VyMMLM95yB* z5~zIuKc(^u-R*MRm7)(%r)7T5r~C2I;Oh06g%Du<@vdGQ49`v=Yu}2kH8?ofUz8Rd zh2k2F{AvASkkA%BHC3lAhf${ZzTotC%Hr=~rl{Gvy&+3bakZSW2x~~UEgzG~^YTMI zD60R4+4s~&g%P)|{^CGT;M>Tc(X~#4Eky4CKy9~#ctqRc`Wh)vjLw-(OXr(GNA;XV z8QEAF1AP9gTKH3&sS_YO8Z+_Lnm~L1-&N6ros8)YAwksD)J%q{nPxp3e)y3D!{X;2 zC7k#EElyvbi2V^L`2@5R^m%kpT*TWpN2q(%;D;yEzzrzb0Fw2s&`Rh{q}0b~JcQR7 zCP)|B#x_3FvPT{DY6-_189<330#4;G8;97XkCs^9;rOv;Xd=27)z-=D2@I-N{zhMlE< zkFUnc;3s_fOWwi zr4@+}$#K)x96JQu>*JI-Yzpxu&X!jZ35RPEoa~_i4e6YQV6tJq5<9kRr38j<-Ph?0h-97EUMW- zb;wlSYcbRmWF_GmKN>5WQIYZ(+kNzxj9W)#T2-TuRn}k8bhp+*=7naQuUu=#e@{6_ zCAFqpqM}YA4mgm{Fux;F&-fK8jv?=DK2vI=?g6IA)=f2=xLY~V^hK6dJ2xsOJy=-S z2~^obuG1@iL?9u=a&?>al|Avv7#CMb35%8y&7SuxD!1kdB4rpQ-6;?l7!O5i-_s29 za@`ca_e5NYWpJ*GPTr}ofAP^$@;Kp1)@|1h2Mz_@B&2WsvHorrnm^%J#~D81^QJyP zaLHpSdx9|}+_`Z&k`+ZOX}wCKdYgcHEQG4z(gM9fn&TS#(Bc7J#sbXcz{OTR9nw6s zveu;`l3~-e-nwM>>ITMWw4!R!7%geIB>WL)jdMxN7y&%vztip&DIET%_W#C;CA-uVeKW>7oY0^_;|q_ydU*FruHpt zPX)t<@7Z7`!Iq6t>WAA+fUkvx(mA}*9Ve-Qn|CG2(=ueoFg18ur^8-*(}moVn~iV? zZ#UHlQ*}beXXiD!)#Nys7xg5QAc!r^7qaWglHhaFiX8t8s;>YgqHkk1u6ghMSXrOt zSl5jK18)5Z@sU^FH5_5>t+|7>5n;jcT#?O+;-X=-wej39tEZ1-7a21eyn(!s$II0E zx#YPc=I2d%dvr@nFzD>8MknwBnLlZKd}7FGWM>S|_X5&*g5%WQXreyBXAy15dH`7dRS! zV~wI~$>m^7y}ZS~K@w{WEjc?ZCE}LSHG?8G>~L+=EnjOJG@I(p=Ia}*00dqWbN`cr zu5)A2nkD_jPWd>+EGxe)I~@I!%AoDO8Uf^LvxcniVeZbevO@NqauMB9k+TAlnxZPQ zuai*3-Fug?GWTh!%k%VemadLA;%Aaqgj)$kMLQV3@lv^e55I#>P-`>p9GZFBcs)~X zQm|#H?p{#AU03l77Ed0jrYZ%Y$X5uXd}z*WL({+4oVae)Q? zZwTIh`)Ubr|LT2cU966nXH3jM%cc?Z`A`!PRlX7xU>a^dtEIlH^C++O*i zBTjgoOb0QO_oG5pqeMHQudo?^Gp+}d$IEC4SE4~MFZb04?MS?ZoHUoMg{ zCSG~~x1Q6v-j@=#rkBXbAm4{Uu>Z*%@MgM(>ZKR>6lf=LiJkirb>F^o^t9~Sd+%lQ zxwm~~6z59vzOMfscw6m@yWssyBS;tkNqxB_4QWr&y?uDmMmV+Ye5w-ln>(6VZD%>l zg|a-)Es)MD5nWf*CfPG%BWPIOI^bJJr z)om88tVkY-^S=}@`+OXI=#5+u@w1(DHE`hfyxT!Hxi0d!@$@~DfI`rV@yki03pPEZ zh$mMPuoCueILegeUPoKxDk$snKn*#MJ~`F9w7=npKN&_m&rEsk;WuQKgc)q!3_pFM z-D3AyJ~X;iz>|l%rQ9P!TKo_sduQic(~yvQ;uxN0=9 z$qfG_SNW`ld%a}(VE+c}@CO9^&qbsQ+uAei!Q`|SAKVUSrqdFkpEsBAwjH_7Z0Php zqGH2tD1g)n?kMB!?sae51am)jPD^r6OOV*v*=1MBfV#|1V+Dolr*f=ORcC>PV9)nO z0J3tYm7fd@4B|P>RI}BiwnqtCBYKL!9}ZKwU6m565-Fh+O!+;Vn@Vbvcpq|9sU%Z( z=EZJ~=mOt~S{qn*k#BUy3(Qhps^ujL?(|CVJ+G@5raaIc@XknRshZdQ@S5xk6e7Bi zddR*@AQ3!0xLoUW1T^v4m#5H!uAo91HV|(@#O5c&a^YxvBsvlM!!HOYZ#qd!zKP(N zM;>bb^{z$iS4-?V?}H7dCn8-UIYSZ6ugcsKWNqf%@=;ciB5$Uh?+jCuJ=LvQDmPa~ z+j6K05ps{MT61MVu;v<~%;n|YWbm7ZVk7A6>)dH)lp`7=4X?&RYXQpizv5LKI*R>008JJm%8}Hqdj7O4>DocfshQQ2}sq zuMjCRu^_~Mk8pYbxP+;g#pg;}Z+eCm%mwxK?E=!L5^CV(wLHe8c_Lyh^V~!0d5=}0 z%Ea?hQMi>#z&)uC#6@Mg@Sf(HM6r_=`=*V$Sr^DgnsWR`YR5FB3^ax}Scj7)Sj0qWD(6hS>9ZP%s!FcHIxBrD3(4>T3 zYd&Th9zdWDGcPlLT#;C-T+CaDL}?4q{M3KaAG$w`9E6H*ejC6MWnh7CuJTT^QQW2Am+1XFIjV zUgdYw)rq<>{3^JO-7EJj;)e6u1VlqsVIaV>X{)#CgK#h`T-Q8tQuLXt%s2S|*?Gv~ z;9MUY3%*V>706Bx{?aiVC$W|va_$(2=qzipwkRR8UVR$yX!=1@v#UY~$_To_Sea{L zf(pah7>iqGh^7hw3U5-uXgITH;>$7xLui^@e(=HvkzdxiF}ai0<#w+7NS{BE{OT!# zLI7hfO;9-J*U(Yj|N2A&wqA_@)hjP)!4YUdT|U(95%Tf?OeA-x9&U`hg0`cW+E1T) z?ZLB{rLr<7<9jx##0B5}5 z9+@j+wx+PGuGH?K-;fZkA_G1AelhKfm;`r|XEo)jFxdH6*yQZLJ!4gCw zNxR}p*`2u)yl=~ZLsE%!dj z6Q5z&{wZN^`I(C=$nr4b4dZ^qhX)UB6|alQnB1EmC&3STJ&oJ0#JU$${je4N5*Rc< zP%BS30@kLpjgO6Bd2_`x{!^lO8+dVMq*Zpq~EJ#HH1o3G)GjN_=7>7bGw)PzFM8)iwEiXJfRG{boRlzE}DibtZj0Hra zte~4tu3Y=lKgVw(04zKf6vaFb7Bdc+L#+=Xy`KsdwptsD+Bol9$NJyxFpC-%0hF5S zDR-h0!qH_tntCsM(++%)(4TvCLd()cWU8@;z;$<@k>Nfpz#W7n|2}Oi(~d zdHR@1CMedRE^Gr*w*Nw&&^^uq_KkX(th}r^%VO-SdQt1g^4Qqe0sD^1_0b}#NC&N2 zJ@c5gtDZa!8}ll#+GCQX)N2ScbeO@2Y?P>t*7SB{?uc{brj3=PyN!C)+_s^&q&dZ5 zY!sTQ=?@x8Z&8;Zca%=dT^WZvr5V3m*VrA2!3eb^F}{UVj(z4-2Xem#Ogu@zW2cPP z9*grkKjRC(3&XpZYLC&dIq&)%ix96L#Xp4YidQ}@-U;UZL@oEiUGDj7R~~YHO>FM^ zdVGR{B)oI_{GX8g`F$kHmtcpnxjS>+wHI}luCC6X(vjU1;`lP_wfH4-%}OxR4@ zVxiBYI2vZB9j_+`+S}Wcl7sbR(%Sm*25@ZY0IFk1Wr30`ENjKQhP=mU1kb0>5_8}l zYU8IdItbfLM0PY4Uoya%7v&RfB(7ZivJo7-0yoxoQYgjzD+?72GarGwNEA3SShFA8 z3{e90bmDJg+KC>!9Rm^05l(I$_nz_Ir3x#QtiKh1nNP;RMoaXFNUkyLYCDlyaj4Zf zar1cU5l4Lb=foHT@K@0JhKDU(wp>bDN>7X?0aN=_+58(R`w$BKvur#bmRE45RPn9T|f@Nlnay6~n+NMjbmC7xn}NjpV)h^z1BLv5>0+IHVg=<5R;I+>iY66@V!lgOkk}3)U8S+`utG5 zpDSm8A17>yvs%TZ=$_nlS68uyk2cM?K$#yLp3NaG0zOZ)M*M_>??Zi1(zuP?p6JV! z`Rg4$wRt0>ZhmccA4K}ih8MWrUVv}d{Aky^47|g$U!Yu^cGr!12Br>{zvwt4_8?VJ z${R#zR)3%ftY9?U-}$}iv?dT72za;w44?chTQ5WuwNx4>gPs=#c<1Wg^bFWuWBwnb zfyH+6NBF?2Yb~~5rrd+Bf`G@^=g2wtpc1#em8VoRY@-%Y&=3TSpzxTqIcR2OsZ;=C z{z?+klFUS|itwY*5B8CvCBSq*Mq)U7Ee`(Ezw<;niG$JMk|}3kV9>X02OFr}4#@!I z%YXR`+O3;%h8zB_?%Lj;D|Qi8@qo<@`y;#H<~R>$Lj=Bj!{+#gK(O(;mpTC!zzf6s z4Rq%E`R{1A`QPUn1P%DY4~|Ey!tst)nGGEAJXDQr5wSBSM)J`-`owP=&*yQ^I4rw6 z#1`?4>$1;TZy19egg~nQvWl0m>BxdPTYbEYzoMmQpJIP1f3zk04Zc>&z{%i1&*ydL z{WLRueTp7@yofrT#c}eg)pNhPiE7SflvF7=tmTvxF!{#Mw`E*84>97yj{iCV?t-3x zt0r5+9(~l8Tt9i^cm5Zh4xsYXxPc~$)Ods)(5UOAr4@!3D#Xx8l3t@O$a!L0*xp*2yC2 zoWUkiFVbs7h9_bdLDYt3GF8&E1m-tY_Jdq47@g{vr0G(6CHQK`(_$!bHu|FB^m^;W zDiZ^n*H{bIIQ)M0P&`J($$K`vs8+*yH_pt+h??kvfM5qpF(PH~=^g;KF*OdcGsk$Hvx08tGL2KLg+2@%W)gWQ}@ljk729vqp?J8hNjBs!etUpUQRZ!(w-v? zff(9ld{I;j9ada=64A~;q5)dVXVpZ5P#1lgi3s1$h@6zH`G~;l;+3GU6^)=|N!n*X zJxfhXQxwZ`i^ha{eJt%|MzN4iw>(!~;RB)~4coSp9Nxa~H+B5^k|Z6(M&?L%F~VR` zm$4fIDch}tItDfh)41&zlim<&vl{VYxPn$&0wXJ%rCTcT!< zkE0^?@~-^lj63bZ{N`$R9S1@l0y!o*JI2F|Jje~?ho~Y%0l|BJW`EKULEd$#>`4jA z`79@iv>AqIw$XYF_x;-i96<>8btI9zAsTTVJnFYGREP);YJ(eLUcj${75Ab@3=>)9 z*ctYRF4u#y><2Npx!C6b1A1rG}UWf<0H99m5attJsOXPMaXpaZo=T_9xx6FVG zZr~LFG#S~Hh)X>))8FRvOyym~HKq1#?O!AShz>(AwU3))J6_wCG7|Z-s)T9;ODp~2 zJ^LcfuNYDA@@KOyEuXc6OP}z4O`K*4cUtndd*b}NLj?&n5+aZWAI8G(_T_quBUA6K zC6q#Smko`9BUQs!J3D%#?|6X$H3=zusEv({IC2320hcc`w~;Cn>>Pr7cp`amnYH!w zK1{FEoB|@EPM3c2Oz#K4qSD@4FlW){cGT7q^yzr}*tLAV8boK8;mar@Bmz?6^ZX>o zOuC-(&{in<-qNq%k)aSAVKfdhv$tn}Y@)Brf~!yN>*%`djGZYcb;qS-M2XlweZt=5 z@z`|Z?y6$uW0GqvQZ_ZPvEhDOm=y3SYOUq0gNd{)(tV?k(7K{-NlR}8WFZW8hqA!X zFrT4C=whZyJvdHrEOU^}`T*(cX1Q-6waR&1t;~wA(l++Wkd6|}^{{n&vQR_OBn@R-o9&Qm z{gbcR(cr)XaqwB6G{jDvam)B1EAEi7#vGsR@hFI=BK zGnUag;`iLpHNVDR>Gkt)v#ceG4j%xwa&bqxvU|pye5Nr}@4z1B<5mlU(8Lip<$H~E zPum1u=5`^;%`Ne{iMZ8+4J+NZ_=CQ@(}h#@=F%jlEyX~)(cR|JOf|vH0M^}YU9}T> zG08v@>QoQ&t8YHK4}ZJQJSec~$#+z<$x7pdMLoB$70)={(dfH5LyJ6N0ySJ8W?<1ipL%k=2V{@j3MW$Tb6{nNiI0G!JV4)sw?d} z@zMQUODRnC8=NCWFlb{_EnV}Not1FQg&~FaQ`+Zi$WM)*VdHQ_ShP~aAlkU=v@O@! zd*=(Hl-6Er^0#ol;L1s5mv7&vKc{8zJ1GZA zG!NuFao^rIeM$elv{D`5+Dr?uf4oX%Js%XTjX&(os*mM*aUX5ri1o_yFRr0=hA{1v zOoy?a%jEFo+K})4e)KW(O*4X=?|A&i@LQkO*UO;J5kWqr+81_VI$xEZmYB$LEpc{U z=26p`x9!-z8)?UFO3#{C`U*RTZ|2#z@*wIFg1#ruu~c$0;<(#~pR|^cqV&$~@anR*fGhJd z$|5fbl8K(B-Vr5|L);OEh<8hSvSf1lB{QqL*Vn6^>P~wg&ob&d4sihd6v;d9W$}#| z69Y1`DD8Xa>_RtE zFiwhzrxUk$+}_cV#I302gS=uRQ>&BuK=5M4^WK@!oFhfc{lk^DoAjsCbN9#P^^i9Y zB#=?6EzmvF^Mqyy1PsoAEJv+tKF-ePw04}M@+ClPMgu4f2|45rzUJERPs%hA3iAk) zK1`-nB+SSEO;{Pu9sgd8j;_fMa_8g-fwh07XjEX8)Zdwt5^t^!yCL+qzTHT~&Lrtn ziH=k?bCj`Gp3c&xXDR@|Y|os&@D;d+4NW>kLL1U)R50UlvalLr2%ai)YEHj-q0I_q zX>DKh9Ee{>5kRo}2L|%4-nHfqfFuda)?ob1Ap$)r;O@z zW4zn`9$wEuB-P71>DPxr&t6^z4xlHg17c{Ii(~o8^>|e^>a>=ABx;%2YzNZo%zNB? zO@;P$f1lVr1N^w+c4i@kk@_7xd8|~)KYz1%tO*Jcg&lTBLUq`Ux$kj2T@ALY(BLI` z3AH-Y;q_K71Xo9v(#be6FqDfpSHxkcpd zS}m0gr<;#a6~)A=nQr0VqZsH)gTz;^;d?h#1eb5KAv&*5FGq8oy+SjlVI3fOAD(MI zeD%W;Y*Z-gJZkh~{jmA%W93Ur9^yX7RKz$NHdcjUGv)|Z7F5FaWqY15jx-`pwBDqo zG*nDqhI!l6_1AcNDvjikk;LWdbF~w$cys(K)Wy}iB>Qy3@F3>VV4L<2n#bJvb%ml2 zU^6z=2qB)-E_ncj>qUQ9B8g*m?h2_HK7s&zs5o5vMp!^OWt~RF)t?dXY_ams7gugk| z{0+G-!q8nq@dcyHtacdA)stj-HHg5Y+fHx!0n!(9+Z17w9w|EC>CICM@2m4DD)W_f z4-(yB^K{27+9-;)*ZkcM)0kNMqO3&%Z~dG4dMstYyQsu$sZ1X;THfx@;Pc!Lgrq?H zAICiVn04YEg&{ek_dha=wBBe^YiW-=4@)C9ML2BfddW1u>#0tYi94Q@)~jS9mwGcv z3$#k=anH<su4{f-Of$gSrwd4?Wx?dvGzlngI#g_ z8xIWz_>g$AJP~24FY2`nHU_$2d|&~0j$WCor2fUN6E-!pp&^oY^BaT*C_){if))jo zob$0HL&Wy@Mo(AJaJQOlFVo7b7KW>8gzl85-K+v*SEVyZmIepU>*-s@c1M$n#5$JM zppLpX-dt$@`V8p-t=>oWg6%-T11G^mLR#^Z7}am-Bv@1zE+ z?0Gxk*;Y}DDB<)DFM;*>aN?q+EUdui*946@)=eI6PdthTp3Cp679Uve>w8ar@~K&?%cs=<^v! zq|djp;Fif4_;-Ds_`sOo#HPzr+O-gk`3YWo+C~8yAh0U6*e+A(o-a&aGLDFy60SQj zplxUXz`K)WlN_%JwX8Ps*WT=mjv)wh`aIeo-AbEmtrdE z=z4~IMCw+y#c#5&3C~u7C!EB1`!J93@oY3tdM?$+9ZS80o3Ij7G|~7@eJ&Z8256$# zXcA~`NOH{Gg$3H|Ub(exvjbdA=n+o8H&uT%BZ-O^a5Rf*Z#8~4;_z|QUg7=wh#)R~zhlHeuyyG*JydoW-h z;y)+QNe8z}H$3}#mqD_j3pk$i3A<_BTczCfX_L!^jQ-qn_vvqtN!T6+0q7tcf~{oRybx4x`v_SzXL90e@{y>k-9hYutwqj(NA zSf{yDBeg>%%7>0En_OSirb9KC9M%?VTqAa5^b<-4s~-Aark&kZ(welN1;RUve@+=r zr)^6#&r2+xDtySUnOxGLkntNJvuaEaS`V1sje0*l#>EW3n7gK2!uodCNl3DY+W1F~ zDP{cid6trVj(qqJXC9vH{))2n0fYPWi&`hPiH}|HW|cz4@W{6CCat_qbq2!wM|jl1237i$8m^MVI;f zT{$1%ip;fKe|0^2rt!hjM_nnO_QzjvR9M__HIuHKsa@*YDZ&X_M5U=}<#=deh9{;} zJjSb9EX0plslstFt<>}V zo)7)U?KJ2fTS2hqRs98OD|GrjhHZi#*wpSoQ_T=`oRHhEV-o7^p~9s~FmnM=y!uhh z^JSS@oba;=shcq=<9Q(#E<;G(rA`M2zi@`KPRVA8`i0`u#n1T8@sO95g~t=dEZ|RRgHfWY<;k_rk=E8;UQd-d|)_1)DbLZ?OLb zg{*#}^j^Ev7GY>v+xLI@8*d5{_(K~6v_rBqP!U9l!m(jjQd*y%Ae%|By6jNxOHj~c zg^M|cb1KKXdV04S$-Llel*1QTY1Z18Rt}_SFR2DZ1u;ZgMIJ1U-ep@J(U~7S=4)W_ z#17}zV&qX0eQ+x^1$Fx!iXrug!evMzUtsdRCXEQ7^!^Uns2jTb$3tlgiH-GdePoR2q!>yo|1PDFbya2VoD63<~ zn$O^3$5maq+#=*X<*6l&+mv$vBYXvLIXk3*8`4bIg|#d-uUS#q zU&_5+!Ht35GcV{C@I)$`eYrK_yD*Mg^{6;{dNX0T6MY&3bHh*`Ss2Q$NHhPLkeBOI z#%wJasFaxEr^+wgFQfeu1+Npti#yM=W@THO7Qs%wNEt^ZHlzwOXI{frc2Xh3Mk8be zzkD~3C5zcg+^>w3l4kRUR7fi#XZgi`Y5p|fsm{G-XS=9LhgfRH#qk{a?zZ-VSwluy zri+S51N%Pj?U6s*pMHh-R98|l&%E{ew#=x%Gs_t}aH07Z$K>!sARw6{uFgwaeVbvd zTrXV^8ECoqUuz*V21W);w-jeg04?vb3a89>KryX0e2>SR1JQ=NC|o11g?Bsyhc6lH z#6^FtXWSObleiocEJD^A6viaTn=gJ8*|tWOZ#ve_)(tZ> z+sb{(OH9Np!j&Vu*Ci0#dX4z??P8J#;k`Cii2X^jFxX9bt%_IUfF-yq?BtUb3S!7+ ziaI10Lw`6yt+H_9Mt*CTbCkDcMZxa$1&Doxnas659se~S1jv@$Y=noc~&4od^z;o%|m}wmgK8;V%`g~Pb)pHZwK$!i$D8J~T#(I4^*yoD3GTI82UztKFGswti0{>*xL!ISbIC5oF2!~BKitWvLtE?on**Ou7x`(d)iD;<*6;*|E~ zi0eI<*e~m9y$cv-c{ILx&I1Way5NwjrucKC=pYoTTFjS;nuD69oz{Kb-q{D}$Q^;d zd@*uvX2j?7%u~%Ef}GC5VCkq!arCdQqzrCpSJ)>~?DP|HR3PECtYaLTG^*ijAsRkT z6w*`Sfkx5GPDAd2^Okhf#U{G-z!XgkzliEX89&GtK(W4ex9Yk{nv`e&E5pW*jePx7 zjf7otF;}!M;nNE7u}I7@(e%Q`+izrMZ0t3Zcu&`=_C)*C%CxGvlKrm-(mOqgM>b6{ zaObO-%21uikY%mujSXTtM_F;j*aeH{t%j;IXRCe?=&CarXyGSR>1htO-wkL6512oJ z`5*(NS`*`A!rXYz?<<*++ZRh3W22BYqK*lM+bUxV<|F;My+l1Q1_wl}zQhbQyOU09 zizEg|BEn+=?DRg+Dol40jkOL7BPg})b??UQZZNY^ZfbHXDJ$#9!_0qD!w$=$h5R(9 zo~9WAalh)D-U{9_y)pZSj1hoaebpyqqb&ECq4{kLJkH$T9V><+oAF8I1KKPr&C>4e znV6+TMw0GV;gFQl7`D$&M-G-SYfy9ZcR(Z4PS!y^)|Hl&Mc%WusXuU6_$%1YBDL6| zGK(J@v(pM|5t=R72tHK!Gg%O6hwmXP6Tjxd&YZYD-|R8_F*myYblcG51gyz;EG^9n z(DB$WY4%`s=M!t9x)*jsvNd!xD!*upv~rs)f2moMPf3joKTRe^Wem4TDXez3=1L&* zY%Z~|+v0Swl61$IO{L}aG(M)PmIk#?V(GOckS&+TRBm>5+3}hEylz^S7|@z!`v3?G z7?0^tt}XLyfZfvVCFnp(3%cHc`U%CfSM#X1h1gv=(Wsy1@Id?Nyr&X=PQ5F!h=SCG zYVVBL=C?tN=3L%-gu4?$!T=8^x=gpRuvBsv3~ef9hF-}5)G|omAlE~X&5@JB3NpM@ zXdp^?7}U4En^xjLhCsd@vId;=&;W0saw@%+bSsy@p$v9L%vtnrKKl_I*q1cJD7?U)N-I6 z0`V;6%gxg5c=zd1Zx4su8g3fc8ds?Z(vWG#H#fTiG1o>LtLm4c^W>>0YhOC4b{6xX zFVC2UZ2cqeaZDi)xJ~NyzxRbrdi%@E=qd?e!Y>y4RVVv@?M=!`M>rE^0!QsuUz~9v zX5Q81WvnHffE-fK_1or^r1M-3rv5`SA_uBY5Uw=Wi}vGIjD#s+iH|!YeX8ZdeKz)S z-S6=aVI?i;mlQUdaTX-^yZ2kxV)kMLI5nwvI1!gnNQn$RT$>Lca@>M^v~>*wFD0}r z(2cXdj_;8W&E?T}s10FQk_U2#uc2+72T$&j4a1V>p6L{f37-4&g(c)kHnfodRvC;ML>07V zwgyxc^QksSD6-a$1Jt$#V`UkP%pIb3}@Xz|1o@p30qeji7 zlf-xd?ru69MAmjC{&Zad}J#gy)=B{&pg2P+Mcw=H{r-+b!svTLz=KC^k zz?V`VEbTYD#+>UETa(kiq;y@-w>$$5=XMxok}-7s;Sk(VW(D{st1C$5hwRub6^waI z^Y6xzUjcug`JF{n7(m~*VHgxyQzrcKTsB9rM6fVI15kynQ?r|ZO!7Q)x@+)@8%&&< z=jzzPNL6`Bk|;WLG%R`KFd@t6-TRzRH2w{3?>l`5Jn02PjvH0S@fa!@R$W~$b z@`I%Etp9gf=^~UlYcdE#48fy~VPmNl{lU3NguEevxDIqYTML`mic{8z`hHuvI&{)$ zQW0=~j;rq$c!d*+fdbTVZ5_x6b&($04GzQ2oQA;cXKVQQG)Zp8l84lDUNga>o<2er zn|2@{Fuuppve4En#aCRpQ*Isnty-X^)z?h-(CPMdk~~M6f6GS^ORE~*@nh@xtMNOc zjGdOU8V6cZqVs&ekKHrA*9B>OTDR>dGzcz0fqj}qh+P7Tiq+XiS*kx<^M6MBw_O^6 zz-;QsAptjL@TtY)8PFI5y+h(<7SV_%UgUoiHZK6FR#%%QFHOSCe<}9=ORg%-?6uPZ zy&yR7WcM-#Ka{(R+RYUD`0i4j-mWAbPK?cei{$^4UHH2df&-`0_`9X4HmufYMT#fM zfOo+Sh!%9I?&dw0zAQL#^RZ>x^+X?Ctpw-c)nN-KGkosOdz7sqy{zm>`V zjq>-KEu;GlrmJnrsMnOg*fvWx@P&e89<~J)trrnF$cx!}J{;k0?9Q>2j}d;o#emM52@lgmyu)%?Xiw-gethjl0;At+X&%~=J}L(>;p?nE>SU9ub}pV{wQ zRt%>}%+s9`5^}sD-%&NlSr$~NnN9ss#$J=Z#aLQyII1-Rz+rV&r!huMF|Wdikgd}^ zcK=tBG5l_-^QTCQEsq2EI{<*OJ(0WU-3y0%&lL&~8!HFF@+Bj@_SWT36}4bhl6R%T z4-!o)71U}L|NVfMA^-auczLeiJV$nTyd7T))v$tFK63>yNWr08T@@-pyK%X*U@94t z0`1R`vHq zA~sFhkru}@;g3*40co&fNq2z_<>TU_pV;$C(_wkgsiFfaYRFsu-8f=15fPETg0^68 zjb(V((~4NX?q*CeE*ZWvL+GX`A9?gti!{*50Ce{DE-3M367KQ^vmVTkj*lOG z&Um~%dxjhkS`Mb`>giEKTKFLB_7U5Qvvdi>*bI#p78ax_NogbP=c>=rE9})7;G~Q} zO5ErBx{^f;vPZdQCj#%|gM+}OLvLS0JTxA+H^wOkNGnY-$ISRl z>1QTmTm~F@@l59H!bQU0)1T_IStoz9@EVf9(oBFCu+sTP~x@@+& zA(GZTLABu&VJ8HisZjkaOzuE~w=cSu0s&-iEbZ&H=K}bF-wy9A@C4o5=cUN8PHF*O za##{WiNUWolY_$~i0Q1?$TRcb^ecAyv{Q9x_^;(M(V63N<+T-w0&GG~PiFx%K#i(H z;d>wnMGPiG8jl6+$nDLZ0b9+_3B0+tP_`0jYlSvTzOA2q{f}F#CgO|uqgNLU!&`0C zAs`JotLA^m5I4$ocAB(fa~pb0xP#;J$faXLu8d3=fLVvD+gX>W=LOGW5wD~I{1wvA zQFC2e@)ozlY{b3gnJvz8=W{E{@&e1+?5A5VxL$r-p1&>E_|nRDQ4?(G#d^* z?W{(TW83d%D@39ynF~G&su_kHNK+@!k=81gfZ5VymhIHBwr4KJ%^}XT@=D2+7)(C| z2D}8HhOYX^JecL*5*(!0v8tKW4bN!>fm)k!sZD7eixlw^PV>?Ts7_ZI9Pz?P!*=o! zGlEdf=SqFAlj3fm?l%Ah0atQY3pZxMQknvaA$$w0Ll_;_wt-_OrlzVaj8u z1hY>n>qj1y_?$Yil?J9A(Gqvo02!~JGY*MNgj}84~%Sx zr`lfF@Z;!_1dl4TDG!i$RXh7rD<<-j@vDZReiWGg(M-WU$*3#!g){k>dG!P-l1;`k z3n_B|<8}spgHvs&w6yd9rK+hBkL1({KX<^nbQNVsa0w#L$LQ8g(ijnz_aq0p&Y{w4 zf^rx9h909&zfgi>3iekk&Y_%qFI|aD-x5q(I@+q*ywbzRdzWgn3A!=0$??@ujAuE) zNM)BI@6|(&3k70R(;NPenMqu<92!6`C*Y>>nSxrc+i*LhTK=cYUtBsKeG|l|A^Q)ULeTx z72`K7wE$r9##E29m#$*4l8?5>#>N6LhYQtqzkQR|)5Th0iB$Qi5#0WZJfu<7@s$_s zeLWV6#F66^l@ij&<=lvS>SWNrmM;rj5lLi3Rm*bz-lJzOyB(joMZUtk^9iEk7f*ez z3cGbHG5W?2z=Erm54M>-Z9CN&aOUo0OEhB0Q33@->E+9uH5oha=AjWU5GD3J%r7w2 z*95_7O?NXrTtP%_A{Ugl@8~*VPeZh2*T2n;Yg4?j;Lt9EYf`MWn6C>}Asuq3)83D7 z)1=+9F3mVkTVEb>XIvVuV-@f)LV){R6M3v(!u?b@C*mjkBFiJ#k?vy3N!|<@)+)R~ zkNg#$u%XI`4wj9+p0BOGRbEdS+S{#pd@%Y<7_ASPaKCFhpVhDc8?VO>w&%w+PK5ue z4v@S#30ZF=LM?b&hzlysE}$Du;zY2}bkIBX`E!I&K`+nVpOkeGsAvh(JTkrB5@+Z2 z)7$-~88Hb2h+ z%sqmq6P~$CB>AZw2;#Z7RjnQV{DV9H#^N=+jpV6C!%UGnw-_JH*g=;MQr4Gm-@f$; z*-x9_El`_QKb$!7&dL))TrIVP}zqOZ(AS-whGMnAEf`0oz1}+a3pV5rY8LNDz>zdd6 z%Q!Et#(tIEx8RxtkoY7OgT_!dZ(f(PKyX4h6)6vq%zVK%a9L5ho~CVeykPqz+X~&ZX z>W~8B>?paPq24L?2@#>owzuv7<-Gh2DDSzk3R{ZWKifZw1&zu;>2BAryykrTmxo6b zvDz1Bp?9?Ey^CbZFSZ1zdiXs}#oUW6V_pAo;DHjv`w%A8PS-m~eqyvQv%LJ~A5lOc z$(vO1By^;jVSv}}h-Ks2v(>lU+%yKuA|!F6i7%Yle}+p1Tdc0p zr}Stl36d57tfM3Rau15Urzo26ZFv*^<$ubNci}KV8oW~@md5-dr4m)n(M|c&vl3PH z$TF&fdx(Xa3pR&4Lb#GS{@I7SGd7>aFNw}ekZVk0R^oYE^A_f`X{r6Cb;nc3y_WSW znkS3H-0d{ga#OzeTLl;6lyFB2t_jOm)Le)$hs`+8;>&&aA`bg$eP+TTdE>^LioJL% zeRhbi$Ap&F*g;25~i;A)azrV#n&G-cjR9!g`02GXH4|6=*As#>?`O%!Et?0=(! zT6w(}$`7(LXaCWgN>%fEll){--v&zM_JC8VP8e>2?Hj%{sc&s1D`_!N*&8M~IF&k~mY(K^eu7GYFh%)tuZcF)25ciDoW#bk(6O$}OhI+2a(er)jwURIc zrDzIQ;gEbXU-Hgv0fVpJ57`au zx>xI|(kzKrGY9R?L)mjO|2l?NB_HQUGOxBIXv`AT%q|{SG2GwRjZz%P-=U2_$#*6q z4-F5O_`o5ypJ!RwnE5xYoBRw1b>SI-3DOB18sU_k$KWD`Msjj8D>DQTdGmAo2-|0F zk=3E*~m44S6EBW z86<0Q8*8JC-_Q(lek$6_Kdp(V&$%1TQO>P#4VZA^DJdg>8+H$N ziwlpZJdZ@EbJxu_uzB?Fz@U}v`&!+__UdXZ>^WrMo#jB;sP!xGTVVne;(4rQHR#s{ z{5)TPwlBr68{a{24_f3>vwKf58N8e4=>5-EBU2I@0$ONx)7nitt zI7TUR&-$6BtjsP*H|=59NL`-V%?(J?!QRuv#9&`|iWKRa2f)I|0~HjoNgI0%)Q>S4 z80iu7!{&VXECboOxp7Xht+{+4Z&rSB{Lhx$VYI$j4VO%^X?h3D8#sM3_=6YVt;h^h zIisDyPd(gUTR8wqXR#SFEs6ms#EfQfvZDz5rbyEz@q4mkW{vtp`2O`s9 z$4eOF2Z=0Q1`+BYkMJuq;h9j}S=XleJpcC4>XgIOx@0ZZo14qbjz~!?Uzmi=HMAhxSyV*%Gbp{A6>x6=r%d$mNdTKGT>?Iy%Or zcZIba5a6FP;We1vJvpg$TjK$->;-kG4QDKsh}r#9Bf?@2eq7nq*$hA6W#NSyl>vbV z)_SpO8>jOe=NxMxP~I@*q$(6{a~%QwD$p>7X8X}}Z_wrfYVQbqW}E3(dtORW9XrLOS12~F@&XW19*jaNm5A_eWQ%MJVbdzgH@|7s!#q8*4wh%~- zUf44u?)%3O?eelRL!abx9(EqgZb&(31G^xZUp(fcZ}vSsFiVkET#;l5@bD=E8P(Bk zg7bgY5O*33?~0*;LHG3Ia2(y@7CAZ!k7Q{b?`Hc;9CL^C~?f#O`eoT%?AV{)h;?ETDTJuF|7ZLc?G7 zZS3dWFJ=m-+SGck-K|vGO}H`o);|QO&saDNyh^eWX0jg|E9Tj|r-?uxOBv)VDh7Hj z4JC5-wBXVZ>VK?Vv~~N1wyToomm5$vJ4}C%zEx;+srd zUHcPJl$l(`>)KyX-j&gY(zI_m-f21Rjt@jW@Yu4$m1`!|lI>UFE~CMRwE>-YwF50U z$a~L)@vR~RN+0A>qV4}d-YU6Z(Wv6%ymB%Ny z{}9vnT3xH_K8DgT;^acN3lgRc{THKr@P<(P5h$W51jAyh8`CF~vUv29{Gp1xdHZd? zV)ri|OR>9_B0l)hlcQvgw_&05t2HYg5K7GJa>@jQJ8R7!485H+TesLa2{$Sjm7M^3 zUPS!vKVAO_ z$EU9Jy~k21d^NNd>b1lB`f94}`?>wA1L%nu*Kymo`(0gORHOAtO=Zvnm}2?v2KdF} zFW&Wg@q9*b62M#smXwq%E-WO5QeFSzVqE$&PY9UMdGh9!TL0(bnkoiY?fY}ayP(9y z+$2(@QyopmReV|c*bc98hamnU5NLWildjs&E)Y7fD^(Y*+L%z=Kj_fK8x11)-+yHG zBF5 zJ9|kkM%~-P-<8OZdiDCXf5ffi#J7R&LatYng$lubI)Ol7JW!>*!*1I-2nZHfHBAXK z)3M_~a8y-FYd?!STlk0jZY*LO4GX`=J8g_jN=+R#sY{;ccfKX@v4y_k0~Y8*@F1S- zKw@A3-hw!5D}mSXN_ZjdP}=26rCs*;_IG)ostA`-%)T?AULj!5Z!bbxQux$2>|VhCSQVqsr39=q z5%=bq1HPISzueU*5qXTB!&{``AvsonE4s+PbIzG5VBgaDixPAWk;zuf3tCku(!OE( zuK?gMMsOf5O0R9XeoXA-MShRCo)EEN|3jW}aNbhkrHn0)rhlsnqe<7ifKuF`&!p|) z))#Op-6{Fa3@)yNN)Z!7S#MZGSh(0#r@TF>5XgU=ygMT)Ir4jtLx;Nx?@Id>KQ?j7 zV(oa(o2t=l$l?8Ku*J9cn32o&45^%vaf*iLFXOn=P8J;Q&1B+%^sztXc*dn@04pJN z0?>#e$zm<>E&yAEKjYI(3k%EX;sy5Y=Dox3@;j3qAu+=|qXPJiv4HD)zw>Xex$&L= z2-JdzVMPX{-0f%yM-}~BL>H$;e2FPhK;WSA)*h@tq4*)w{?q$$OegLjPnk*!e^Iqd z#Sm&3b+o&W%5qdq!#cTI!CdeP}#jO%r+3cc~3-tAD z{GuZ+x1*_DIn&kf?V9Dq_c8NOhRC?rPR^+!{ALZu`53SoRh=Cq*>@q-A>6x)HxRK4-@x)zA8oI5ZkLe6wP>{PH5PR*%^G zDe{AP0DrNif~yTZWsXAL#D3YH*45AztLXD)3j*}yfqq0qJb8swYc7mBFG3}Kr|?PZ za*Wk}mFZ~xkUpsY4$cAa^FB$qh!{2nC1`|R1vaRz+?vL;D@2a)3%p&g8~8E`sAznb zFVzm!6lHe&_P8UbU2g%srxoyZ=$$Dl68~B!|>;8sLJtZ`=s~3rIosi&y=ZmXDv!!7XSZyLTDRg4f zTjYSg9`wj=f!IK(%;y3i^?0 zRn7FM%`S`}$z%)(0rdTZgoJI!d80kDr@=wl^OYjOuPDj)45S)NT3^eLq3J;`7snuo zQl^P#)kQEPB0M4-O{Dpu{!52Y`;tFKneY6~kLn31>wt-#e&7+UZa9s83{&au0Uz(` zc%;uu%+bh+dbp;t66?WYy^UnID?3&hYl^)$VF-?X4RegH=%G#`_tO_%tQERIz2>yp zxVpyrNeNx3^lX}l$b2<|Q>*#ax5inYk*zHgH)$V1&I*L&FoRx_x5IoDVk^H_iZq&6 z!H;^;vO-R>*_IU!`w?pt=zKWuKNjwfXYgUePp<5aZK8@VU3VN9VrV#R{!Dz?f4M62<3IFl2V+6bitkIqJ{OCZ4<6KVdE;yfxr zTbKf@;OUEHyjbG+Z7G}g*E4eTN00f_s|$t2@IJ!Mbm}N$z2xYnoC;5NHq`hrFJoIm zOJ3yFFyeFWDAVrZ;i=@r0MtQ}O&10`EfF+%g^#3BduWVtLO=O#i$9Xua-r-M`)BGEysBVTuSxqL-3; zKc^zYsm``II03vSRLi7lxoYj*PVRrn^tRno{y{dOiurA_ekwG{UqV9180JDHNmi!T z9PL2mo;On&Rjk{xp&bjn;%1f|YyX)GOv)fQ;H(tgRmzSFuJy`dI?%l*)@X5{h(6Aj ze1j-!JQZd-&nSA|!cgcC>H5_OdKcx21I+*whCiMyac-K?{hsy0j?_m~&F0h%arLDe zyNWtD`cWSBIT7a&Eb6hpi{9CKJAT6#`Vsh3Ckp@#LI%bp#RGkLY4LV_mTl86sFHpJ z({HU68tZrQ%X#oi4Gi{YFO2*>(ZBYR)}!l#)uC9Bb2>s-+Ba1d<%b5#wbxVkrFU2A zO$%LxwV(f34jc%= zA$O8Cm6Q#>@{)L~xuc7>8lD_vq>w(9HYKgu?nYyCTrc^i-%cgE<8EsfDzkX>yttSW zbJW$PujjgfCm2|5vZYd;nL)_O$;nzh5jONjO~*tY%9COjc3~}o`mSOgIx1uYBmDMr z*!YFD@ZEZ;$oqscPvg5@(H77Eej2dewl`g3Q{Z}l3$l>r&aEciH%FWK>?!(-!c2mD zZSsJZzTG}F9A1Daehq55Wsh}Gsa+Nxr>>G~N*M3J>CI21bY(*!*t&-pzYop{12U>C zCB1+DepAxcwq{a zacAfT`5-p!fv`%Y?Dk3(YoawZg#kAG7}1VT}eE|`>UT`Yz&rf zjgcc25wD44Lo#nYi_W(};DTt^KLzHbE8Nt}T3?6TH+ho@T6Y-mfn^=79&A}Dh(26# zjfCZHjuId_J}po<%wwhAW_X}<2Gt=uSKcBZ^bRUH+L|8u$Yl=2kG8*MHq^~sv^yq@ zBfOS+FQgl`RZ^Xf1}o}a@$10M!h&VG)lNKq?&TG#nhxdeu zI|ITMXf467DIA(DB4@qTtZ6iM=BUAl2Uby=3<#pc!X7)8vh2m8#}Mm6ul(pzFQO(1 z+Pw-1;bhWmt4`Fb_Ul8OCp?yu=8PNLb4lI*Ii0NZg#2I!=-$%U-B{V_EgWvhsv|14 z)+ALre0&V3k*G-eJ`4Mjo!f@SC)2}HTO>ZV@1(z1-(J=E@}(TvwJ~a^UHWlgec`=VkbU?xgWVMqj%iB59q9-0?*+dAJ5jB!fF3=E zd5CqMGTq=mg00S;Mss{yp$ro%9c1RNFRUDi7pf#s^29Nbn%yAP;j(j`1 z#(3>)ij2fOhERV4{<2rE!vBaUIuA)ZVT8BwmQectFSfn{sLifv8+Uh#mr~q|ODIL! zLa`S2Qrz8Li?_I2fwpMTpus6_#ogT{KuGeZPy4*@`_Ftc_hd3j?%YTA>|T4FJ-Y<0 z+?1E+ui3LdeH)SS_T1w@URX!O0`WaVlt&ZN{6osW+UY{q4)9z$3ykY{LX+mJOlz!i!PN&&5wy zg{IGkD5>L&OfXCKs9wvl{&3PQiW$e-U?HX-x*thJmu}zqfy1~QH?owO?Zw`M7P7(^ zK&jbREt*y=sa1Fkp3)@{f3qa|*y}lpFEs^Ca|HN(M}4wjxqKZy?)}4#3zMAl<&9 z9O4EWiL0pA{k`{>Y>8SrV~ul+XNrEX9SP^WrMF9j;4dFBjB>UElfVDoW4q6g`6XBp zowC{%iY*g#Dt})j)K-);KTi7L8O1YsEA9ygIl0GwGxldcLb0|YG9&GCv=Jzj8qa%x ze|vt;<@ih&$ePwTCg8aHPl}GQ&j>ou^3|eu4jT$q?^KeRDfa01qgzJR4Oa-WBi6th zgNCo9jZN&h&U89yUt>FrK4TfM;eTMhU{}FBUAkLxp`qk5@Vprgizob<>D%Hhu}hT0 zYbZ(+0vMD^-Dx~s8S4!t%1ep#iHX{wSr<@11oA{HdcO=BCn+HA0+Y%P&!Bbf{Y)He z$}kiaq0>65ur#Sp-Vl5wL+td5ton zG2&^Pf1^LY##9%@J0nBIy?;WHIJ3#5${LT@Bfc7&%CC(IZxvRTrjL=^LR5IiT!f?~ zl(s}NzeWm{kh7N`b7Vhxd@9OLi01aN9YJ2O(ZQybw#@JSIvEAxt+)TP$lkK`0Z;M8 z??Uepl1;Pt*ym2KU^j2YlSK@0_GFsAVB_~Xb|@6E+4@f^xrwkf%3?nU-2A4X*XBvQ z-Z9u!&%F5lgisCZAo45o74B|c_W(=c!Qotq$oF1rhC0astwlE%?Ay^lAShQZs3e$w z^2Xya=zZC|mj;S-qa})DO14of13#Lrh{mF;Z2Uhoj=wA-zAMj9jc4baIY>>KEw2+b z+(#IZKPBYE{LZ0DlXLwMx(GiS+6|_l>%^xad3x+I5)WOXQgI#JMpnvE)kyRk-_zBE z+u~@yQ4WEC@sHYNxwvWEA5r#ACSa9*pxQ+1S2H_oEAG1ZYf5ceoRL-rT*?Zq;1v+f z{>DwXZCQoe{uW~w!xNKrfVA+V!W&5AN$(Ss9M-3_C3UZ*-ut=xDHlfc;HMBzKst{M zk_izT*1;b?cIvTs#amDN_S_&45zaI%{QASIJ1o0{>+2&3z=w6^cXa)RKw{h7D1>-d zOiB#N_bFEOc)z0LZXU=_y8LGI@ozNXRf6^if7;nSAgPT1rrOY~iLCMhs_w)A-hnXI;oVZwjs@(G?&&i8-W6;Sq3bmXOv%V}&UMSa8E z#f3|3616ryKK{1Z{x3f86H8W`f813?ghWpK@ErA*4I)6^;17o0bod&rD;m&YbFFwE zQ}Oa7|19E8ootP6rdSs*PJmFhe*2O*sd~EDnDF|u{%2$=3}zGnP1A;y z$Y%qDOaN6t<2%-4uPXanlii>q^!;Ip?hK>5k0$Nj{Du^Y(s6w)S;<~0z+bA4G z3nrcqUsufu3rm5F9lx%2V~cPiq~szhiWM(oD~RreT8VJ&y627?@eF331iQMOTmdFy z_nH$+iRK(nO-N@EVd86|q$Z#Cg3G_nHa|U0w=yu)pUoupZo91e-0x@RMmH}c<%96ZguI|F? zTIgRvLms@O^plFO2v@y$<+9U^T1ie!iP{cpsslDhvY2k9J=c|W6lz7;z?@^p#DFHY z&cW=fOq#g4zA+6EHQJxtlSwg29?DCOFL-RCXdbl@*pK$6W+To&_qSu$|4 z`1+_7^dW~qddwYL_Ev?q3(!)z`XN{g=L=vQ%SV@n97|#y7Eb&aAWq|EKae&GFcuVs^*m zED0$AVOz`$#0fIqA$d2i7y?7l{3czO5QA^xh&Fke#QoOr95S&$41v;}hYdq9Ynf_R zn<0D{b{AYl`Qnk$r|iMvtZyPxhk9>EKu*W9zh+S@d~VoZxotnYcK@y#aV4kn9k=DP zR~}23oc%MJiqdl748G%9Unl3kajA$Dp?icZhu@#Ah~mezG1q}0CoS^_2R0sX7<3%T z$p2bXD#dV-u$?(Z30^^Y-}`BK+(;mv*H*s=>anuOb6ts@t%cIy1gOYsJ@p+!v(o>} z*aCeVMoIzL_H&q4>Bo+-N9lS#yjEt`>n%r*W;%&mb{>@i@5IRtQd9Y9$RbJ4tI_~- zlCQaS*cnWkTy5V|CUK=NR^m-?yL{M)^N={@T@JlEuc#))JV~o=nx{}decPUG3*vc7 zB0fqQDf5x&W)Zb@;l=aRi<|-}=#mrx#rYjH{2GmN4;m!b9zDrQI5-H;k~BDA-L+}1&&txHQ9i9hi}yjSQX1UVezKka@{_#oNB zu_2c&YDoxkbs-!J7;CA>8wGv~|7GJYILzh(xF)Bz$R=wU1)!ohYF3RhlD^hJ>-&U6 z6J;|kB9~TWz*n%WF9Rt_z~AUvN+##V502^@Rp+Miz`ck(pXaVS_4Feu1VjAipo+(Q zbk{)B%g&35X!ih%LBGD)^C##MUh=mKsoge^u3y+0#_GF!y-Qft8P@svyn#&o2)-!OYu>8(I;dg_C)F4I|%7e z*Dw;9@tzIkF(b-jCm!tlLjmVtl!JqV?;lSD1qJ#1_F}%0DsHTyBuy4?u2jbriW@t(Nn)iMyJo^WFKJ!qnAs7 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 dZcy}qdVni_{rcxl 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

i zVlZ8{#4c7Yf|??0UkEPh8$x7Gb$Dnl8$V**9z%-kc-P3paba*2G_0JvzTYQ4cPTjJ&s= zAOhEcXuke2hUfuQAMiS+gQ`_h@0O)4Jr{Xj-fw!^5;Ke@Qg6-FDuaK&c~V2_eKj@D zvv)T|q@A4O*)A_HPner>ZtKg=f~HDBnd?#$pNVoz7u6>OxcLtYUu#hX){-M* zZ!Fr0pFqcc;|g%VyKO$Pwb#O7KjtGm*q^Qp=tHuHppeEP&U1qsh#|XRC1w{ZLxC-V zh6IdvW#i-1OQyw3mAE?r=X}x~nC52eg4$cRQMS(?vmB?4ljY@88@Hv1###yG&qR8P zeQRVcZJb`*CbL$Xd&VlU(^R~ydD)H(oF9$|A$%kucY^NsV*1+j{i+k@X15_u9x&ew zKOAwJd5xn_YqQr*w6T8Miq&ZQoa;)kKDZ?og`dWQ&&mf!4P7ZmheFC>3?{aYC6v-Ehex2AJ23rS^4-T7dz|mj&`NJU19*4Y9z&%3gYi%P! z`UH(jq`Zu8dchR@%~K`t{e+aEX-nLq>l}TO0SvgroXv52-b`6Jw_1N%<$=Br%pV3< zAg#HMMhkV_*MJ0rp+Z2wUOwEedc^4C?qVc)nM{{qAOK%Jy)c#|@Yx%XC!m?0jZ*Qx zRpz_M8Ddh}WnId)n?>QigAk$J`8?Uk_RVc>8+thpCH4qF(pk9s#MQMy532A<5dqqg zdnHS>!G7lB{RLdE;FHLVEBe42Lwg*f zYOFQzsDB7=y<)t}2v?#=55R?tG}#k29QUC+$?wmdQxbE}kqEj8&q|)}hP@riLc0nZ zeUFiGuEmtNd3SI|l_IiKNBrnm1b+^&b~R=-bDJb0tTP9oj8J69R_ zmQ;GC9wmyHRVv!5NwJ{3)8#_t!TW@xoP6PHd-U}gqo=$FT8-nrM@D2?&vnPaAc;?s z_t7x|-1E-t=v?zr<=R&-?OLY!!K#UJ!>M~26sh_GPCYR&^gM>G_`L1hyBt~#ADiE< zo;>zyki0l^3*Mo!T0Qnpc^7a|nia}@+R^V7u#v-3XEVp&2uMG$7i%$3um26{*RPV> z!5L8m(TBj|Z?^>J1gxXHW9z4pEnBZlUSuI`R^Sx%Qwq)|zc!%O^%NXwDGvOLU7> zq_)=bLdqy#MK-a`p2IH;fWto0BgkWWED<%E!j~mneOo2tOe$%qH(?jsBu&hZq@{KH zy}f`7c0`lAl73{?stF1MY?0XRHz?h|)^q{EXhxL8{B8avF5m0D$)H`{S zFE>>5{B1eq#O`F`5{Z2Q75n2PVE=lKzkL72${Mg)ai0k{?&A!~_(7Q)f=idbb#akIi&6-3;q|;|isW{Y%d9V;BbI?in{er5C~F3rE^JA(hTz=%_gftY z<(#MC?0oHBEVNg}G`$dSeSLlG?R$A+sqp(uZwAg@^G~2qAURg9IzBu>!I5#e=7!yS zPchfMcKdAqsnK(j0jh6w|NfvU9k>Wg85>{d2`hJ1LZSI{b27SfqoYDA@{kXJ)JYcv z>Z`%b`dU7zWO8jvxr_9D_OW;*|AR@g%TMpEQ;$2hZ(E%OW)9aAOE5Kf9_)X*CVwzK zF`;Xm=8S=5X3DIb#xHG}dw82`X_2k1(KJepTU)5Bml8sof+uDaWqg1W(8&2*UtjC& z?7eHOGz&Km&zF4wOPjei)Yf>Gw6?ZmJXRI-^r&rLy<)JC4X#1G#VbWwmzBhUT^x2B zP#Uqe;^ab;$56P&L?}Ccc+XHCI}HB?Y?>Vw9ld`JGJZG-GUA?0Px}F4l1PaF%0spw#yT`+8YbpsrSYMgoSFD?WWcMb6o?u2_>%d}o2%aW5 zT3UJF*o!&N9a^3+iMyS_&ClH(gdhjIu7XFeRYW(J?}lT=!F+3n_HZ*#5s9SlE0HFdV4^)K{QX! z%%0_oIBku6`}S=jF4tUF^*Z8IO_+n@T}Q`UfJ%iP#hbf5kK92Q3iK20@MVX~4+C}L zoLWOD|D&T5hnaEe-`Paj1uXLkht3tO$&d1*GwMgbt@ey5#mXo}(h7{B?~^e}eKdcA zk-fy1wz|*--H?9n_d-NNY{I#y{Gc&Wdm5++1Z6bNQmi0?A$vzLe$UcwNvM z3!3zZ4Zn5 zO}~#HZ;qV>M3s>5w=lD?JZW#|cbOf~PN~OtW;GZHX=Jw4zObiFPd_ddX{k(#WMN^^ zhHu`Jec_=5)Q&jnrN!SL-6v1TfP+(BegRZJ+xd<7RON%B(kFe__4|TQ+RKK z$qY`C(b&N=kUD$@R(=iF$ibey37Ms@Z95USz(24|0+;+^evgiN1}a!Rng@#S z32ko|f*I6-Tr6zEqRtxF9@l|ND^ZQTv$(KIDp(*Z$g#HIXad#hW66-W6a;+bHca`+ z`HQHxekQ;UHcZ`|;P6V|wsbKlS>Z&V?A06anz~@hpYbl5%w6*Zh#v(b&qEjSynuZ$ z4)Na*Kgn5u$Vmlyn;dICAn2y`W@pPJQad_#;rDK**rkT&4 zq=^WJ{`ltY3Xg8rX5RO+6i3+ZfB#Ss&%HCb0J2{vU2hGD62s!-n@5Eq0mDzpbJ%e3{^Rz5pnpR&onsh8QG2gE#gkLQ zWmEZl60(q2oOIi9t;~Di=e~&1@g&mkhbOjKfx0^u2)nvsmp$Lj8dw>$s8VhcGA%2b z{_q?b+=A)xKibqrUe>2mNqN8Ir=DkO+~V3=Y+P>c^Ol>ZLOjnqXA1cFbc6eJ;ls^a zzZS!TEn2cyR#!2#*HJ4;hKb;lB;jKOugLN0SObAyb8whtG{It-!sfsK4n#`1TFu;b zBzf9=>5SV;0U7r0P5T*xk&g~$7zbT{WezpOUw_F2bFzLr;=>iDdoPo*JG&E{OV&G3 z=v7h*Ewt%oR=4lZE+s1&>=|h7RQbYiZ?dP5U)L-rx`l06jySi)F=vvw@Wx*vm{8PH zoEtEdpMLJcrJJb?je*8&uO(RTn$b6s$1n{#EfNeb)a{^SN5lRSvM7MrhaXHXIcbG_ zA^fZB=6_vGZ3qI(rG0*#f*b$&XJuQm!NYY~T7lP4{`EEa&!0U*7aAhsPDn_o>+Vju z$0&7^ZOIMK`-lvLH>pYRAAk@J?jp6j0E0xFZ>g*Mm$(|l6q0FFv4x1u8R4>%A3fI(?ViP0T# z$u|@Lv`g!DadyrF;8$Ar>P-|p`Qzw39857WpAEV#ZP(Y-d-`4T-VW zDtCGOx%eBP@pstJW-uI_6$d4J@=ks4FDemH8OmWa(d(^B)kxl3hcX%MJ!#fbgSi-jTfVzmVxy0InQwAHud4Ci)V4N@ zxHB-^-5v`2?Y^$j2LbME3cQQ>`)@|}3dMYx2V47V`3hVLTb4)0$|s$x=ny6iFcJUp zn^@n4)a!W)5p<#>yOK>UHFN8h-hJBRQgY1FFNg3JBC*9ltdh%fW;y4Z(8XOM&IdkU z06*lB0)caANGwn^_XI6DDE>vAVtZgIH*TDn2w|_kfgc9Zh%tSFLqN`j>k2jxUgJAI z7?_L`0@r`{-;1{uvFT0>6LZIumwt)&U1Yo3@|z#HbC-JTQLHFfd^qGP$YE5y2W;pr zZt6?eg1zeLC3{Njy*XZOY#R9QmYt#X+H6Z?rY@IwUjl*la>X@VZ6l+V<3km6+%UywlG0Fc7IZ(Zkwe80q|Cn~epFC4GHXxG_ednY?)bGjCB zOcaa}O&Mv-S8d=n(lbsIa&J18Mp$*)tsG2=dsL_EqI9x?dZS9~?B;Kz3kG>c)>YyE zyP7{E6l!3(;=h-G0`U`^o?)X?>}5#pZ%1c zIP|)B+N46poMD=Tgyf-^*ax4|_X#~Lk`XT^I{M8JuaC{!XnLVO~+=5DPJCak#1pMIyR}yZ&=JyqM=C|Z_>kyGBN)Wq5Qv_?h+2J znDZXa*6zp09lR&F{8MP@293VxoqC8C z69o53D;uQ)0njkG#hR6Je;gys-Ri{2$fEC*v8>O%KR@@cbKG9CgeXuc1W?DNkmUjQ z(*NxJ9lJk5Vij~7C^Z&sc!EDd<^~$46zC3n43ze<8C4=XTZ)fAK?`^j9 zDcqV8Csa(StuQnax)a})Z_LQZ$e}xNxUG806%q9mxZAAp0$FRY1nNszeJPS?dsg+g zM?S!+Mx!@I0(eyn?<+rZtWOd_Fw4?u{PRjw{ee#gAyj!O;=C8R7atJ0`ZR~=bYTT+ zLRA6BAD*FY+IRbK(V%ektQV8PVN_Z<+>60!%xgW*BNwUb^R08xDd>cQii zB9e0=bMl-)K90;mFKadoc|n)+mE_RYYQvCneOOH}tDC#G_mmF@b^t^-=(@w26<~+6LWob@jB5rcO@HfGwLg%_0wI z%Yu__AO+~mgZdq6^m+(8xundCUqb2^3s`ACMJrE zvY)RrmA~l;tE}@(Yjlop zt1t>TUfOpL`b^MT6zIYUtd*G(QLojHo3GU2o-N5!0BlUN*Tu$qgRI~ zCnxKfXV;Pc+=PQT>G~s3<1dYa))t>#VG;?h_|_LC)#JcWu3(=y0t?5rjoUw#l(sJt zoz^xU1P8|hzvb$Nkh&$5s*@S4rJ3Nt_wb=Uh?H}>+`h+@)d8vp5>`G#jPWqwu=nD8 zR>;kwbgy#xP33j{(#q;{$zfXBG$7UHi{QoNugD2(W8(=j0C)hWf&TbW6MU4;2;hzP z?}eZY4AU>6sK}IeW(Xh6ywbx8$D|n?A)%VUyreOJx^mP4M{^j*dqE$70W5>;*DupI zusAbc!zxfU!f5IGHhBTOVID`|dqNB3Q4A~HrF7^bsCqEiZg$tLqTSnFa`h4AO;bDv zH@uUXCz5|FiXjl<@rU^aF3|MPzbqKOGZTO~am{u^{4>KRP-@EtNHEmS!-SM*!GyD(X;d)s@o}y*m z%+tf~|Dn*@5$t}mRK3{))R>t&q4tnD^}gdf&xhV|^T1%m;jN1rrCmbuM=m4;B>4Z( z`JS6V!d?WsfQYZ_X&cd43b9zklBrsc-(`axtHC2HJkFju(ek zhJT(9mQAIb^gFQFO?Z&~xcxBEA8xrPM&o-}a$AaDz%wH;@u{xvt^k;X;^Y>0MiK^5(EJUgyVZ!5@9Qf0;hR-V^jCj)rN3{x%(y;U zA2-w%_f&daVnh7b@`@f*7)&0+9%&H#*SBcBM>%{07O))u2F)89Rc19sUkLJ!9j2^F5qXGokqxn4AANN18Ffl2e%z2ZVx$nV6 z+!Y|rm-T4wQj@$JKB%y zjn=kEqRxd?h@hQE| zi2E%9ya=4@t0euG?QJyA4auzkvHgLlLkk~5hJB?chhZI$G;6ForH6kj^^Bd}=K@Jl zeEy%erURFrXyeu1;r+uifOO(aSyU#ay?T0mev&a$(zQ)u0XYbgl?wW{d++d@&515F zJxJHoR53trv`%nyu2yG~17I>@goJ8;zoYIRil*#lvi$w zu94uhf%nm)mlQa}b1xMBUZ?(>eK-wQ@bD%an62-v@rayAp41=9lusVrALqNe9s37^ z|7rcX(Udoh@acS|ii>QA!%h~Tu(n>41f5UIh?2-E5B07X8|ugfBU_b6Ms&{;Ci}`t zOW~DcGRxvIZS7t6UUG}TqwgN+$F zcc+naG7NTHspR&wOK)h^G;D7TIU;>owPEjJTuH=&JGS6xnbEIem&g0*! zp3%Lfnx1-qDo9if^PJT;FyN0cF*8$|n3%|GjDPxddx9b|Wz>Q-=)-pFiD3Gh{X5Oa z>3t4YzLCEpE7!*W{I|f)U=HReH8Bht1X#z39>?7B0K0E#~4q^?>BgKmbazd ziabU8B9#;s)j;)uoP`Ai0aEWP)|UkZ?-Jm0;ceMPp{qD{F9A&p$J5zR0K#Eqt&&~! z_2DYeXgl@IRf9TJk%^J$9*SHp`&)$p4=9TA{e47+l-4!oWthJK@Jb_OvIGcAy^{n3 zQd21;J}dLDh}$X?VMx>F{ot89xNqN|@(5toaWd znNS7l5;>ceb4;THhLIq!KJ#uXYGvgGMn#zb_cL(md?PrOjLp&P2RMp-;WUn29EV_j z*~I61JFNrEN#n7nJEMXLGIqK~oM^p+)SKjQ6?oa(F7@V4?i0@;K^8mnay%AC`b6;t z7KfK-5n%N2CQ?oxY+9b=(ggvXnJ3MLl2;m}fZg}{bc?mO?M3LL?+iV&uJZ7x?&fdE znfs#bM5`Q5zTkCm^vhxgC7`zKgwpr(YaGNPug}7r?xHat%76!_n(shXMgopD@K5Ho zzh-M2{R+*yJ~-n_&pO!G)Im3PL!7^#V;5P*Ev9km{gyZUGfws*(>|X#7H3zS9Hd*S zJ|6WP?39Snp_F)uH+S~!#PHRt0>>B5uVSJOzb+(xzKJ~4oW%_eSr*;u$6FMTq1MPt zV*Tj6r`R7q!F)#uDrS?bT<%!(5$LIwT*FgSxzUrr0P;9!TdWa3(d<4|T7$|Qxw48% zY1+v4i(1SEIfZNO>B-EaU3`uPV=CyJ9cGqJ_4aKcXm^E&4r7Jmnpn9(K~j?j+`!PV zR3!hIeNl};>kT1T>qsxNjwjTVXhn8;vd7Qz=1?1e<6;`zEE*fht1`f~#7I@{c(G&Ymh_vVdHaE;&wmm_#YfhpK&lUr)$>%fZN=g%*o`gt4o zRu|%(*03gdNoNOa3aj(q^kkRB^g5ErYD_I&fzWWl=cBae7QB;&>rMy9%b#e#WaP;n zYht`|at0PeI*u#!05}oFo3m4&xfd+H?z?b$DlvAeaq(jg>6!7^>=UMX)f{D3SCDFc z^HHI_o#_+E&!W)>M<;695e>CU{%n??+G?-;EhaBD2eZ^KvB!0l7=Sog>&^(1)JrNIx$h>vECid7tqmGCtuUB@n~nc zTkCB{d%q1-lAu-xjt`#RC77Yd-42P47K6Au*mTMLTzNXn6f9Bp!bNX`z)R`sUZf%( zCR@S$i6Eav(`V0p634^aVZXi++kAWGc@W7hT^v%D_=JOBEZzTPOLcE^Os~X%xq+-K zhRM}iwrkDC!L9%1vc!MYFcGfj=EnI^G1)EeMC9=ofje)i>TdCk)zkZl`Y$7ISXR}a zNgIrrplL-D9O)ajEe?Z8J87Ak{g5{F3vh8+(Mw=VoQKKGG!>na(SD^&$yvg#Ut-)R zNFF9XWyJmaG^Hrk4;t16Sv81NA|997C-+tF7TVh|Nmn-ROW9E8xWp+GrhjP(?7HE9-sS5!JJ{k< z^^O}@?kNP^V@rKGY5qJn^Un~%eV2gtsxHD#J1tj+pO86_9Xs^%4Se*KOji&(-|bhr zrk!4L`b4Mjn`WQtrtG!PAQ?oD*=}MH!mH|f_~xBb(a$wrq`yjZl^lDvMbag$>V&ji z@<|8NRdWW-6zOtoyh71DDXht`q8JZBk;{Vohh_}IeTf;%_wfBk1Z~2{bdVMKi<54J zdp2r~QZ(2<-TH4E=w9en8T;*^X}=Y&WM@sysBEX>FBG)`rbn zqmhXjJCx^ZDT@wG=NTfum8Gs4iR)hd(CKY4pobbYMcDPH+UaZ@2(;#9xV2`}@_`g< z?Q{J94`FW|6;=C%4NFLM*L9sSX(BY%4jesmaRr)ZzY;FtX zT$Z4#ng=hQ=L1V}EgI@8M_6!V)N|m?d5oB=7DF_J$QMvKGFNmUDd2p#{o?abns5lo zOFennXc~#EUxrHZNP%rVo*E04e9M!L^9c_{SjDDE@YPtus3fezdKDbAe28Wio6q4o zH=4JR;1$X0dWR~tp7lEE_GHasyxxLvmE@^r@C>I&Xt7bP%9 z7X{t4>?h26=+HZAuBGUk#*iuXv662|kMlM*)t05lpM7BAdq#ciwl&r46N$Q~)l-SV z6TCg0C#xY}lA2P_qc>HN(G0gbjUuw#>dLbm(h(gA6cH{_v^YBP2Y(2pzQ6JQdWB_l z_{;`me?Jhmw63ViZBg8Qu`$8EFlLkBpaYquzI?}~UKkD(EF&KuR8)1#u;V6|@-#g0 z_|!7&s9GFt6jq6=<1JH&Wa+;6C18dD1<627IzvY&9aUIw^`n_8&U&bZxk{nd{(+iGgLk1-9-Hk4=}wQ%?`_v$5}c?`OSMRv=|&1 zvqKUgTfMsVPMFjIzbv=5ms)Ewev3H)StV-JgC_+|?6>EJ+#H z?-o3mrned$hOp2J8dGKs37jxoN;GDrdG3&vYDVVT&!sCtrX1*d-|XKUnT^-@=$O5u zERA-s6?*Hu^3MAv*bA(h2d0XjBBc~`#)>9GWX)eMOeF$|IL_9BB4v{<0D9zBxf#21 z7B9o<1*Bv~=Eq;ozOU>r*3&hR+2-5VvX|Hze?J4`aFO4kk_}>{~ehR|^VPzYGcM)xpYu}t&QGXpRiWweAu@Ck+D!NF_S?D*x4l!z#$e_bq#IxD2%_xP>{ zpXg{r*`u$^qYoAQfyc)VFIeMg;OB38IWCC1)P8$&HQJxl4zKEsnX(AD8T1vnYpF@9 z|3YY%-#>Qc?Ce~kDe)1kX~Q2ax@IY`90e~fD^sGKEuTbiMa6x;TF_kgy(TvdKx&V- z`VbmAA3S{HvB&3{aTzmmie2fEBF`L^m!cVKcNHRy4O||?OBDU#lB~$Hy)7;8)833k z4Gqbo`qh!V$U1c|yWlMCXFm6*$Vre6 z0tc4hvtAWg&lm_1mu^0spI!M$1jO;^Xu`r{b?gfgZBM^z2sMSonmvBDyK*sqvV~1-q|oh znv3n5<0fZm&#PSzxVFwhvHAOxI?87E{dq}`g(Eto-x-=KTzLwvXE9XxaDj8|%3kw~ zzdczX>=DeLbH9D@ql?v2*Rr;cBPaW%$!C{0z7CS;TicY!i~YBL-XqaES(wWp%BDJ& zM_9EwsN&WucR|l?{j)21^S;f4lN3}lywMq5D+iT4O;?RdZ7g$bn2(QwpMStc4U*1Q zVShvcncNVsl*yK8M0+wTO4$!j+3BfJ=-y4o-)05Zm~QHM)!KGrG#$^8d*2DVtih8= zGfQQ950ze?EZlb3Fq3cFkYAm{y+mzZ$pG6YxWIOOIqLu5>NN>;x5Xl<{fnM3(ud(> zcMpKrZn$3`^{VuqQSKn(4RzOw-6pK9w~oQK!I;N|dhlPe@Pfkijg$Im{(hT=D!dba zzb5#!x}-KT+J&tRyb51@#XVxzb%QxF|Bc{>(?2errAl^7wM-*^-P()uA!FkLec6lx z!>9g@>!g>~!xe=!4ds^yUYG0Gd|-EV&rLHOxS&IODUz!FXbPmQqWeQ$pHUie?xa~`k7+1 ze)&)mMg6&fdo15cms5YM^jkysdDhF-#4~y-8dTeFO>&LyCd(ju|G2{d4r7nt{(RoK* zMVoxw7WwMo07oGvjqj)1{R@i?;(c}&AzjD9a_y-Gj_rAu*LPzC+ooMN)OOKMsKn|iJs(UbQ2(3Xf zyOGVBA8B%|Nch;NRE)$pf zuw>GjM>15l>A+IMI5e|=Fx_-x#RMbTv}Lk#FqGg{@(*p$&!3KpJ?ydtwsdDsA-l_4HDGk;;xy$ z%MB~0c787`E`Z9kxLb^-cDu(*60DF-I8SM5Wr>)mB(LpX+fJ)(&E#Q5lXC-p2obDO zgG?!I{ZCHP<`l_){+)l7H?Ao>(yWUo{kVN9^!M8%#e6xNTS<}JtjKxgV( z7I$O0+>--mA8B@{yS&%*NbR;Bkvbj6MQ=-zYbY!~U&+TZ-g5Qq`K@2VF`j(mWbya$ zUy%#LgQ!RA3p_f7B>5aQaXs2Q@i|@>c~|Tn@A-ziF^}qP(*Zq7liq z8DKNEvGQy$+FZy50wPECykv{gS0c@U;)h3Jh znWsB_cs=Hoy#CMKh}yyTP<3?;Xxx%}I8346Oq#7;&$-+gI@hMqs31r$DcP9_T4&q1 z6r_BdzuTN7K=*pD>iK6Mu%uTQu7R^?-iQ!~%E*mXUw`D{?z9k!?!6t<5}W8*BM)v1=MbE?aSX zRzQNb7`5?D1($bwJc>X(_wzG)PjF+Autxfkd}Q_`wA?Avm5y*VxjhXs)@Ju=L!(-e8PwNS)~^>BFsz^{bw(x z*ySrv?iAjGx9{AFCRQn%UC|%6ODWR6IbR*o-k=~7$5WzIaG5NEz#24aAwN*%@1O-uD$ofDecGA`-*o)_ONxe(m3;TdYSMfKl@0>eQ8uEMTNRx*+1;&QD1ubfwM~Ap3Jo85frYOArOEjD zW|<~40PDzlY9}1O1tc5=!?E!*sOBNzxH_xU{x7>_rA85DA6`JAT!PZHcmLV#L%%fP%GhMf48CGw_-N4E7k?7 z6ANyOjy51kR;1UXxwr$ZsnQp#AO>-Bg0n`)4-Zg{7}W9%0w&qc zq+4j>87d=x=<;km{7w<{Xd+ZjV5RYMnMOHI-UQ1nmWgZ)4`VnE>MgyR2B-vQB_^*z zxJ2A%`7>_JJ(mP{i7BG4Ch;tNf7CPMaeMg!DX{f&i`HV#e2{;=ls2mt~*(=HK2JciG&aXL@Z4!%o2uqshjyhO~O1 z4Z1T=UZ^rcpsPG)t1>>SR(ir9P|jsRBIfh^@bMPK{qawuy1$sO9kl2MLyL!D_(R;f z0>eYbsBxUY(3!ZA2{xV|wW+ZTN<$Bl_{W(% zzzWBbi_%XYc?ZK)i`_%&lhvP-0pTuZHv}L=7hG5a_WWPv3P?3uo4f%m z%#MW~BuQ84;vrzSkR*Y2b(T*bip&2g(Q)fHQ%5<6=Tl>CH+Jn((bZ?fDCnrEVruvm zDFjLcaby`3Bcy~&e>de23_&A{YNcfr1j*3cwp5B#iqFW*3&AHE7#yEYr5C%Fd+I7s z^J@PE6+t7!(%v}ol#WUYdhF)>?!>T}ZjL`w+cy%f9sUE7rhSiih~hr=D&W9je7Ygl z6XEV9O>8$8ucXNwlb7E$wEIy!n>5~{;ZJI??S{3qks%s2+woP(gDIO|^M^;$VyFN3 zp~a6Kzvh<#)HW*|i8J|TaXYq zj>fOrY{t8o*HYrz!ez=#VZ=81{w(q7ggha!(|-*l zTbTeD2#1FbkdTTNtO&CvrlqNJ3Z0Qb4ev1h4kmm{A&@+uTW2DuF6^uS#jc0I?R4H| z#K4e8@{`lxz;9v-;5x1{_abD8UVp1$v^yrqcpm)TB>s7i{Dng}DrXy#H`LiJNYlrXDb&w7GD^$JjuNTfB%V zEg-!;!Jrnle`4r4PyWX25WC#UgcD1bp^}e1a*WG)qDgt8U)V(0uX#fUkr!q7oizoJ zv&ly6ji6v~L@KqCBW-z$_>LsNbol4!mFEVF#*&Hu#Et)Ji~yv78^mk17!e+x9Y4l( zrTv11CI3^*!SNaMei3Y&chnD0SQ<~%5wp8TO7m>*^QFV}sOiSk!las(7Uq@L^n)Nt z##f&28~`G&_IA6p8c0PX)N)Ot9Sve*Lv7QjOYU!t+j9~r@? z5coicbUMp(Jp;PT8XC{LUj+Z)9&S|vy7>9gx)}m)`IHsy5)~7G@RwFIHPtHk0qQ){ zh$6WfocqX9EQ{tT0ga09F#1DG_+n72<@V513W4JNXBK);1KMf=9l}!<(hMqNLcoiM zadRXGFr>fwj=x!Q?z&w-d>iE3uHy5;dkQ;J?tFd4`i zrJVqARPjuOTcOj;yH>kd6}Tr=5Uj9B5w^wxWz2Q;*hSmqExcDEnO*TDDu^Ilv%>dIUmZf^aF zAPr3r@YR!3iZG_gv6rlIE@n{1{@{-cJ98;zwY=YCU`|Qa?2MCi0MC4HI!>vq^QEI# zgF$>pdOo<(=*aC0dgG+Gp)rG%^G!`|(sn(=xr`0AnOWb~1D7Q0)zj9T9CeMC_f)z{ zvB0b&PpE5+n!dhbU!Tul?&fkxNO#w80TvJ)<{3NuMD9DgtgKdAdU~v%OE3LC_-Re_ z2ajb6kF{+{Oz7B2+a$?tuMKiR=VV!?`fs+lpgw0@Iwhbx#Di;Sk{z*z&%;@<^Hlkd z<8?o#K9kF#ZhyFnU^rJ`Td0ZeaN`j*M(D7wZRA?FtZ;}V(Q-*h zNGJ`M3q_$rhWtEoa!X|ffz8c5rrWaMr5a9x%w34HM#N$mk& z;Kp-J6Me_P(xp=~)Kqk7*Ovi!R$m3%0QwfIkWiwzvarhFOIy9Lw?@Ll9L~i>nbphQ zG(^PmnS1QZzUBK=s!OTE#=9NA$6nYuJP|$zfJQpIr=O$k-@<2RhtV)>_86XE9~h@~ zht_1%5yC1)UIZ}J_Q1qN^DeeM9)sm6Z5j3-Ui%K&1+Ao{X33tXDr6ew57W=t%PmVl z(us{V+l&qcI`*~q7S5thks!>E+SF>%W%6H)bhg3J@u}b`Fwhpvyct|@Qhv1vL`OE% z>ljK>A~Vh!n0vN7Ob>HGRvV-aU6|QTF$K8C9f=R{6rv)lTA399E;;(BEMq_zs*cTY z#V^G}Bh+%cV2C1G^5_WFo~l(Cw~ol?pl!!(S%134&tl#nnq4K8f}k58&GvbD`#dm@ zBS4^tgWy`!lP?A`(b+i!J_bVm1C&}mOx<_D;a>rV0Z^~Rt4RQ~I+c!@j*07HhxV!< zHUoCzLx9=$Rg6^F{wnwbglIZ{PJpKx!L6fq9 z7Qr$sv26FZoii#7l@ED1j{g_pUPjPSQO9EhBq_j0|A*Iz47QvBef?-|p6)+B#dk#i zMV*gn5JyM$-vRvp7%{WiiLeaNlEJYJMi-vae|10W%7Y|6qMc3J+DxIX{@)1bDEO9s z=&04C8AXv{q3D`kW;_6us!pU-4ILFzKD)F@WnvTKQE1RM9rn_j|5`8pBP{+s0jFYg zbW@9C808~s*4CwY@rMeJKp32eDH;ya{^_sSJImH{<5JK1Js)Q+*j*^(+5YE5?0yzY z@a~cQpYQx5axVsY9jXQpyW4>t!lvkco_GYE<2iPv$>Sbq=dfYwaw?3{>b&y%Q)+7I z6YD}`QPxmFS64Ye{1T;jmCd=jO1g1coQCKPYIm4xkah_B^l4QGwW}>C>-CeYy8B^7rPK>MdH9M&FZQtb-Mm!3muNwpw*~^_Hhm9s1j=XzvnE6n; z1n2Gc3CRJV3@{+5MBvKFR!>b$U9}EAdJ5gCo&khH6mlPv1Rg+JVr<_zt}Z;c0ht|6Gob3L1r%ixs6%a~)1!)52**{aS0;$}Ssr7Crw~Q$RdCG4mtf5&N)RXk#E{)9YCf50 zDsgyGhLk4Lths}sYv0N7IGl52VhSk^tiZ>eO9jX4v$WZ=S)MA!X~I4lo4JY(*|Ib~ zU#E4uQFucuW^IW8lZM9F?m7@T=Lmq#P43Q) zfk#-{?(i^YzJ{4v(x=+mC+h109vgeev={R6FSKul)X%;!tN=L*tgx`Z_V96*7F#`m z2K2(Zr#KM;Kn{^l0jaV)VVMnkGJ_(Z@BN*cmd4pHDk_@Q-=7bLOQVTQH`I7Iq_W&O z^L&#i$~e-2o`pB zMt=@z;0gP~fwGtN;$`B=ow@m1aoehOT;R%zaIWXvdQ#l8Z3qVkM^!eD{@Jjc)K6Id z)r20T)>xREdlps4Y9Y%2GKit}T)d#1*ak|_jf5$JFw17yK7eO1mL5ZYi4mS(a_h@i z=4xAGF5SwP>jNMLu+a!02Y|`o^d|%SYtWZ1s;? z8lRRDnd3){cw7KO%vTa@rb0M!Jmzn{mACIXZ;=70T}+lVAM%{p&b8@mPv2E?m>va( zFZihaDoEt~kIU9V1s)?KCykuneuz07OZMNrKNQHgT1JPZyAPu?X_^uz3=W>qQ1f_@!(9EvhfQG1{OL? z5D11r>M`FV6@t#9@Dn4bQ#EiGE)km>W^6#&A2(Yl9qC_4gKSn$;Ua83n(sYMo-Hrx zONcFsJlF27T)xQci@pGj_BsTb?qXr4Pj`NPfu68OWVrMbesLGk1RQ$x zt7!(@U0g4B$&|Ivo#uRC%?hdy3hy|oFK{UIuedYcx%>rZt9+|yyS*|!}uj6 zK7O{a+MUmkSn#h8zgH1GnsxZId(eZ&DHnx7#9RT zN&}1SGAUU%z=yqm4h2ve><$Gq7^ZQt&X3v-EarC?$8y8%5+CfP@p_x61DXVU)bCJb z<_fG((N|*BU#5a4-SH%2-B5StM_$PtfDMbX1oBdxA~oMUc^5w(UCZEj2h8N8}t_F;8&f4fe@#HnP}B|~*OA+^BZ zc4`wTMD~WQsDq}UtR-Gy;Kj~DM(k0Lq0gAxLLNa$c5z}v#6VQVeI^W?3KktIbf|+^ zY=@5ceywf+D!&a1{>rQ=xb(;W%u4<~o@e|sP^w&OjU)jcYssTFV-+8GH6AM(&CbC0 z^OfCIHombTq*co%7k>}W^OloQzMjI~;koPQm#1OI!aYtR{KWwkBxqdG{N=TOs(}Ay zQPF1=;YeL$*HvlO4MQ!af_2{jVCjx@0(%bIIOr`wCfpH}s6|%Grg5ey*c>@XfFSNJ&F}l=b%3$=O@u z8!>h2=l4uO%jGr0@#*n=3l>BFTh?0tBNc#t!f+zDRT{0n)6^#U0evv@wR#bNuICyc z_{J_QlqLk~_NEm#Q@m>J;kXpj70hp~OG-)#zHQ)IV}R&GN{>9(;B^_SZ@jzcw%|2s zB6q>VZOlW-!?96VMJ!2tlr#LXB}BcWW5krl2g&p2T3MYk)uM*36uWXN1#SU5`3>J# zUTD`8m$#j}UTGsr4`1=)Y|JLyo?S@v_pyzKvKW;z7*q+I9rtlGx^9ulzI_pE^H(J?<=3J>RAn6T|K7C!2rFW~mFlp{@l9ql=|++S*aX*MB4!CPFB+FBc1SDGT#a`#J*dF%^H>*k95veo#XAa7n> zWjo<$>bKvRRLJt8)GrXx^OZq|qs%yT2$K1CZ1eOI^JwL(Zj~sdOnbgEK)K%{|9Bb}ErIA&x7+IFi@tGo( z+&mea3648}aHbN_^yiI$%_M_aI%LY~Pk<0)V6khV^M^!9d7Dwua40NtSVV7iCObNK z$Y7dyNhxXHt4LM7r-s^B;O6p*iK2A6%H(Bxw(fq-B`xLIG`@}oI0r5$ez3Y|0D^2j z7x`=cI(`F<(5c@RF;ssejQ;}#0dG;$#adG*x@?3Fez9c&T77lt@6W`$YGRg>W`8^$ zN-tC-BOoxp(vnHJyp)O1?jaWO&*dsR*5PjVq+YEYQ4_Y=&f_E{po|q@>|$M3ONjnb zO?a@wNpF}5?cQcK4(LvKnt$7RdpoyQemh;7|FMRouD2@aGtX=%5Gs4lFtnL)g$5!! z8(w!#D3!df)qu9bG@v}@pThq*w)O!Dkb{~Ton1p|X~}3!Ym{e8mPLM*dL$ZU!P5KO zle#K@*UD7k?w&Um9N)#igDcqaC~bI0?9^%y(;a6u!8Q^Z*&%l-WTL5Gp#~Kdddxh* zk-^Q?U^x=?zh?uN8zmW|{D;I078Z?(Iv^5=H~6PW;O~UDBd_TEHvSXf_aw}vKv-Wa zH;FqA2^&8=M0?!etG?x7a~~{ znwC)JauN-q5w;~km1j%t1^XpALu<7#84T>eW{SY_Ay6whi<0#3PQzte{sx0UYJTl9tc%4ssvYR1g!)HGwQ`_3lZk+0TWr6M< zcHTGFU2A1iz1HS5zyUr!+6Sv94^c;3vWr+K3&)7ut;vE54almSrF$K>j+ZxgW7`Ub z#}7D@u6p1W2=nwR$}ZJ*qgg{HcL=I}e|>Ov;kXdX z;F!gA#w!1@cA?kW7zVVP{22nyAhQjZnrvq`dcd|EQ0e&6+$-VL(?>SoMt^w;lN=>B zJlx7c?a8|VtA3cmRe*lQB;CZbktJ*)KxFEDwrAztdL9C)txY5(YEJDjt4!DS^-Z5` z05rk~*{WHrdnq))`t%?SDIs|8%l@2y=jY&H(Wg(IJV^_@WBtF?B9*NKJ2){` zS69bjHpwJb{QHY4m^3Mj@YJGOCd+!Xp-ujPWE*IXas1K7?8^Io)`|kP)n?zxN_*FN z%cIkwx2nFFL8o$og6Hp(hW*z&@G9oirwbG<)+O27Tx1z5WbtbP#?2$Ka0LM~4!2aH z{&CGkl?O4iH5MMKqsOn)Casg~nc)o}nENh5FFOAu6EvG0XuUN@4!-G55*+vJa&)b= zOROqVNXW>@^MBmDH9DTTROR%VSr%m6xEw8r&EOVjd`bWOdEz9C>ddw&P+N{e^>vnb z1ce^%v8-5x(Fp&V%Br-2YJ-V{7)xR=^dTnrd*dZ`R;xpafF5%k%z9gb25LA|6!mE9 zuQi8UrdooHy+(A5GRxY)QwVV@yNj!JgBfn_ni8Kg`%AAWeh}D5`k-oUsw;drYi=|> zK_}n9@g(QGfvi_@+WmQ@5%jFnelkjrP9=;zfSnzZJ$_6jOxeq?7mrE#s3)4-Jbfui zm6tHxb?!TqbA{#IRHmyi8xw2Qg$o#L&f%uE%~oa7h1JFq7FU;~x_-q3upLC#Qw%Nk zSk~)av9gZ75u{1)-oyN&SyGVu$f??gZHZBTD?X2789Biah zX1u>w8ZG+jcD~V%z%6!$Ntj`7D)sqQ6aO?oct`D+aq~alG^<%V5#Ov& zAzcl!R9v?lkA?&tEX643@PDGukvE_=DvjX&0|0DeSe)Ku?prT1o>EWQ@?6(@(&Bf! zQ{o-^Fl&2SZ};2R^>1O#M++(3S>;XVZ|*?^kMWtEz{@4iC}hK1imdeIrprA~5!&^AVrzUt zJdy}4YUh~VnF#}5+gflyNmfQeku!hh_6rAxy&CU@+N73NJ=}o&?qE+qc%e@@EAwQt zBI@Rf-PykD>C>cASnCf~@T=;)S704fJVkWOwpWU8{!)JWhSB3OS1Y$E?Rkk<>Z zXYHJ%glMoR3BTffAv*V)vU+2f2vg%uWsUxqFw)cI;K1~*vHXB)Zpv2(*+I_~WXc{K?^|N7e zf!WF!o}$j^aYBsx-mt&z_Z;2muSQkg+{%KRmfpW7VmEJRIhcn$nl9VSJ8{jh5EfIt zDZcgRe8Ti0Q_m>g+6E5Q7dI$1>nm=MDe5&o1jB#O>Wq5T6pegjWYg9Q8|m#I)TdoF ziox*?XxezQOE}bEl$_2jNr|R05hZM-7(PX_1WPO(|7F<5v2a%#!9T=&L}H`kn!YJ* zp*rPNL&;+lYqeAS?0BAep~Nk-5H4%Xq1E#dYcR$FMm`m@t*)~Qis9j38^pe;TfB!0qF;%Z!fiC>>~F;)G1VuowNOA=RQ9c1MR>F}jmKgt-HL z?)7MWprS=OpzVUSSNbAqSbM zhn%}vOPOnVx=i7`{%!qi0b^K(t&Ml*`3nPb^!JI|wCMO)uBa`6E(Okye|5UykUk4C zV%h+tPCx+*K>T7Iqc^0KLi~Tqa=9%siWi7Qu6>_n_#i$YvY$}td+beM(DNF-)ZRX- zJa}KWWuUTykcYA*sM-dm@cX~di2gQj{)N(JHD#?oe3F^KnwW zj_a7e$Ys~eLTz}@aJPq@1K#jjGARzKUcq`i8Mg3-jVRe;Z5$iX(N$AoKAc{B^Z|`D zIU48n4zFWPD(idnUal&qXjq1j73!|W_Flu%m+U#EDnSWemcu5QmKZ$BWVu1l_lCVx zZw&&fog&aEe~d2^0ejp1vR}M(J7F3OO=&s4WbTi4N#s>IXqIeqPUyX&Pi(HMQO%Ir zX^J*{SRFLnVC17wa|~8&xg8Gl7q%Koj;tk!x^RAn+pNi5qH`v-Tlxh@tEYLHKoWDq zEfS;jXgb;~-??aDikY+h+nRs75+!+*%^3g&bPf9tdAZQomZdq46CAHz7o-yHE6%5l zek5NX>=CX>3Gx;B%SGky7(%52sEepo5I+Yv(Pd(&RIblvNR8pgR?M3-2K6_q&vuvZ z74O>gPuaq!-W5Zk+89x<5CHh}6~Kz@k{3k#Q-qTt)p zRqD}G6~B3)LLnI!#MbD>Uyu#mPQz3)!E1Iyh4msCiqw)6ClvZ|)~;qsN>QhHwk<5p zmn(jVjovJk09#L&ISXHp>lHhl1+Pz8PEn%N?LIHEIAf!CXjD1xs?!P~dIrd4+sJv2 zxlBb-Hpdy+2>TPuQ?Vty!c0mu)yaaosHLJF!#qaOqzh0KY=+oV#J~)dhlR|9a zS>qR8LQ2qspBQ+&-rc>uBcF+S)GTMuJ#y(duH;UZa z8P9EttZ4Z#iqh1NCKGlN$CY3C45BHKF0kGq#+ekI*|#hgjPr(S+Ol(>PGIM5@w+kA zIdz0&xZjA;fU6d&fJ)7sXY!>B2fRsH@T5ul8rP)Exa$c&8OQK>P1WdEreSjzL#A%= zAjj??`1|06y+oy5CZ~hyiSeT3!EfEYu8v=*sseCKGrxa8mt_)HU<(7F1c+M*@0Om! zHIhGe%4G$psk{$Tr44A7Dag%Mk5bYOGM34MmYorhNxM;uQp0|hZtj&BY7g}89gj0} z1Hok~9WPAG8CREETlD3{h?x_ebop72!m;iCZ(g%*q%V|ZO8 zSI~X*9*l0UFp?#=R^L?Q5D7E#-E?cZEL9w@`fxe*SXEtIJkIEY+j_b1@tEixpg_77 zH}*e)a#c!?U91lk$}>}|@*$l$Z`K!vi<2iYn$|AcJ@bEXe%<*x^7c(BDIpCHnf%F% zc7cM|vGEBBuqudRGKX~zlELoJ($TqD)LoRFf6D9A#;cXlkG{VS;9hC%_1899oLO}@ zJ&$ut{%}PZU2mR~mKrTa@AuR#7aj2i;AwJB0)H!dyzz&YvU*zjH}w(kSaCjoKYK+% z*Eg)of!D!Q?|BwhxcFFZoL<@UU+yIW=VMw=-#U4oS|(VSAip(|iwpG;A$(8V3edN z3(ZCta#vHzTHvPd0UQz7fY@Yw*%L!`ZFb6d~?6B=pdr4-DkQnsYot9wXR>;qionDuw)&in zW2DjdM&)DDcq=%F9-W1K26P!YPt?xlZ!DUld}uv$Qz9kkp+%YgLFO4;(J$B_R^QJQ zHvj-=yr;}W5_7CGRs@0r2Iwx{w7q`6?=r{jalF<*u3As;Es0~)!P6Zl{R6`;;Fq3)m{Ht zh`QXm(YSK7KlMEOq^bN{>eJu_y^BfN`v!fWU?qhX&{{M~ONxzNuNtNPmHRJQ^}YYq zUriSq7aq%p5qaBU>qqAq-@nat^?I5o=cxxT{D~ de4UHP{WX81ik}T7n-hzA;kl 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�r-6)nXKI+8N?D(6)ma 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 IDLx7NA6-e)r2qf` literal 0 HcmV?d00001 diff --git a/docs/static/img/chat-input.png b/docs/static/img/chat-input.png new file mode 100644 index 0000000000000000000000000000000000000000..29605c1b1c6357a0306ac7cda8db7f6bfa430c1a GIT binary patch literal 54171 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 xE@z*+cG0X)bkbc`DerSTRz_v{K2wM}Rp0oB`6) literal 0 HcmV?d00001 diff --git a/docs/static/img/drag-and-drop-canvas.png b/docs/static/img/drag-and-drop-canvas.png new file mode 100644 index 0000000000000000000000000000000000000000..e9a0083a79f535c8d3a89441123d1a6ac6544a51 GIT binary patch literal 199514 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
Lj+g+nZ!2E?|T#F?^6tV6!y$7BVi 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
mzrD7G}2O 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

HYyD<9>@-c5%*=gswcYx8Pl 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 N@93(Rsy%r2zW}1vai9PI literal 0 HcmV?d00001 diff --git a/docs/static/img/drag-and-drop-flow.png b/docs/static/img/drag-and-drop-flow.png new file mode 100644 index 0000000000000000000000000000000000000000..3351498b2f32866ce392e9e2c85ba8281e7ebd53 GIT binary patch literal 187938 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%0A7` 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 OF4{Ppt3G@C;r{_fPy|o_ literal 0 HcmV?d00001 diff --git a/docs/static/img/duplicate-space.png b/docs/static/img/duplicate-space.png new file mode 100644 index 0000000000000000000000000000000000000000..fd9cf865e5a6bd9b665cd0fc35c0d2a7d0d4d1ba GIT binary patch literal 271831 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

nQC>lMDV=7s&G*P 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

- ))} - -
-
-
- -
-
- {chatHistory.length > 0 ? ( - chatHistory.map((chat, index) => ( - - )) - ) : ( -
- - 👋{" "} - - Langflow Chat - - -
-
- - Start a conversation and click the agent's thoughts{" "} - - - {" "} - to inspect the chaining process. - -
-
- )} -
-
-
-
- { - setChatValue(value); - if (flowState && chatKey) { - setFlowState((old: FlowState | undefined) => { - let newFlowState = cloneDeep(old!); - newFlowState.input_keys![chatKey] = value; - return newFlowState; - }); - } - }} - inputRef={ref} - /> -
-
-
-
- - - )} - - ); -} diff --git a/src/frontend/src/modals/genericModal/index.tsx b/src/frontend/src/modals/genericModal/index.tsx index 44173057f..e00462218 100644 --- a/src/frontend/src/modals/genericModal/index.tsx +++ b/src/frontend/src/modals/genericModal/index.tsx @@ -6,6 +6,13 @@ import { Badge } from "../../components/ui/badge"; import { Button } from "../../components/ui/button"; import { Textarea } from "../../components/ui/textarea"; import { + BUG_ALERT, + PROMPT_ERROR_ALERT, + PROMPT_SUCCESS_ALERT, + TEMP_NOTICE_ALERT, +} from "../../constants/alerts_constants"; +import { + EDIT_TEXT_PLACEHOLDER, INVALID_CHARACTERS, MAX_WORDS_HIGHLIGHT, PROMPT_DIALOG_SUBTITLE, @@ -90,13 +97,23 @@ export default function GenericModal({ useEffect(() => { setInputValue(value); }, [value, modalOpen]); - const coloredContent = (inputValue || "") .replace(//g, ">") - .replace(regexHighlight, varHighlightHTML({ name: "$1" })) - .replace(/\n/g, "
"); + .replace(regexHighlight, (match, p1, p2) => { + // Decide which group was matched. If p1 is not undefined, do nothing + // we don't want to change the text. If p2 is not undefined, then we + // have a variable, so we should highlight it. + // ! This will not work with multiline or indented json yet + if (p1 !== undefined) { + return match; + } else if (p2 !== undefined) { + return varHighlightHTML({ name: p2 }); + } + return match; + }) + .replace(/\n/g, "
"); function getClassByNumberLength(): string { let sumOfCaracteres: number = 0; wordsHighlight.forEach((element) => { @@ -133,17 +150,17 @@ export default function GenericModal({ } if (!inputVariables || inputVariables.length === 0) { setNoticeData({ - title: "Your template does not have any variables.", + title: TEMP_NOTICE_ALERT, }); } else { setSuccessData({ - title: "Prompt is ready", + title: PROMPT_SUCCESS_ALERT, }); } } else { setIsEdit(true); setErrorData({ - title: "Something went wrong, please try again", + title: BUG_ALERT, }); } }) @@ -151,8 +168,8 @@ export default function GenericModal({ console.log(error); setIsEdit(true); return setErrorData({ - title: "There is something wrong with this prompt, please review it", - list: [error.toString()], + title: PROMPT_ERROR_ALERT, + list: [error.response.data.detail ?? ""], }); }); } @@ -182,7 +199,7 @@ export default function GenericModal({ {myModalTitle}
- -
+ +
{/* BUG ON THIS ICON */} {title} diff --git a/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx index 4c592a3de..e0b7af4f7 100644 --- a/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx @@ -1,4 +1,4 @@ -import _ from "lodash"; +import _, { cloneDeep } from "lodash"; import { MouseEvent, useCallback, useEffect, useRef, useState } from "react"; import ReactFlow, { Background, @@ -12,7 +12,12 @@ import ReactFlow, { updateEdge, } from "reactflow"; import GenericNode from "../../../../CustomNodes/GenericNode"; -import Chat from "../../../../components/chatComponent"; +import { + INVALID_SELECTION_ERROR_ALERT, + UPLOAD_ALERT_LIST, + UPLOAD_ERROR_ALERT, + WRONG_FILE_ERROR_ALERT, +} from "../../../../constants/alerts_constants"; import useAlertStore from "../../../../stores/alertStore"; import useFlowStore from "../../../../stores/flowStore"; import useFlowsManagerStore from "../../../../stores/flowsManagerStore"; @@ -25,12 +30,13 @@ import { getNodeId, isValidConnection, reconnectEdges, + scapeJSONParse, + updateIds, validateSelection, } from "../../../../utils/reactflowUtils"; import { getRandomName, isWrappedWithClass } from "../../../../utils/utils"; import ConnectionLineComponent from "../ConnectionLineComponent"; import SelectionMenu from "../SelectionMenuComponent"; -import ExtraSidebar from "../extraSidebarComponent"; const nodeTypes = { genericNode: GenericNode, @@ -51,12 +57,14 @@ export default function Page({ const templates = useTypesStore((state) => state.templates); const setFilterEdge = useFlowStore((state) => state.setFilterEdge); const reactFlowWrapper = useRef(null); + const [showCanvas, setSHowCanvas] = useState( + Object.keys(templates).length > 0 && Object.keys(types).length > 0 + ); const reactFlowInstance = useFlowStore((state) => state.reactFlowInstance); const setReactFlowInstance = useFlowStore( (state) => state.setReactFlowInstance ); - const nodes = useFlowStore((state) => state.nodes); const edges = useFlowStore((state) => state.edges); const onNodesChange = useFlowStore((state) => state.onNodesChange); @@ -78,13 +86,101 @@ export default function Page({ (state) => state.setLastCopiedSelection ); const onConnect = useFlowStore((state) => state.onConnect); + const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId); + const setErrorData = useAlertStore((state) => state.setErrorData); + const [selectionMenuVisible, setSelectionMenuVisible] = useState(false); + const edgeUpdateSuccessful = useRef(true); const position = useRef({ x: 0, y: 0 }); const [lastSelection, setLastSelection] = useState(null); + function handleGroupNode() { + takeSnapshot(); + if (validateSelection(lastSelection!, edges).length === 0) { + const clonedNodes = cloneDeep(nodes); + const clonedEdges = cloneDeep(edges); + const clonedSelection = cloneDeep(lastSelection); + updateIds({ nodes: clonedNodes, edges: clonedEdges }, clonedSelection!); + const { newFlow, removedEdges } = generateFlow( + clonedSelection!, + clonedNodes, + clonedEdges, + getRandomName() + ); + const newGroupNode = generateNodeFromFlow(newFlow, getNodeId); + const newEdges = reconnectEdges(newGroupNode, removedEdges); + setNodes([ + ...clonedNodes.filter( + (oldNodes) => + !clonedSelection?.nodes.some( + (selectionNode) => selectionNode.id === oldNodes.id + ) + ), + newGroupNode, + ]); + setEdges([ + ...clonedEdges.filter( + (oldEdge) => + !clonedSelection!.nodes.some( + (selectionNode) => + selectionNode.id === oldEdge.target || + selectionNode.id === oldEdge.source + ) + ), + ...newEdges, + ]); + } else { + setErrorData({ + title: INVALID_SELECTION_ERROR_ALERT, + list: validateSelection(lastSelection!, edges), + }); + } + } + + const setNode = useFlowStore((state) => state.setNode); useEffect(() => { const onKeyDown = (event: KeyboardEvent) => { + const selectedNode = nodes.filter((obj) => obj.selected); + if ( + selectionMenuVisible && + (event.ctrlKey || event.metaKey) && + event.key === "g" + ) { + event.preventDefault(); + handleGroupNode(); + } + if ( + (event.ctrlKey || event.metaKey) && + event.key === "p" && + selectedNode.length > 0 + ) { + event.preventDefault(); + setNode(selectedNode[0].id, (old) => ({ + ...old, + data: { + ...old.data, + node: { + ...old.data.node, + frozen: old.data?.node?.frozen ? false : true, + }, + }, + })); + } + if ( + (event.ctrlKey || event.metaKey) && + event.key === "d" && + selectedNode.length > 0 + ) { + event.preventDefault(); + paste( + { nodes: selectedNode, edges: [] }, + { + x: position.current.x, + y: position.current.y, + } + ); + } if (!isWrappedWithClass(event, "noundo")) { if ( (event.key === "y" || (event.key === "z" && event.shiftKey)) && @@ -158,18 +254,10 @@ export default function Page({ document.removeEventListener("keydown", onKeyDown); document.removeEventListener("mousemove", handleMouseMove); }; - }, [lastCopiedSelection, lastSelection, takeSnapshot]); - - const [selectionMenuVisible, setSelectionMenuVisible] = useState(false); - - const setErrorData = useAlertStore((state) => state.setErrorData); - - const edgeUpdateSuccessful = useRef(true); - - const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId); + }, [lastCopiedSelection, lastSelection, takeSnapshot, selectionMenuVisible]); useEffect(() => { - if (reactFlowInstance) { + if (reactFlowInstance && currentFlowId) { resetFlow({ nodes: flow?.data?.nodes ?? [], edges: flow?.data?.edges ?? [], @@ -184,6 +272,12 @@ export default function Page({ }; }, []); + useEffect(() => { + setSHowCanvas( + Object.keys(templates).length > 0 && Object.keys(types).length > 0 + ); + }, [templates, types]); + const onConnectMod = useCallback( (params: Connection) => { takeSnapshot(); @@ -262,14 +356,14 @@ export default function Page({ position: position, }).catch((error) => { setErrorData({ - title: "Error uploading file", + title: UPLOAD_ERROR_ALERT, list: [error], }); }); } else { setErrorData({ - title: "Invalid file type", - list: ["Please upload a JSON file"], + title: WRONG_FILE_ERROR_ALERT, + list: [UPLOAD_ALERT_LIST], }); } } @@ -286,6 +380,8 @@ export default function Page({ (oldEdge: Edge, newConnection: Connection) => { if (isValidConnection(newConnection, nodes, edges)) { edgeUpdateSuccessful.current = true; + oldEdge.data.targetHandle = scapeJSONParse(newConnection.targetHandle!); + oldEdge.data.sourceHandle = scapeJSONParse(newConnection.sourceHandle!); setEdges((els) => updateEdge(oldEdge, newConnection, els)); } }, @@ -329,116 +425,74 @@ export default function Page({ setFilterEdge([]); }, []); + function onMouseAction(edge: Edge, color: string): void { + const edges = useFlowStore.getState().edges; + const newEdges = _.cloneDeep(edges); + const style = { stroke: color, transition: "stroke 0.25s" }; + const updatedEdges = newEdges.map((obj) => { + if (obj.id === edge.id) { + return { ...obj, style }; + } + return obj; + }); + setEdges(updatedEdges); + } + return ( -
- {!view && } - {/* Main area */} -
- {/* Primary column */} -
-
- {Object.keys(templates).length > 0 && - Object.keys(types).length > 0 ? ( -
- - - {!view && ( - - )} - { - takeSnapshot(); - if ( - validateSelection(lastSelection!, edges).length === 0 - ) { - const { newFlow, removedEdges } = generateFlow( - lastSelection!, - nodes, - edges, - getRandomName() - ); - const newGroupNode = generateNodeFromFlow( - newFlow, - getNodeId - ); - const newEdges = reconnectEdges( - newGroupNode, - removedEdges - ); - setNodes((oldNodes) => [ - ...oldNodes.filter( - (oldNodes) => - !lastSelection?.nodes.some( - (selectionNode) => - selectionNode.id === oldNodes.id - ) - ), - newGroupNode, - ]); - setEdges((oldEdges) => [ - ...oldEdges.filter( - (oldEdge) => - !lastSelection!.nodes.some( - (selectionNode) => - selectionNode.id === oldEdge.target || - selectionNode.id === oldEdge.source - ) - ), - ...newEdges, - ]); - } else { - setErrorData({ - title: "Invalid selection", - list: validateSelection(lastSelection!, edges), - }); - } - }} - /> - - {!view && } -
- ) : ( - <> +
+ {showCanvas ? ( +
+ + + {!view && ( + )} -
+ { + handleGroupNode(); + }} + /> +
-
+ ) : ( + <> + )}
); } diff --git a/src/frontend/src/pages/FlowPage/components/ParentDisclosureComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/ParentDisclosureComponent/index.tsx new file mode 100644 index 000000000..edc479fce --- /dev/null +++ b/src/frontend/src/pages/FlowPage/components/ParentDisclosureComponent/index.tsx @@ -0,0 +1,41 @@ +import { Disclosure } from "@headlessui/react"; +import IconComponent from "../../../../components/genericIconComponent"; +import { DisclosureComponentType } from "../../../../types/components"; + +export default function ParentDisclosureComponent({ + button: { title, Icon, buttons = [] }, + children, + openDisc, +}: DisclosureComponentType): JSX.Element { + return ( + + {({ open }) => ( + <> +
+ +
+ {title} +
+
+ {buttons.map((btn, index) => ( + + ))} +
+ +
+
+
+
+ {children} + + )} +
+ ); +} diff --git a/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/index.tsx index f9e904581..f713ca884 100644 --- a/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/index.tsx @@ -1,10 +1,11 @@ import { cloneDeep } from "lodash"; +import { LinkIcon, SparklesIcon } from "lucide-react"; import { useEffect, useMemo, useState } from "react"; import ShadTooltip from "../../../../components/ShadTooltipComponent"; import IconComponent from "../../../../components/genericIconComponent"; import { Input } from "../../../../components/ui/input"; import { Separator } from "../../../../components/ui/separator"; -import ApiModal from "../../../../modals/ApiModal"; +import { PRIORITY_SIDEBAR_ORDER } from "../../../../constants/constants"; import ExportModal from "../../../../modals/exportModal"; import ShareModal from "../../../../modals/shareModal"; import useAlertStore from "../../../../stores/alertStore"; @@ -24,7 +25,9 @@ import { sensitiveSort, } from "../../../../utils/utils"; import DisclosureComponent from "../DisclosureComponent"; +import ParentDisclosureComponent from "../ParentDisclosureComponent"; import SidebarDraggableComponent from "./sideBarDraggableComponent"; +import { sortKeys } from "./utils"; export default function ExtraSidebar(): JSX.Element { const data = useTypesStore((state) => state.data); @@ -37,7 +40,6 @@ export default function ExtraSidebar(): JSX.Element { const hasApiKey = useStoreStore((state) => state.hasApiKey); const validApiKey = useStoreStore((state) => state.validApiKey); - const isBuilt = useFlowStore((state) => state.isBuilt); const setErrorData = useAlertStore((state) => state.setErrorData); const [dataFilter, setFilterData] = useState(data); const [search, setSearch] = useState(""); @@ -232,73 +234,22 @@ export default function ExtraSidebar(): JSX.Element { [] ); + const getIcon = useMemo(() => { + return (SBSectionName: string) => { + if (nodeIconsLucide[SBSectionName]) { + return ( + + ); + } + }; + }, []); + return (
-
- {hasStore && validApiKey && ( - -
{ModalMemo}
-
- )} -
- - - -
- {(!hasApiKey || !validApiKey) && ( - -
{ExportMemo}
-
- )} - -
- {currentFlow && currentFlow.data && ( - - - - )} -
-
-
-
handleBlur()} @@ -314,94 +265,215 @@ export default function ExtraSidebar(): JSX.Element { setSearch(event.target.value); }} /> -
+
{ + if (search) { + setFilterData(data); + setSearch(""); + } + }} + >
- +
+
+
+ Core Components +
+
{Object.keys(dataFilter) - .sort((a, b) => { - if (a.toLowerCase() === "saved_components") { - return -1; - } else if (b.toLowerCase() === "saved_components") { - return 1; - } else if (a.toLowerCase() === "custom_components") { - return -2; - } else if (b.toLowerCase() === "custom_components") { - return 2; - } else { - return a.localeCompare(b); - } - }) + .sort(sortKeys) + .filter((x) => PRIORITY_SIDEBAR_ORDER.includes(x)) .map((SBSectionName: keyof APIObjectType, index) => Object.keys(dataFilter[SBSectionName]).length > 0 ? ( - -
- {Object.keys(dataFilter[SBSectionName]) - .sort((a, b) => - sensitiveSort( - dataFilter[SBSectionName][a].display_name, - dataFilter[SBSectionName][b].display_name + <> + +
+ {Object.keys(dataFilter[SBSectionName]) + .sort((a, b) => + sensitiveSort( + dataFilter[SBSectionName][a].display_name, + dataFilter[SBSectionName][b].display_name + ) ) - ) - .map((SBItemName: string, index) => ( - - - onDragStart(event, { - //split type to remove type in nodes saved with same name removing it's - type: removeCountFromString(SBItemName), - node: dataFilter[SBSectionName][SBItemName], - }) - } - color={nodeColors[SBSectionName]} - itemName={SBItemName} - //convert error to boolean - error={!!dataFilter[SBSectionName][SBItemName].error} - display_name={ + .map((SBItemName: string, index) => ( + - - ))} -
-
+ side="right" + key={index} + > + + onDragStart(event, { + //split type to remove type in nodes saved with same name removing it's + type: removeCountFromString(SBItemName), + node: dataFilter[SBSectionName][SBItemName], + }) + } + color={nodeColors[SBSectionName]} + itemName={SBItemName} + //convert error to boolean + error={ + !!dataFilter[SBSectionName][SBItemName].error + } + display_name={ + dataFilter[SBSectionName][SBItemName].display_name + } + official={ + dataFilter[SBSectionName][SBItemName].official === + false + ? false + : true + } + /> + + ))} +
+
+ ) : (
) - )} + )}{" "} + + {Object.keys(dataFilter) + .sort(sortKeys) + .filter((x) => !PRIORITY_SIDEBAR_ORDER.includes(x)) + .map((SBSectionName: keyof APIObjectType, index) => + Object.keys(dataFilter[SBSectionName]).length > 0 ? ( + <> + +
+ {Object.keys(dataFilter[SBSectionName]) + .sort((a, b) => + sensitiveSort( + dataFilter[SBSectionName][a].display_name, + dataFilter[SBSectionName][b].display_name + ) + ) + .map((SBItemName: string, index) => ( + + + onDragStart(event, { + //split type to remove type in nodes saved with same name removing it's + type: removeCountFromString(SBItemName), + node: dataFilter[SBSectionName][SBItemName], + }) + } + color={nodeColors[SBSectionName]} + itemName={SBItemName} + //convert error to boolean + error={ + !!dataFilter[SBSectionName][SBItemName].error + } + display_name={ + dataFilter[SBSectionName][SBItemName] + .display_name + } + official={ + dataFilter[SBSectionName][SBItemName] + .official === false + ? false + : true + } + /> + + ))} +
+
+ {index === + Object.keys(dataFilter).length - + PRIORITY_SIDEBAR_ORDER.length + + 1 && ( + <> +
+
+ {/* BUG ON THIS ICON */} + + + + Discover More + +
+
+
+ +
+
+
+ + )} + + ) : ( +
+ ) + )} +
); diff --git a/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/sideBarDraggableComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/sideBarDraggableComponent/index.tsx index f33e97a1d..7d468b4ba 100644 --- a/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/sideBarDraggableComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/sideBarDraggableComponent/index.tsx @@ -43,6 +43,7 @@ export const SidebarDraggableComponent = forwardRef( const deleteComponent = useFlowsManagerStore( (state) => state.deleteComponent ); + const version = useDarkStore((state) => state.version); const [cursorPos, setCursorPos] = useState({ x: 0, y: 0 }); const popoverRef = useRef(null); diff --git a/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/utils.tsx b/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/utils.tsx new file mode 100644 index 000000000..ee0509cd0 --- /dev/null +++ b/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/utils.tsx @@ -0,0 +1,26 @@ +import { PRIORITY_SIDEBAR_ORDER } from "../../../../constants/constants"; + +export function sortKeys(a: string, b: string) { + // Define the order of specific keys + + const indexA = PRIORITY_SIDEBAR_ORDER.indexOf(a.toLowerCase()); + const indexB = PRIORITY_SIDEBAR_ORDER.indexOf(b.toLowerCase()); + + // Check if both keys are in the predefined order + if (indexA !== -1 && indexB !== -1) { + return indexA - indexB; + } + + // If only 'a' is in the predefined order, it should come first + if (indexA !== -1) { + return -1; + } + + // If only 'b' is in the predefined order, it should come first + if (indexB !== -1) { + return 1; + } + + // If neither 'a' nor 'b' are in the predefined order, sort them alphabetically + return a.localeCompare(b); +} diff --git a/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx index 279165a69..8a134f48a 100644 --- a/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx @@ -1,6 +1,8 @@ -import { cloneDeep } from "lodash"; +import _, { cloneDeep } from "lodash"; import { useEffect, useState } from "react"; +import { useUpdateNodeInternals } from "reactflow"; import ShadTooltip from "../../../../components/ShadTooltipComponent"; +import CodeAreaComponent from "../../../../components/codeAreaComponent"; import IconComponent from "../../../../components/genericIconComponent"; import { Select, @@ -8,13 +10,17 @@ import { SelectItem, SelectTrigger, } from "../../../../components/ui/select-custom"; +import { postCustomComponent } from "../../../../controllers/API"; import ConfirmationModal from "../../../../modals/ConfirmationModal"; import EditNodeModal from "../../../../modals/EditNodeModal"; import ShareModal from "../../../../modals/shareModal"; +import useAlertStore from "../../../../stores/alertStore"; import { useDarkStore } from "../../../../stores/darkStore"; import useFlowStore from "../../../../stores/flowStore"; import useFlowsManagerStore from "../../../../stores/flowsManagerStore"; import { useStoreStore } from "../../../../stores/storeStore"; +import { useTypesStore } from "../../../../stores/typesStore"; +import { APIClassType } from "../../../../types/api"; import { nodeToolbarPropsType } from "../../../../types/components"; import { FlowType } from "../../../../types/flow"; import { @@ -24,14 +30,20 @@ import { updateFlowPosition, } from "../../../../utils/reactflowUtils"; import { classNames } from "../../../../utils/utils"; +import ToolbarSelectItem from "./toolbarSelectItem"; export default function NodeToolbarComponent({ data, deleteNode, - position, setShowNode, numberOfHandles, showNode, + name = "code", + selected, + updateNodeCode, + setShowState, + onCloseAdvancedModal, + isOutdated, }: nodeToolbarPropsType): JSX.Element { const nodeLength = Object.keys(data.node!.template).filter( (templateField) => @@ -48,7 +60,7 @@ export default function NodeToolbarComponent({ data.node.template[templateField].type === "dict" || data.node.template[templateField].type === "NestedDict") ).length; - + const templates = useTypesStore((state) => state.templates); const hasStore = useStoreStore((state) => state.hasStore); const hasApiKey = useStoreStore((state) => state.hasApiKey); const validApiKey = useStoreStore((state) => state.validApiKey); @@ -56,26 +68,44 @@ export default function NodeToolbarComponent({ const isMinimal = numberOfHandles <= 1; const isGroup = data.node?.flow ? true : false; + // const frozen = data.node?.frozen ?? false; const paste = useFlowStore((state) => state.paste); const nodes = useFlowStore((state) => state.nodes); const edges = useFlowStore((state) => state.edges); const setNodes = useFlowStore((state) => state.setNodes); - const setEdges = useFlowStore((state) => state.setEdges); + const setEdges = useFlowStore((state) => state.setEdges); + const unselectAll = useFlowStore((state) => state.unselectAll); const saveComponent = useFlowsManagerStore((state) => state.saveComponent); + const getNodePosition = useFlowStore((state) => state.getNodePosition); const flows = useFlowsManagerStore((state) => state.flows); const version = useDarkStore((state) => state.version); const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot); const [showModalAdvanced, setShowModalAdvanced] = useState(false); const [showconfirmShare, setShowconfirmShare] = useState(false); const [showOverrideModal, setShowOverrideModal] = useState(false); - - const [flowComponent, setFlowComponent] = useState(); + const [flowComponent, setFlowComponent] = useState( + createFlowComponent(cloneDeep(data), version) + ); const openInNewTab = (url) => { window.open(url, "_blank", "noreferrer"); }; + useEffect(() => { + if (!showModalAdvanced) { + onCloseAdvancedModal!(false); + } + }, [showModalAdvanced]); + const updateNodeInternals = useUpdateNodeInternals(); + + const setLastCopiedSelection = useFlowStore( + (state) => state.setLastCopiedSelection + ); + + const setSuccessData = useAlertStore((state) => state.setSuccessData); + const setNoticeData = useAlertStore((state) => state.setNoticeData); + useEffect(() => { setFlowComponent(createFlowComponent(cloneDeep(data), version)); }, [ @@ -97,6 +127,9 @@ export default function NodeToolbarComponent({ takeSnapshot(); setShowNode(data.showNode ?? true ? false : true); break; + case "Share": + if (hasApiKey || hasStore) setShowconfirmShare(true); + break; case "Download": downloadNode(flowComponent!); break; @@ -112,7 +145,7 @@ export default function NodeToolbarComponent({ takeSnapshot(); expandGroupNode( data.id, - updateFlowPosition(position, data.node?.flow!), + updateFlowPosition(getNodePosition(data.id), data.node?.flow!), data.node!.template, nodes, edges, @@ -122,6 +155,58 @@ export default function NodeToolbarComponent({ break; case "override": setShowOverrideModal(true); + break; + case "delete": + deleteNode(data.id); + break; + case "copy": + const node = nodes.filter((node) => node.id === data.id); + setLastCopiedSelection({ nodes: _.cloneDeep(node), edges: [] }); + break; + case "duplicate": + paste( + { + nodes: [nodes.find((node) => node.id === data.id)!], + edges: [], + }, + { + x: 50, + y: 10, + paneX: nodes.find((node) => node.id === data.id)?.position.x, + paneY: nodes.find((node) => node.id === data.id)?.position.y, + } + ); + break; + case "update": + takeSnapshot(); + // to update we must get the code from the templates in useTypesStore + const thisNodeTemplate = templates[data.type].template; + // if the template does not have a code key + // return + if (!thisNodeTemplate.code) return; + + const currentCode = thisNodeTemplate.code.value; + if (data.node) { + postCustomComponent(currentCode, data.node) + .then((apiReturn) => { + const { data } = apiReturn; + if (data && updateNodeCode) { + updateNodeCode(data, currentCode, "code"); + } + }) + .catch((err) => { + console.log(err); + }); + setNode(data.id, (oldNode) => { + let newNode = cloneDeep(oldNode); + newNode.data = { + ...data, + }; + newNode.data.node.template.code.value = currentCode; + return newNode; + }); + } + break; } }; @@ -130,74 +215,243 @@ export default function NodeToolbarComponent({ Object.values(flow).includes(data.node?.display_name!) ); + const setNode = useFlowStore((state) => state.setNode); + + const handleOnNewValue = ( + newValue: string | string[] | boolean | Object[] + ): void => { + if (data.node!.template[name].value !== newValue) { + takeSnapshot(); + } + + data.node!.template[name].value = newValue; // necessary to enable ctrl+z inside the input + + setNode(data.id, (oldNode) => { + let newNode = cloneDeep(oldNode); + + newNode.data = { + ...newNode.data, + }; + + newNode.data.node.template[name].value = newValue; + + return newNode; + }); + }; + + const handleNodeClass = (newNodeClass: APIClassType, code?: string): void => { + if (!data.node) return; + if (data.node!.template[name].value !== code) { + takeSnapshot(); + } + + setNode(data.id, (oldNode) => { + let newNode = cloneDeep(oldNode); + + newNode.data = { + ...newNode.data, + node: newNodeClass, + description: newNodeClass.description ?? data.node!.description, + display_name: newNodeClass.display_name ?? data.node!.display_name, + }; + + newNode.data.node.template[name].value = code; + + return newNode; + }); + updateNodeInternals(data.id); + }; + + const [openModal, setOpenModal] = useState(false); + const hasCode = Object.keys(data.node!.template).includes("code"); + + useEffect(() => { + function onKeyDown(event: KeyboardEvent) { + if ( + selected && + (hasApiKey || hasStore) && + (event.ctrlKey || event.metaKey) && + event.key === "u" + ) { + event.preventDefault(); + handleSelectChange("update"); + } + if ( + selected && + isGroup && + (event.ctrlKey || event.metaKey) && + event.key === "g" + ) { + event.preventDefault(); + handleSelectChange("ungroup"); + } + if ( + selected && + (hasApiKey || hasStore) && + (event.ctrlKey || event.metaKey) && + event.shiftKey && + event.key === "S" + ) { + event.preventDefault(); + setShowconfirmShare((state) => !state); + } + + if ( + selected && + (event.ctrlKey || event.metaKey) && + event.shiftKey && + event.key === "Q" + ) { + event.preventDefault(); + if (isMinimal) { + setShowState((show) => !show); + setShowNode(data.showNode ?? true ? false : true); + return; + } + setNoticeData({ + title: + "Minimization are only available for nodes with one handle or fewer.", + }); + } + if ( + selected && + (event.ctrlKey || event.metaKey) && + event.shiftKey && + event.key === "U" + ) { + event.preventDefault(); + if (hasCode) return setOpenModal((state) => !state); + setNoticeData({ title: `You can not access ${data.id} code` }); + } + if ( + selected && + !isGroup && + (event.ctrlKey || event.metaKey) && + event.shiftKey && + event.key === "A" + ) { + event.preventDefault(); + setShowModalAdvanced((state) => !state); + } + if (selected && (event.ctrlKey || event.metaKey) && event.key === "s") { + if (isSaved) { + event.preventDefault(); + return setShowOverrideModal((state) => !state); + } + if (hasCode) { + event.preventDefault(); + saveComponent(cloneDeep(data), false); + setSuccessData({ title: `${data.id} saved successfully` }); + } + } + if ( + selected && + (event.ctrlKey || event.metaKey) && + event.shiftKey && + event.key === "D" + ) { + event.preventDefault(); + if (data.node?.documentation) { + return openInNewTab(data.node?.documentation); + } + setNoticeData({ + title: `${data.id} docs is not available at the moment.`, + }); + } + if (selected && (event.ctrlKey || event.metaKey) && event.key === "j") { + event.preventDefault(); + downloadNode(flowComponent!); + } + } + + document.addEventListener("keydown", onKeyDown); + + return () => { + document.removeEventListener("keydown", onKeyDown); + }; + }, [isSaved, showNode, data.showNode, isMinimal]); + return ( <>
- + {hasCode && ( + + + + )} + + - + + + + + {/* - - {hasStore && ( - - - - )} + /> + + */} @@ -311,9 +624,13 @@ export default function NodeToolbarComponent({ index={6} onConfirm={(index, user) => { saveComponent(cloneDeep(data), true); + setSuccessData({ title: `${data.id} successfully overridden!` }); }} onClose={setShowOverrideModal} - onCancel={() => saveComponent(cloneDeep(data), false)} + onCancel={() => { + saveComponent(cloneDeep(data), false); + setSuccessData({ title: "New node successfully saved!" }); + }} > @@ -328,12 +645,36 @@ export default function NodeToolbarComponent({ open={showModalAdvanced} setOpen={setShowModalAdvanced} /> - + {showconfirmShare && ( + + )} + {hasCode && ( +
+ {openModal && ( + + )} +
+ )}
diff --git a/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/toolbarSelectItem/index.tsx b/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/toolbarSelectItem/index.tsx new file mode 100644 index 000000000..88e74623a --- /dev/null +++ b/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/toolbarSelectItem/index.tsx @@ -0,0 +1,51 @@ +import ForwardedIconComponent from "../../../../../components/genericIconComponent"; +import { toolbarSelectItemProps } from "../../../../../types/components"; + +export default function ToolbarSelectItem({ + shift, + isMac, + keyboardKey, + value, + icon, + styleObj, + dataTestId, + ping, +}: toolbarSelectItemProps) { + return ( +
+ + {value} + + {isMac ? ( + + ) : ( + + {shift ? "Ctrl" : "Ctrl +"} + + )} + {shift && ( + + )} + + {keyboardKey} + +
+ ); +} diff --git a/src/frontend/src/pages/FlowPage/index.tsx b/src/frontend/src/pages/FlowPage/index.tsx index 9aa88a6e2..a222dddcc 100644 --- a/src/frontend/src/pages/FlowPage/index.tsx +++ b/src/frontend/src/pages/FlowPage/index.tsx @@ -1,11 +1,13 @@ import { useEffect } from "react"; import { useParams } from "react-router-dom"; +import FlowToolbar from "../../components/chatComponent"; import Header from "../../components/headerComponent"; import { useDarkStore } from "../../stores/darkStore"; import useFlowsManagerStore from "../../stores/flowsManagerStore"; import Page from "./components/PageComponent"; +import ExtraSidebar from "./components/extraSidebarComponent"; -export default function FlowPage(): JSX.Element { +export default function FlowPage({ view }: { view?: boolean }): JSX.Element { const setCurrentFlowId = useFlowsManagerStore( (state) => state.setCurrentFlowId ); @@ -17,12 +19,22 @@ export default function FlowPage(): JSX.Element { useEffect(() => { setCurrentFlowId(id!); }, [id]); - return ( <>
- {currentFlow && } + {currentFlow && ( +
+ {!view && } +
+ {/* Primary column */} +
+ +
+ {!view && } +
+
+ )} state.uploadFlow); const removeFlow = useFlowsManagerStore((state) => state.removeFlow); const isLoading = useFlowsManagerStore((state) => state.isLoading); + const setExamples = useFlowsManagerStore((state) => state.setExamples); const flows = useFlowsManagerStore((state) => state.flows); const setSuccessData = useAlertStore((state) => state.setSuccessData); const setErrorData = useAlertStore((state) => state.setErrorData); - const [pageSize, setPageSize] = useState(10); + const [pageSize, setPageSize] = useState(20); const [pageIndex, setPageIndex] = useState(1); const [loadingScreen, setLoadingScreen] = useState(true); @@ -30,7 +36,7 @@ export default function ComponentsComponent({ useEffect(() => { if (isLoading) return; - const all = flows + let all = flows .filter((f) => (f.is_component ?? false) === is_component) .sort((a, b) => { if (a?.updated_at && b?.updated_at) { @@ -76,14 +82,14 @@ export default function ComponentsComponent({ }) .catch((error) => { setErrorData({ - title: "Error uploading file", + title: CONSOLE_ERROR_MSG, list: [error], }); }); } else { setErrorData({ - title: "Invalid file type", - list: ["Please upload a JSON file"], + title: WRONG_FILE_ERROR_ALERT, + list: [UPLOAD_ALERT_LIST], }); } } @@ -91,7 +97,7 @@ export default function ComponentsComponent({ function resetFilter() { setPageIndex(1); - setPageSize(10); + setPageSize(20); } return ( diff --git a/src/frontend/src/pages/MainPage/index.tsx b/src/frontend/src/pages/MainPage/index.tsx index 6e0c5cb55..e7aa678e7 100644 --- a/src/frontend/src/pages/MainPage/index.tsx +++ b/src/frontend/src/pages/MainPage/index.tsx @@ -1,17 +1,21 @@ import { Group, ToyBrick } from "lucide-react"; -import { useEffect } from "react"; +import { useEffect, useState } from "react"; import { Outlet, useLocation, useNavigate } from "react-router-dom"; import DropdownButton from "../../components/DropdownButtonComponent"; import IconComponent from "../../components/genericIconComponent"; import PageLayout from "../../components/pageLayout"; import SidebarNav from "../../components/sidebarComponent"; import { Button } from "../../components/ui/button"; -import { USER_PROJECTS_HEADER } from "../../constants/constants"; +import { CONSOLE_ERROR_MSG } from "../../constants/alerts_constants"; +import { + MY_COLLECTION_DESC, + USER_PROJECTS_HEADER, +} from "../../constants/constants"; +import NewFlowModal from "../../modals/NewFlowModal"; import useAlertStore from "../../stores/alertStore"; import useFlowsManagerStore from "../../stores/flowsManagerStore"; import { downloadFlows } from "../../utils/reactflowUtils"; export default function HomePage(): JSX.Element { - const addFlow = useFlowsManagerStore((state) => state.addFlow); const uploadFlow = useFlowsManagerStore((state) => state.uploadFlow); const setCurrentFlowId = useFlowsManagerStore( (state) => state.setCurrentFlowId @@ -21,6 +25,7 @@ export default function HomePage(): JSX.Element { const setErrorData = useAlertStore((state) => state.setErrorData); const location = useLocation(); const pathname = location.pathname; + const [openModal, setOpenModal] = useState(false); const is_component = pathname === "/components"; const dropdownOptions = [ { @@ -40,7 +45,7 @@ export default function HomePage(): JSX.Element { }) .catch((error) => { setErrorData({ - title: "Error uploading file", + title: CONSOLE_ERROR_MSG, list: [error], }); }); @@ -71,7 +76,7 @@ export default function HomePage(): JSX.Element { return (
} @@ -112,6 +115,7 @@ export default function HomePage(): JSX.Element {
+ ); } diff --git a/src/frontend/src/pages/ProfileSettingsPage/index.tsx b/src/frontend/src/pages/ProfileSettingsPage/index.tsx index 6a5bc7b70..a7af7c86a 100644 --- a/src/frontend/src/pages/ProfileSettingsPage/index.tsx +++ b/src/frontend/src/pages/ProfileSettingsPage/index.tsx @@ -6,6 +6,12 @@ import GradientChooserComponent from "../../components/gradientChooserComponent" import Header from "../../components/headerComponent"; import InputComponent from "../../components/inputComponent"; import { Button } from "../../components/ui/button"; +import { + EDIT_PASSWORD_ALERT_LIST, + EDIT_PASSWORD_ERROR_ALERT, + SAVE_ERROR_ALERT, + SAVE_SUCCESS_ALERT, +} from "../../constants/alerts_constants"; import { CONTROL_PATCH_USER_STATE } from "../../constants/constants"; import { AuthContext } from "../../contexts/authContext"; import { resetPassword, updateUser } from "../../controllers/API"; @@ -37,8 +43,8 @@ export default function ProfileSettingsPage(): JSX.Element { async function handlePatchUser() { if (password !== cnfPassword) { setErrorData({ - title: "Error changing password", - list: ["Passwords do not match"], + title: EDIT_PASSWORD_ERROR_ALERT, + list: [EDIT_PASSWORD_ALERT_LIST], }); return; } @@ -54,10 +60,10 @@ export default function ProfileSettingsPage(): JSX.Element { } handleInput({ target: { name: "password", value: "" } }); handleInput({ target: { name: "cnfPassword", value: "" } }); - setSuccessData({ title: "Changes saved successfully!" }); + setSuccessData({ title: SAVE_SUCCESS_ALERT }); } catch (error) { setErrorData({ - title: "Error saving changes", + title: SAVE_ERROR_ALERT, list: [(error as any).response.data.detail], }); } diff --git a/src/frontend/src/pages/StorePage/index.tsx b/src/frontend/src/pages/StorePage/index.tsx index d83c8a174..412dd1a68 100644 --- a/src/frontend/src/pages/StorePage/index.tsx +++ b/src/frontend/src/pages/StorePage/index.tsx @@ -20,6 +20,13 @@ import { SelectTrigger, SelectValue, } from "../../components/ui/select"; +import { + APIKEY_ERROR_ALERT, + COMPONENTS_ERROR_ALERT, + INVALID_API_ERROR_ALERT, + NOAPI_ERROR_ALERT, +} from "../../constants/alerts_constants"; +import { STORE_DESC, STORE_TITLE } from "../../constants/constants"; import { AuthContext } from "../../contexts/authContext"; import { getStoreComponents, getStoreTags } from "../../controllers/API"; import StoreApiKeyModal from "../../modals/StoreApiKeyModal"; @@ -62,18 +69,14 @@ export default function StorePage(): JSX.Element { if (!loadingApiKey) { if (!hasApiKey) { setErrorData({ - title: "API Key Error", - list: [ - "You don't have an API Key. Please add one to use the Langflow Store.", - ], + title: APIKEY_ERROR_ALERT, + list: [NOAPI_ERROR_ALERT], }); setLoading(false); } else if (!validApiKey) { setErrorData({ - title: "API Key Error", - list: [ - "Your API Key is not valid. Please add a valid API Key to use the Langflow Store.", - ], + title: APIKEY_ERROR_ALERT, + list: [INVALID_API_ERROR_ALERT], }); } } @@ -144,14 +147,14 @@ export default function StorePage(): JSX.Element { } }) .catch((err) => { - if (err.response.status === 403 || err.response.status === 401) { + if (err.response?.status === 403 || err.response?.status === 401) { setValidApiKey(false); } else { setSearchData([]); setTotalRowsCount(0); setLoading(false); setErrorData({ - title: "Error getting components.", + title: COMPONENTS_ERROR_ALERT, list: [err["response"]["data"]["detail"]], }); } @@ -171,8 +174,8 @@ export default function StorePage(): JSX.Element { return ( {StoreApiKeyModal && ( diff --git a/src/frontend/src/pages/deleteAccountPage/index.tsx b/src/frontend/src/pages/deleteAccountPage/index.tsx index af219209b..c82cc1cc7 100644 --- a/src/frontend/src/pages/deleteAccountPage/index.tsx +++ b/src/frontend/src/pages/deleteAccountPage/index.tsx @@ -10,7 +10,6 @@ export default function DeleteAccountPage() { // Implement your account deletion logic here // For example, make an API call to delete the account // Upon successful deletion, you can redirect the user to another page - console.log("Account deleted!"); // Implement the logic to redirect the user after account deletion. // For example, use react-router-dom's useHistory hook. }; diff --git a/src/frontend/src/pages/loginPage/index.tsx b/src/frontend/src/pages/loginPage/index.tsx index f7cdbd190..2d9ea59c9 100644 --- a/src/frontend/src/pages/loginPage/index.tsx +++ b/src/frontend/src/pages/loginPage/index.tsx @@ -4,6 +4,7 @@ import { Link, useNavigate } from "react-router-dom"; import InputComponent from "../../components/inputComponent"; import { Button } from "../../components/ui/button"; import { Input } from "../../components/ui/input"; +import { SIGNIN_ERROR_ALERT } from "../../constants/alerts_constants"; import { CONTROL_LOGIN_STATE } from "../../constants/constants"; import { AuthContext } from "../../contexts/authContext"; import { onLogin } from "../../controllers/API"; @@ -42,7 +43,7 @@ export default function LoginPage(): JSX.Element { }) .catch((error) => { setErrorData({ - title: "Error signing in", + title: SIGNIN_ERROR_ALERT, list: [error["response"]["data"]["detail"]], }); }); diff --git a/src/frontend/src/pages/signUpPage/index.tsx b/src/frontend/src/pages/signUpPage/index.tsx index d731eee9e..1cdad3d59 100644 --- a/src/frontend/src/pages/signUpPage/index.tsx +++ b/src/frontend/src/pages/signUpPage/index.tsx @@ -4,6 +4,7 @@ import { Link, useNavigate } from "react-router-dom"; import InputComponent from "../../components/inputComponent"; import { Button } from "../../components/ui/button"; import { Input } from "../../components/ui/input"; +import { SIGNUP_ERROR_ALERT } from "../../constants/alerts_constants"; import { CONTROL_INPUT_STATE, SIGN_UP_SUCCESS, @@ -60,7 +61,7 @@ export default function SignUp(): JSX.Element { }, } = error; setErrorData({ - title: "Error signing up", + title: SIGNUP_ERROR_ALERT, list: [detail], }); return; diff --git a/src/frontend/src/stores/alertStore.ts b/src/frontend/src/stores/alertStore.ts index 63c58e28c..e23a8d4e3 100644 --- a/src/frontend/src/stores/alertStore.ts +++ b/src/frontend/src/stores/alertStore.ts @@ -2,6 +2,7 @@ import { uniqueId } from "lodash"; import { create } from "zustand"; import { AlertItemType } from "../types/alerts"; import { AlertStoreType } from "../types/zustand/alert"; +import { customStringify } from "../utils/reactflowUtils"; const pushNotificationList = ( list: AlertItemType[], @@ -13,67 +14,130 @@ const pushNotificationList = ( const useAlertStore = create((set, get) => ({ errorData: { title: "", list: [] }, - errorOpen: false, noticeData: { title: "", link: "" }, - noticeOpen: false, successData: { title: "" }, - successOpen: false, notificationCenter: false, notificationList: [], + tempNotificationList: [], loading: true, setErrorData: (newState: { title: string; list?: Array }) => { if (newState.title && newState.title !== "") { set({ errorData: newState, - errorOpen: true, notificationCenter: true, - notificationList: pushNotificationList(get().notificationList, { - type: "error", - title: newState.title, - list: newState.list, - id: uniqueId(), - }), + notificationList: [ + { + type: "error", + title: newState.title, + list: newState.list, + id: uniqueId(), + }, + ...get().notificationList, + ], }); + const tempList = get().tempNotificationList; + if ( + !tempList.some((item) => { + return ( + customStringify({ + title: item.title, + type: item.type, + list: item.list, + }) === customStringify({ ...newState, type: "error" }) + ); + }) + ) { + set({ + tempNotificationList: [ + { + type: "error", + title: newState.title, + list: newState.list, + id: uniqueId(), + }, + ...get().tempNotificationList, + ], + }); + } } }, - setErrorOpen: (newState: boolean) => { - set({ errorOpen: newState }); - }, setNoticeData: (newState: { title: string; link?: string }) => { if (newState.title && newState.title !== "") { set({ noticeData: newState, - noticeOpen: true, notificationCenter: true, - notificationList: pushNotificationList(get().notificationList, { - type: "notice", - title: newState.title, - link: newState.link, - id: uniqueId(), - }), + notificationList: [ + { + type: "notice", + title: newState.title, + link: newState.link, + id: uniqueId(), + }, + ...get().notificationList, + ], }); + const tempList = get().tempNotificationList; + if ( + !tempList.some((item) => { + return ( + customStringify({ + title: item.title, + type: item.type, + link: item.link, + }) === customStringify({ ...newState, type: "notice" }) + ); + }) + ) { + set({ + tempNotificationList: [ + { + type: "notice", + title: newState.title, + link: newState.link, + id: uniqueId(), + }, + ...get().tempNotificationList, + ], + }); + } } }, - setNoticeOpen: (newState: boolean) => { - set({ noticeOpen: newState }); - }, setSuccessData: (newState: { title: string }) => { if (newState.title && newState.title !== "") { set({ successData: newState, - successOpen: true, notificationCenter: true, - notificationList: pushNotificationList(get().notificationList, { - type: "success", - title: newState.title, - id: uniqueId(), - }), + notificationList: [ + { + type: "success", + title: newState.title, + id: uniqueId(), + }, + ...get().notificationList, + ], }); + const tempList = get().tempNotificationList; + if ( + !tempList.some((item) => { + return ( + customStringify({ title: item.title, type: item.type }) === + customStringify({ ...newState, type: "success" }) + ); + }) + ) { + set({ + tempNotificationList: [ + { + type: "success", + title: newState.title, + id: uniqueId(), + }, + ...get().tempNotificationList, + ], + }); + } } }, - setSuccessOpen: (newState: boolean) => { - set({ successOpen: newState }); - }, setNotificationCenter: (newState: boolean) => { set({ notificationCenter: newState }); }, @@ -90,6 +154,16 @@ const useAlertStore = create((set, get) => ({ setLoading: (newState: boolean) => { set({ loading: newState }); }, + clearTempNotificationList: () => { + set({ tempNotificationList: [] }); + }, + removeFromTempNotificationList: (index: string) => { + set({ + tempNotificationList: get().tempNotificationList.filter( + (item) => item.id !== index + ), + }); + }, })); export default useAlertStore; diff --git a/src/frontend/src/stores/darkStore.tsx b/src/frontend/src/stores/darkStore.tsx index 6278e59c7..f3ccc2e5c 100644 --- a/src/frontend/src/stores/darkStore.tsx +++ b/src/frontend/src/stores/darkStore.tsx @@ -2,9 +2,11 @@ import { create } from "zustand"; import { getRepoStars, getVersion } from "../controllers/API"; import { DarkStoreType } from "../types/zustand/dark"; -export const useDarkStore = create((set) => ({ +const startedStars = Number(window.localStorage.getItem("githubStars")) ?? 0; + +export const useDarkStore = create((set, get) => ({ dark: JSON.parse(window.localStorage.getItem("isDark")!) ?? false, - stars: 0, + stars: startedStars, version: "", setDark: (dark) => set(() => ({ dark: dark })), refreshVersion: () => { @@ -13,8 +15,23 @@ export const useDarkStore = create((set) => ({ }); }, refreshStars: () => { - getRepoStars("logspace-ai", "langflow").then((res) => { - set(() => ({ stars: res })); - }); + let lastUpdated = window.localStorage.getItem("githubStarsLastUpdated"); + let diff = 0; + // check if lastUpdated actually exists + if (lastUpdated !== null) { + diff = Math.abs(new Date().getTime() - new Date(lastUpdated).getTime()); + } + + // if lastUpdated is null or the difference is greater than 2 hours + if (lastUpdated === null || diff > 7200000) { + getRepoStars("logspace-ai", "langflow").then((res) => { + window.localStorage.setItem("githubStars", res.toString()); + window.localStorage.setItem( + "githubStarsLastUpdated", + new Date().toString() + ); + set(() => ({ stars: res, lastUpdated: new Date() })); + }); + } }, })); diff --git a/src/frontend/src/stores/flowStore.ts b/src/frontend/src/stores/flowStore.ts index cb117196f..bcc8f6309 100644 --- a/src/frontend/src/stores/flowStore.ts +++ b/src/frontend/src/stores/flowStore.ts @@ -1,4 +1,4 @@ -import { cloneDeep } from "lodash"; +import { cloneDeep, zip } from "lodash"; import { Edge, EdgeChange, @@ -9,55 +9,123 @@ import { applyNodeChanges, } from "reactflow"; import { create } from "zustand"; +import { + FLOW_BUILD_SUCCESS_ALERT, + MISSED_ERROR_ALERT, +} from "../constants/alerts_constants"; +import { BuildStatus } from "../constants/enums"; +import { getFlowPool } from "../controllers/API"; +import { VertexBuildTypeAPI } from "../types/api"; import { NodeDataType, NodeType, sourceHandleType, targetHandleType, } from "../types/flow"; -import { FlowStoreType } from "../types/zustand/flow"; import { + ChatOutputType, + FlowPoolObjectType, + FlowStoreType, + VertexLayerElementType, + chatInputType, +} from "../types/zustand/flow"; +import { buildVertices } from "../utils/buildUtils"; +import { + checkChatInput, cleanEdges, getHandleId, getNodeId, scapeJSONParse, scapedJSONStringfy, + updateGroupRecursion, + validateNodes, } from "../utils/reactflowUtils"; +import { getInputsAndOutputs } from "../utils/storeUtils"; +import useAlertStore from "./alertStore"; +import { useDarkStore } from "./darkStore"; import useFlowsManagerStore from "./flowsManagerStore"; // this is our useStore hook that we can use in our components to get parts of the store and call actions const useFlowStore = create((set, get) => ({ - sseData: {}, flowState: undefined, + flowBuildStatus: {}, nodes: [], edges: [], isBuilding: false, - isPending: false, - isBuilt: false, + isPending: true, + hasIO: false, reactFlowInstance: null, lastCopiedSelection: null, + flowPool: {}, + inputs: [], + outputs: [], + setFlowPool: (flowPool) => { + set({ flowPool }); + }, + addDataToFlowPool: (data: FlowPoolObjectType, nodeId: string) => { + let newFlowPool = cloneDeep({ ...get().flowPool }); + if (!newFlowPool[nodeId]) newFlowPool[nodeId] = [data]; + else { + newFlowPool[nodeId].push(data); + } + get().setFlowPool(newFlowPool); + }, + getNodePosition: (nodeId: string) => { + const node = get().nodes.find((node) => node.id === nodeId); + return node?.position || { x: 0, y: 0 }; + }, + updateFlowPool: ( + nodeId: string, + data: FlowPoolObjectType | ChatOutputType | chatInputType, + buildId?: string + ) => { + let newFlowPool = cloneDeep({ ...get().flowPool }); + if (!newFlowPool[nodeId]) { + return; + } else { + let index = newFlowPool[nodeId].length - 1; + if (buildId) { + index = newFlowPool[nodeId].findIndex((flow) => flow.id === buildId); + } + //check if the data is a flowpool object + if ((data as FlowPoolObjectType).data?.artifacts !== undefined) { + newFlowPool[nodeId][index] = data as FlowPoolObjectType; + } + //update data artifact + else { + newFlowPool[nodeId][index].data.artifacts = data; + } + } + get().setFlowPool(newFlowPool); + }, + CleanFlowPool: () => { + get().setFlowPool({}); + }, setPending: (isPending) => { set({ isPending }); }, resetFlow: ({ nodes, edges, viewport }) => { + const currentFlow = useFlowsManagerStore.getState().currentFlow; + let newEdges = cleanEdges(nodes, edges); + const { inputs, outputs } = getInputsAndOutputs(nodes); set({ nodes, - edges, + edges: newEdges, flowState: undefined, - sseData: {}, - isBuilt: false, + inputs, + outputs, + hasIO: inputs.length > 0 || outputs.length > 0, }); get().reactFlowInstance!.setViewport(viewport); - }, - updateSSEData: (sseData) => { - set((state) => ({ sseData: { ...state.sseData, ...sseData } })); + if (currentFlow) { + getFlowPool({ flowId: currentFlow.id }).then((flowPool) => { + set({ flowPool: flowPool.data.vertex_builds }); + }); + } }, setIsBuilding: (isBuilding) => { set({ isBuilding }); }, - setIsBuilt: (isBuilt) => { - set({ isBuilt }); - }, setFlowState: (flowState) => { const newFlowState = typeof flowState === "function" ? flowState(get().flowState) : flowState; @@ -84,50 +152,53 @@ const useFlowStore = create((set, get) => ({ setNodes: (change) => { let newChange = typeof change === "function" ? change(get().nodes) : change; let newEdges = cleanEdges(newChange, get().edges); + const { inputs, outputs } = getInputsAndOutputs(newChange); set({ edges: newEdges, nodes: newChange, flowState: undefined, - isBuilt: false, - sseData: {}, + inputs, + outputs, + hasIO: inputs.length > 0 || outputs.length > 0, }); const flowsManager = useFlowsManagerStore.getState(); - - flowsManager.autoSaveCurrentFlow( - newChange, - newEdges, - get().reactFlowInstance?.getViewport() ?? { x: 0, y: 0, zoom: 1 } - ); + if (!get().isBuilding) { + flowsManager.autoSaveCurrentFlow( + newChange, + newEdges, + get().reactFlowInstance?.getViewport() ?? { x: 0, y: 0, zoom: 1 } + ); + } }, setEdges: (change) => { let newChange = typeof change === "function" ? change(get().edges) : change; - set({ edges: newChange, flowState: undefined, - isBuilt: false, - sseData: {}, }); const flowsManager = useFlowsManagerStore.getState(); - - flowsManager.autoSaveCurrentFlow( - get().nodes, - newChange, - get().reactFlowInstance?.getViewport() ?? { x: 0, y: 0, zoom: 1 } - ); + if (!get().isBuilding) { + flowsManager.autoSaveCurrentFlow( + get().nodes, + newChange, + get().reactFlowInstance?.getViewport() ?? { x: 0, y: 0, zoom: 1 } + ); + } }, setNode: (id: string, change: Node | ((oldState: Node) => Node)) => { let newChange = typeof change === "function" ? change(get().nodes.find((node) => node.id === id)!) : change; - get().setNodes((oldNodes) => oldNodes.map((node) => { if (node.id === id) { + if ((node.data as NodeDataType).node?.frozen) { + (newChange.data as NodeDataType).node!.frozen = false; + } return newChange; } return node; @@ -156,6 +227,18 @@ const useFlowStore = create((set, get) => ({ ); }, paste: (selection, position) => { + function updateGroup() {} + + if ( + selection.nodes.some((node) => node.data.type === "ChatInput") && + checkChatInput(get().nodes) + ) { + useAlertStore.getState().setErrorData({ + title: "Error pasting components", + list: ["You can only have one ChatInput component in the flow"], + }); + return; + } let minimumX = Infinity; let minimumY = Infinity; let idsMap = {}; @@ -182,6 +265,8 @@ const useFlowStore = create((set, get) => ({ let newId = getNodeId(node.data.type); idsMap[node.id] = newId; + updateGroupRecursion(node, selection.edges); + // Create a new node object const newNode: NodeType = { id: newId, @@ -235,11 +320,7 @@ const useFlowStore = create((set, get) => ({ id, data: cloneDeep(edge.data), style: { stroke: "#555" }, - className: - targetHandleObject.type === "Text" - ? "stroke-gray-800 " - : "stroke-gray-900 ", - animated: targetHandleObject.type === "Text", + className: "stroke-gray-900 ", selected: false, }, newEdges.map((edge) => ({ ...edge, selected: false })) @@ -277,8 +358,6 @@ const useFlowStore = create((set, get) => ({ nodes: [], edges: [], flowState: undefined, - sseData: {}, - isBuilt: false, getFilterEdge: [], }); }, @@ -287,6 +366,31 @@ const useFlowStore = create((set, get) => ({ }, getFilterEdge: [], onConnect: (connection) => { + const dark = useDarkStore.getState().dark; + // const commonMarkerProps = { + // type: MarkerType.ArrowClosed, + // width: 20, + // height: 20, + // color: dark ? "#555555" : "#000000", + // }; + + // const inputTypes = INPUT_TYPES; + // const outputTypes = OUTPUT_TYPES; + + // const findNode = useFlowStore + // .getState() + // .nodes.find( + // (node) => node.id === connection.source || node.id === connection.target + // ); + + // const sourceType = findNode?.data?.type; + // let isIoIn = false; + // let isIoOut = false; + // if (sourceType) { + // isIoIn = inputTypes.has(sourceType); + // isIoOut = outputTypes.has(sourceType); + // } + let newEdges: Edge[] = []; get().setEdges((oldEdges) => { newEdges = addEdge( @@ -297,17 +401,11 @@ const useFlowStore = create((set, get) => ({ sourceHandle: scapeJSONParse(connection.sourceHandle!), }, style: { stroke: "#555" }, - className: - ((scapeJSONParse(connection.targetHandle!) as targetHandleType) - .type === "Text" - ? "stroke-foreground " - : "stroke-foreground ") + " stroke-connection", - animated: - (scapeJSONParse(connection.targetHandle!) as targetHandleType) - .type === "Text", + className: "stroke-foreground stroke-connection", }, oldEdges ); + return newEdges; }); useFlowsManagerStore @@ -329,6 +427,204 @@ const useFlowStore = create((set, get) => ({ }); }); }, + buildFlow: async ({ + startNodeId, + stopNodeId, + input_value, + }: { + startNodeId?: string; + stopNodeId?: string; + input_value?: string; + }) => { + get().setIsBuilding(true); + const currentFlow = useFlowsManagerStore.getState().currentFlow; + const setSuccessData = useAlertStore.getState().setSuccessData; + const setErrorData = useAlertStore.getState().setErrorData; + const setNoticeData = useAlertStore.getState().setNoticeData; + function validateSubgraph(nodes: string[]) { + const errorsObjs = validateNodes( + get().nodes.filter((node) => nodes.includes(node.id)), + get().edges + ); + + const errors = errorsObjs.map((obj) => obj.errors).flat(); + if (errors.length > 0) { + setErrorData({ + title: MISSED_ERROR_ALERT, + list: errors, + }); + get().setIsBuilding(false); + const ids = errorsObjs.map((obj) => obj.id).flat(); + + get().updateBuildStatus(ids, BuildStatus.ERROR); + throw new Error("Invalid nodes"); + } + } + function handleBuildUpdate( + vertexBuildData: VertexBuildTypeAPI, + status: BuildStatus, + runId: string + ) { + if (vertexBuildData && vertexBuildData.inactivated_vertices) { + get().removeFromVerticesBuild(vertexBuildData.inactivated_vertices); + } + + if (vertexBuildData.next_vertices_ids) { + // next_vertices_ids is a list of vertices that are going to be built next + // verticesLayers is a list of list of vertices ids, where each list is a layer of vertices + // we want to add a new layer (next_vertices_ids) to the list of layers (verticesLayers) + // and the values of next_vertices_ids to the list of vertices ids (verticesIds) + + // const nextVertices will be the zip of vertexBuildData.next_vertices_ids and + // vertexBuildData.top_level_vertices + // the VertexLayerElementType as {id: next_vertices_id, layer: top_level_vertex} + const nextVertices: VertexLayerElementType[] = zip( + vertexBuildData.next_vertices_ids, + vertexBuildData.top_level_vertices + ).map(([id, reference]) => ({ id: id!, reference })); + + const newLayers = [ + ...get().verticesBuild!.verticesLayers, + nextVertices, + ]; + const newIds = [ + ...get().verticesBuild!.verticesIds, + ...vertexBuildData.next_vertices_ids, + ]; + get().updateVerticesBuild({ + verticesIds: newIds, + verticesLayers: newLayers, + runId: runId, + verticesToRun: get().verticesBuild!.verticesToRun, + }); + get().updateBuildStatus( + vertexBuildData.top_level_vertices, + BuildStatus.TO_BUILD + ); + } + + get().addDataToFlowPool( + { ...vertexBuildData, buildId: runId }, + vertexBuildData.id + ); + + useFlowStore.getState().updateBuildStatus([vertexBuildData.id], status); + + const verticesIds = get().verticesBuild?.verticesIds; + const newFlowBuildStatus = { ...get().flowBuildStatus }; + // filter out the vertices that are not status + const verticesToUpdate = verticesIds?.filter( + (id) => newFlowBuildStatus[id]?.status !== BuildStatus.BUILT + ); + + if (verticesToUpdate) { + useFlowStore.getState().updateBuildStatus(verticesToUpdate, status); + } + } + await buildVertices({ + input_value, + flowId: currentFlow!.id, + startNodeId, + stopNodeId, + onGetOrderSuccess: () => { + setNoticeData({ title: "Running components" }); + }, + onBuildComplete: (allNodesValid) => { + const nodeId = startNodeId || stopNodeId; + if (nodeId && allNodesValid) { + setSuccessData({ + title: `${ + get().nodes.find((node) => node.id === nodeId)?.data.node + ?.display_name + } built successfully`, + }); + } else { + setSuccessData({ title: FLOW_BUILD_SUCCESS_ALERT }); + } + get().setIsBuilding(false); + }, + onBuildUpdate: handleBuildUpdate, + onBuildError: (title: string, list: string[], elementList) => { + const idList = elementList + .map((element) => element.id) + .filter(Boolean) as string[]; + useFlowStore.getState().updateBuildStatus(idList, BuildStatus.BUILT); + setErrorData({ list, title }); + get().setIsBuilding(false); + }, + onBuildStart: (elementList) => { + const idList = elementList + // reference is the id of the vertex or the id of the parent in a group node + .map((element) => element.reference) + .filter(Boolean) as string[]; + useFlowStore.getState().updateBuildStatus(idList, BuildStatus.BUILDING); + }, + onValidateNodes: validateSubgraph, + }); + get().setIsBuilding(false); + get().revertBuiltStatusFromBuilding(); + }, + getFlow: () => { + return { + nodes: get().nodes, + edges: get().edges, + viewport: get().reactFlowInstance?.getViewport()!, + }; + }, + updateVerticesBuild: ( + vertices: { + verticesIds: string[]; + verticesLayers: VertexLayerElementType[][]; + runId: string; + verticesToRun: string[]; + } | null + ) => { + set({ verticesBuild: vertices }); + }, + verticesBuild: null, + addToVerticesBuild: (vertices: string[]) => { + const verticesBuild = get().verticesBuild; + if (!verticesBuild) return; + set({ + verticesBuild: { + ...verticesBuild, + verticesIds: [...verticesBuild.verticesIds, ...vertices], + }, + }); + }, + removeFromVerticesBuild: (vertices: string[]) => { + const verticesBuild = get().verticesBuild; + if (!verticesBuild) return; + set({ + verticesBuild: { + ...verticesBuild, + verticesIds: get().verticesBuild!.verticesIds.filter( + (vertex) => !vertices.includes(vertex) + ), + }, + }); + }, + updateBuildStatus: (nodeIdList: string[], status: BuildStatus) => { + const newFlowBuildStatus = { ...get().flowBuildStatus }; + nodeIdList.forEach((id) => { + newFlowBuildStatus[id] = { + status, + }; + if (status == BuildStatus.BUILT) { + const timestamp_string = new Date(Date.now()).toLocaleString(); + newFlowBuildStatus[id].timestamp = timestamp_string; + } + }); + set({ flowBuildStatus: newFlowBuildStatus }); + }, + revertBuiltStatusFromBuilding: () => { + const newFlowBuildStatus = { ...get().flowBuildStatus }; + Object.keys(newFlowBuildStatus).forEach((id) => { + if (newFlowBuildStatus[id].status === BuildStatus.BUILDING) { + newFlowBuildStatus[id].status = BuildStatus.BUILT; + } + }); + }, })); export default useFlowStore; diff --git a/src/frontend/src/stores/flowsManagerStore.ts b/src/frontend/src/stores/flowsManagerStore.ts index 4a64b3125..9471889c3 100644 --- a/src/frontend/src/stores/flowsManagerStore.ts +++ b/src/frontend/src/stores/flowsManagerStore.ts @@ -1,7 +1,11 @@ import { AxiosError } from "axios"; -import { cloneDeep } from "lodash"; +import { cloneDeep, debounce } from "lodash"; import { Edge, Node, Viewport, XYPosition } from "reactflow"; import { create } from "zustand"; +import { + SAVE_DEBOUNCE_TIME, + STARTER_FOLDER_NAME, +} from "../constants/constants"; import { deleteFlowFromDatabase, readFlowsFromDatabase, @@ -37,6 +41,10 @@ const past = {}; const future = {}; const useFlowsManagerStore = create((set, get) => ({ + examples: [], + setExamples: (examples: FlowType[]) => { + set({ examples }); + }, currentFlowId: "", setCurrentFlowId: (currentFlowId: string) => { set((state) => ({ @@ -52,6 +60,7 @@ const useFlowsManagerStore = create((set, get) => ({ }); }, currentFlow: undefined, + saveLoading: false, isLoading: true, setIsLoading: (isLoading: boolean) => set({ isLoading }), refreshFlows: () => { @@ -61,7 +70,16 @@ const useFlowsManagerStore = create((set, get) => ({ .then((dbData) => { if (dbData) { const { data, flows } = processFlows(dbData, false); - get().setFlows(flows); + get().setExamples( + flows.filter( + (f) => f.folder === STARTER_FOLDER_NAME && !f.user_id + ) + ); + get().setFlows( + flows.filter( + (f) => !(f.folder === STARTER_FOLDER_NAME && !f.user_id) + ) + ); useTypesStore.setState((state) => ({ data: { ...state.data, ["saved_components"]: data }, })); @@ -70,6 +88,7 @@ const useFlowsManagerStore = create((set, get) => ({ } }) .catch((e) => { + set({ isLoading: false }); useAlertStore.getState().setErrorData({ title: "Could not load flows from database", }); @@ -78,22 +97,19 @@ const useFlowsManagerStore = create((set, get) => ({ }); }, autoSaveCurrentFlow: (nodes: Node[], edges: Edge[], viewport: Viewport) => { - // Clear the previous timeout if it exists. - if (saveTimeoutId) { - clearTimeout(saveTimeoutId); + if (get().currentFlow) { + get().saveFlow( + { ...get().currentFlow!, data: { nodes, edges, viewport } }, + true + ); } - - // Set up a new timeout. - saveTimeoutId = setTimeout(() => { - if (get().currentFlow) { - get().saveFlow( - { ...get().currentFlow!, data: { nodes, edges, viewport } }, - true - ); - } - }, 300); // Delay of 300ms. }, saveFlow: (flow: FlowType, silent?: boolean) => { + set({ saveLoading: true }); // set saveLoading true immediately + return get().saveFlowDebounce(flow, silent); // call the debounced function directly + }, + saveFlowDebounce: debounce((flow: FlowType, silent?: boolean) => { + set({ saveLoading: true }); return new Promise((resolve, reject) => { updateFlowInDatabase(flow) .then((updatedFlow) => { @@ -115,6 +131,7 @@ const useFlowsManagerStore = create((set, get) => ({ //update tabs state resolve(); + set({ saveLoading: false }); } }) .catch((err) => { @@ -125,7 +142,7 @@ const useFlowsManagerStore = create((set, get) => ({ reject(err); }); }); - }, + }, SAVE_DEBOUNCE_TIME), uploadFlows: () => { return new Promise((resolve) => { const input = document.createElement("input"); diff --git a/src/frontend/src/stores/globalVariables.ts b/src/frontend/src/stores/globalVariables.ts new file mode 100644 index 000000000..e2f3e37df --- /dev/null +++ b/src/frontend/src/stores/globalVariables.ts @@ -0,0 +1,34 @@ +import { create } from "zustand"; +import { GlobalVariablesStore } from "../types/zustand/globalVariables"; + +export const useGlobalVariablesStore = create( + (set, get) => ({ + globalVariablesEntries: [], + globalVariables: {}, + setGlobalVariables: (variables) => { + set({ + globalVariables: variables, + globalVariablesEntries: Object.keys(variables), + }); + }, + addGlobalVariable: (name, id, type) => { + const data = { id, type }; + const newVariables = { ...get().globalVariables, [name]: data }; + set({ + globalVariables: newVariables, + globalVariablesEntries: Object.keys(newVariables), + }); + }, + removeGlobalVariable: (name) => { + const newVariables = { ...get().globalVariables }; + delete newVariables[name]; + set({ + globalVariables: newVariables, + globalVariablesEntries: Object.keys(newVariables), + }); + }, + getVariableId: (name) => { + return get().globalVariables[name]?.id; + }, + }) +); diff --git a/src/frontend/src/stores/shortcuts.ts b/src/frontend/src/stores/shortcuts.ts new file mode 100644 index 000000000..798613708 --- /dev/null +++ b/src/frontend/src/stores/shortcuts.ts @@ -0,0 +1,15 @@ +import { create } from "zustand"; +import { shortcutsStoreType } from "../types/store"; + +export const useShortcutsStore = create((set, get) => ({ + openCodeModalWShortcut: false, + handleModalWShortcut: (modal) => { + switch (modal) { + case "code": + set({ + openCodeModalWShortcut: !get().openCodeModalWShortcut, + }); + break; + } + }, +})); diff --git a/src/frontend/src/stores/typesStore.ts b/src/frontend/src/stores/typesStore.ts index 557a3a30d..808a5d646 100644 --- a/src/frontend/src/stores/typesStore.ts +++ b/src/frontend/src/stores/typesStore.ts @@ -27,10 +27,6 @@ export const useTypesStore = create((set, get) => ({ resolve(); }) .catch((error) => { - useAlertStore.getState().setErrorData({ - title: "An error has occurred while fetching types.", - list: ["Please refresh the page."], - }); console.error("An error has occurred while fetching types."); console.log(error); reject(); diff --git a/src/frontend/src/style/applies.css b/src/frontend/src/style/applies.css index e2bcdb7d9..8900938bf 100644 --- a/src/frontend/src/style/applies.css +++ b/src/frontend/src/style/applies.css @@ -69,7 +69,7 @@ @apply flex h-full w-[14.5rem] flex-col overflow-hidden border-r scrollbar-hide; } .side-bar-search-div-placement { - @apply relative mx-auto mb-2 mt-2 flex items-center; + @apply relative mx-auto flex items-center py-3; } .side-bar-components-icon { @apply h-6 w-4 text-ring; @@ -114,7 +114,10 @@ @apply pointer-events-none; } .extra-side-bar-buttons { - @apply relative inline-flex w-full items-center justify-center rounded-md bg-background px-2 py-2 text-foreground shadow-sm ring-1 ring-inset ring-input transition-all duration-500 ease-in-out; + @apply relative inline-flex w-full items-center justify-center rounded-md bg-background px-2 py-2 text-foreground transition-all duration-500 ease-in-out; + } + .header-menubar-item { + @apply relative flex cursor-default cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50; } .extra-side-bar-buttons:hover { @apply hover:bg-muted; @@ -175,14 +178,24 @@ @apply fixed bottom-4 right-4; } .message-button-icon { - @apply fill-chat-trigger stroke-chat-trigger stroke-1; + @apply fill-medium-indigo stroke-medium-indigo stroke-1; } .disabled-message-button-icon { @apply fill-chat-trigger-disabled stroke-chat-trigger-disabled stroke-1; } + .parent-disclosure-arrangement { + @apply flex w-full select-none items-center justify-between bg-background px-3 py-1; + } .components-disclosure-arrangement { @apply -mt-px flex w-full select-none items-center justify-between border-y border-y-input bg-muted px-3 py-2; } + .components-disclosure-arrangement-child { + /* different color than the non child */ + @apply -mt-px flex w-full select-none items-center justify-between border-y border-y-input bg-muted px-3 py-2; + } + .parent-disclosure-title { + @apply p-2 px-2 text-sm font-medium; + } .components-disclosure-title { @apply flex items-center text-sm text-primary; } @@ -267,7 +280,7 @@ @apply relative flex flex-col justify-center bg-background; } .generic-node-div-title { - @apply flex w-full items-center gap-8 border-b bg-muted p-4; + @apply flex w-full items-center gap-2 border-b bg-muted p-4; } .generic-node-title-arrangement { @apply flex-max-width items-center truncate; @@ -276,33 +289,53 @@ @apply h-10 w-10 rounded p-1; } .generic-node-tooltip-div { - @apply ml-2 truncate; + @apply ml-2 max-w-[220px] truncate; } .generic-node-validation-div { @apply max-h-96 overflow-auto; } .generic-node-status-position { - @apply relative top-[3px] h-5 w-5; + @apply h-5 w-5; } .generic-node-status-animation { @apply hidden h-4 w-4 animate-spin rounded-full bg-ring opacity-0; } .generic-node-status { - @apply h-4 w-4 rounded-full opacity-100; + @apply animate-wiggle opacity-100; } .green-status { - @apply generic-node-status bg-status-green; + @apply generic-node-status text-status-green; } + .gray-status { + @apply generic-node-status text-status-gray; + } + .red-status { - @apply generic-node-status bg-status-red; + @apply generic-node-status text-status-red; } .yellow-status { - @apply generic-node-status bg-status-yellow; + @apply generic-node-status text-status-yellow; + } + .inactive-status { + /* what colour for inactive status? + muted-foreground is too strong, maybe use a lighter shade of it? + + */ + @apply border-none ring ring-muted-foreground; + } + .built-invalid-status { + @apply border-none ring ring-[#FF9090]; + } + .built-invalid-status-dark { + @apply border-none ring ring-[#751C1C]; + } + .building-status { + @apply border-none ring; } .status-build-animation { - @apply hidden h-4 w-4 animate-spin rounded-full bg-ring opacity-0; + @apply opacity-0; } .status-div { @apply absolute w-4 duration-200 ease-in-out; @@ -411,7 +444,9 @@ .code-area-external-link:hover { @apply hover:text-accent-foreground; } - + .dropdown-component-disabled { + @apply pointer-events-none cursor-not-allowed; + } .dropdown-component-outline { @apply input-edit-node relative pr-8; } @@ -421,11 +456,17 @@ .dropdown-component-display { @apply block w-full truncate bg-background; } + .dropdown-component-display-disabled { + @apply text-muted-foreground; + } .dropdown-component-arrow { - @apply pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2; + @apply pointer-events-none absolute inset-y-0 flex items-center pr-2; } .dropdown-component-arrow-color { - @apply extra-side-bar-save-disable h-5 w-5; + @apply h-5 w-5 text-accent-foreground; + } + .dropdown-component-arrow-color-disable { + @apply h-5 w-5 text-muted-foreground; } .dropdown-component-options { @apply z-10 mt-1 max-h-60 overflow-auto rounded-md bg-background py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm; @@ -449,7 +490,7 @@ @apply absolute inset-y-0 right-0 flex items-center pr-4; } .dropdown-component-check-icon { - @apply h-5 w-5 text-black; + @apply h-5 w-5 text-primary; } .edit-flow-arrangement { @@ -467,7 +508,7 @@ @apply flex items-center gap-0.5 rounded-md px-1.5 py-1 text-sm font-medium; } .header-menu-bar-display { - @apply flex max-w-[120px] cursor-pointer items-center gap-2 lg:max-w-[200px]; + @apply flex max-w-[115px] cursor-pointer items-center gap-2 lg:max-w-[145px]; } .header-menu-flow-name { @apply flex-1 truncate; @@ -553,7 +594,7 @@ } .app-div { - @apply fixed bottom-5 left-5 flex flex-col-reverse; + @apply absolute bottom-5 left-5 flex flex-col-reverse; } .chat-input-modal-txtarea { @@ -825,13 +866,13 @@ } .api-modal-tabs { - @apply flex h-full max-w-full flex-col overflow-hidden rounded-md border bg-muted text-center sm:w-[75vw] md:w-[75vw] lg:w-[75vw] xl:w-[76vw] 2xl:w-full; + @apply flex h-full flex-col overflow-hidden rounded-md border bg-muted text-center; } .api-modal-tablist-div { - @apply flex items-center justify-between px-2; + @apply flex items-center justify-between px-2 py-2; } .api-modal-tabs-content { - @apply -mt-1 h-full w-full overflow-hidden px-4 pb-4; + @apply -mt-1 h-full w-full px-4 pb-4; } .api-modal-accordion-display { @apply mt-2 flex h-full w-full; @@ -876,13 +917,13 @@ @apply mr-2 h-5 w-5 rotate-[44deg]; } .form-modal-play-icon { - @apply mx-1 h-5 w-5; + @apply mx-1 h-5 w-5 fill-current; } .form-modal-chat-position { @apply flex-max-width px-2 py-6 pl-4 pr-9; } .form-modal-chatbot-icon { - @apply mb-3 ml-3 mr-6 mt-1; + @apply mb-3 ml-3 mr-6 mt-1 flex flex-col; } .form-modal-chat-image { @apply flex flex-col items-center gap-1; @@ -926,9 +967,6 @@ .form-modal-initial-prompt-btn { @apply mb-2 flex items-center gap-2 rounded-md border border-border bg-background px-4 py-2 text-sm font-semibold shadow-sm; } - .form-modal-iv-box { - @apply flex-max-width mt-2 h-[80vh]; - } .form-modal-iv-size { @apply mr-6 flex h-full w-2/6 flex-col justify-start overflow-auto scrollbar-hide; } @@ -1012,7 +1050,7 @@ } .beta-badge-wrapper { - @apply absolute right-0 top-0 h-16 w-16 overflow-hidden rounded-tr-lg; + @apply pointer-events-none absolute right-0 top-0 h-16 w-16 overflow-hidden rounded-tr-lg; } .beta-badge-content { @apply mt-2 w-24 rotate-45 bg-beta-background text-center text-xs font-semibold text-beta-foreground; diff --git a/src/frontend/src/style/index.css b/src/frontend/src/style/index.css index 0185d25b7..e744fb503 100644 --- a/src/frontend/src/style/index.css +++ b/src/frontend/src/style/index.css @@ -27,6 +27,7 @@ --radius: 0.5rem; --ring: 215 20.2% 65.1%; /* hsl(215 20% 65%) */ --round-btn-shadow: #00000063; + --ice: #31a3cc; --error-background: #fef2f2; --error-foreground: #991b1b; @@ -49,6 +50,9 @@ --component-icon: #d8598a; --flow-icon: #2f67d0; + --hover: #F2F4F5; + --disabled-run: #6366f1; + /* Colors that are shared in dark and light mode */ --blur-shared: #151923de; @@ -60,12 +64,16 @@ --chat-send: #059669; --status-green: #4ade80; --status-blue: #2563eb; + --status-gray: #6b7280; --connection: #555; } .dark { --background: 224 35% 7.5%; /* hsl(224 40% 10%) */ --foreground: 213 31% 80%; /* hsl(213 31% 91%) */ + --ice: #60A5FA; + --hover: #1A202E; + --disabled-run: #6366f1; --muted: 223 27% 11%; /* hsl(223 27% 11%) */ --muted-foreground: 215.4 16.3% 56.9%; /* hsl(215 16% 56%) */ diff --git a/src/frontend/src/types/api/index.ts b/src/frontend/src/types/api/index.ts index 46e62376c..faef230a5 100644 --- a/src/frontend/src/types/api/index.ts +++ b/src/frontend/src/types/api/index.ts @@ -18,6 +18,8 @@ export type APIClassType = { template: APITemplateType; display_name: string; icon?: string; + is_input?: boolean; + is_output?: boolean; input_types?: Array; output_types?: Array; custom_fields?: CustomFieldsType; @@ -25,7 +27,9 @@ export type APIClassType = { documentation: string; error?: string; official?: boolean; + frozen?: boolean; flow?: FlowType; + field_order?: string[]; [key: string]: | Array | string @@ -51,6 +55,9 @@ export type TemplateVariableType = { input_types?: Array; display_name?: string; name?: string; + real_time_refresh?: boolean; + refresh_button?: boolean; + refresh_button_text?: string; [key: string]: any; }; export type sendAllProps = { @@ -129,3 +136,47 @@ export type Component = { data: Object; tags: [string]; }; + +export type VerticesOrderTypeAPI = { + ids: Array; + vertices_to_run: Array; + run_id: string; +}; + +export type VertexBuildTypeAPI = { + id: string; + inactivated_vertices: Array | null; + next_vertices_ids: Array; + top_level_vertices: Array; + run_id: string; + valid: boolean; + params: string; + data: VertexDataTypeAPI; + timestamp: string; +}; + +// data is the object received by the API +// it has results, artifacts, timedelta, duration +export type VertexDataTypeAPI = { + results: { [key: string]: { [key: string]: string } }; + artifacts: { [key: string]: string }; + timedelta?: number; + duration?: string; +}; + +export type CodeErrorDataTypeAPI = { + error: string | undefined; + traceback: string | undefined; +}; + +// the error above is inside this error.response.data.detail.error +// which comes from a request to the API +// to type the error we need to know the structure of the object + +// error that has a response, that has a data, that has a detail, that has an error +export type ResponseErrorTypeAPI = { + response: { data: { detail: CodeErrorDataTypeAPI } }; +}; +export type ResponseErrorDetailAPI = { + response: { data: { detail: string } }; +}; diff --git a/src/frontend/src/types/chat/index.ts b/src/frontend/src/types/chat/index.ts index 62cb4eb78..e24c6e891 100644 --- a/src/frontend/src/types/chat/index.ts +++ b/src/frontend/src/types/chat/index.ts @@ -8,5 +8,27 @@ export type ChatMessageType = { thought?: string; files?: Array<{ data: string; type: string; data_type: string }>; prompt?: string; - chatKey: string; + chatKey?: string; + componentId: string; + stream_url?: string | null; + sender_name?: string; +}; + +export type ChatOutputType = { + message: string; + sender: string; + sender_name: string; + stream_url?: string; +}; + +export type chatInputType = { + result: string; +}; + +export type FlowPoolObjectType = { + timestamp: string; + valid: boolean; + params: any; + data: { artifacts: any; results: any | ChatOutputType | chatInputType }; + id: string; }; diff --git a/src/frontend/src/types/components/index.ts b/src/frontend/src/types/components/index.ts index d78ce867c..469749b88 100644 --- a/src/frontend/src/types/components/index.ts +++ b/src/frontend/src/types/components/index.ts @@ -1,5 +1,6 @@ -import { ReactElement, ReactNode } from "react"; -import { ReactFlowJsonObject, XYPosition } from "reactflow"; +import { ReactElement, ReactNode, SetStateAction } from "react"; +import { ReactFlowJsonObject } from "reactflow"; +import { InputOutput } from "../../constants/enums"; import { APIClassType, APITemplateType, TemplateVariableType } from "../api"; import { ChatMessageType } from "../chat"; import { FlowStyleType, FlowType, NodeDataType, NodeType } from "../flow/index"; @@ -7,9 +8,9 @@ import { sourceHandleType, targetHandleType } from "./../flow/index"; export type InputComponentType = { autoFocus?: boolean; onBlur?: (event: React.FocusEvent) => void; - value: string; + value?: string; disabled?: boolean; - onChange: (value: string) => void; + onChange?: (value: string) => void; password: boolean; required?: boolean; isForm?: boolean; @@ -20,6 +21,13 @@ export type InputComponentType = { className?: string; id?: string; blurOnEnter?: boolean; + optionsIcon?: string; + optionsPlaceholder?: string; + options?: string[]; + optionsButton?: ReactElement; + optionButton?: (option: string) => ReactElement; + selectedOption?: string; + setSelectedOption?: (value: string) => void; }; export type ToggleComponentType = { enabled: boolean; @@ -27,14 +35,15 @@ export type ToggleComponentType = { disabled: boolean | undefined; size: "small" | "medium" | "large"; id?: string; + editNode?: boolean; }; export type DropDownComponentType = { + disabled?: boolean; + isLoading?: boolean; value: string; options: string[]; onSelect: (value: string) => void; editNode?: boolean; - apiModal?: boolean; - numberOfOptions?: number; id?: string; }; export type ParameterComponentType = { @@ -61,6 +70,15 @@ export type InputListComponentType = { editNode?: boolean; }; +export type InputGlobalComponentType = { + disabled: boolean; + onChange: (value: string) => void; + setDb: (value: boolean) => void; + name: string; + data: NodeDataType; + editNode?: boolean; +}; + export type KeyPairListComponentType = { value: any; onChange: (value: Object[]) => void; @@ -68,6 +86,7 @@ export type KeyPairListComponentType = { editNode?: boolean; duplicateKey?: boolean; editNodeModal?: boolean; + isList?: boolean; }; export type DictComponentType = { @@ -103,6 +122,7 @@ export type PromptAreaComponentType = { }; export type CodeAreaComponentType = { + setOpenModal?: (bool: boolean) => void; disabled: boolean; onChange: (value: string[] | string) => void; value: string; @@ -112,9 +132,12 @@ export type CodeAreaComponentType = { dynamic?: boolean; id?: string; readonly?: boolean; + open?: boolean; + setOpen?: (open: boolean) => void; }; export type FileComponentType = { + IOInputProps?; disabled: boolean; onChange: (value: string[] | string) => void; value: string; @@ -126,6 +149,7 @@ export type FileComponentType = { export type DisclosureComponentType = { children: ReactNode; openDisc: boolean; + isChild?: boolean; button: { title: string; Icon: React.ElementType; @@ -146,6 +170,7 @@ export type RangeSpecType = { export type IntComponentType = { value: string; disabled?: boolean; + rangeSpec: RangeSpecType; onChange: (value: string) => void; editNode?: boolean; id?: string; @@ -194,6 +219,8 @@ export type AccordionComponentType = { open?: string[]; trigger?: string | ReactElement; keyValue?: string; + openDisc?: boolean; + sideBar?: boolean; }; export type Side = "top" | "right" | "bottom" | "left"; @@ -444,7 +471,7 @@ export type chatInputType = { }; lockChat: boolean; noInput: boolean; - sendMessage: () => void; + sendMessage: (count?: number) => void; setChatValue: (value: string) => void; }; @@ -475,10 +502,20 @@ export type fileCardPropsType = { export type nodeToolbarPropsType = { data: NodeDataType; deleteNode: (idx: string) => void; - position: XYPosition; setShowNode: (boolean: any) => void; numberOfHandles: number; showNode: boolean; + name?: string; + openAdvancedModal?: boolean; + onCloseAdvancedModal?: (close: boolean) => void; + selected: boolean; + updateNodeCode?: ( + newNodeClass: APIClassType, + code: string, + name: string + ) => void; + setShowState: (show: boolean | SetStateAction) => void; + isOutdated?: boolean; }; export type parsedDataType = { @@ -506,24 +543,27 @@ export type modalHeaderType = { export type codeAreaModalPropsType = { setValue: (value: string) => void; + setOpenModal?: (bool: boolean) => void; value: string; nodeClass: APIClassType | undefined; setNodeClass: (Class: APIClassType, code?: string) => void | undefined; children: ReactNode; dynamic?: boolean; readonly?: boolean; + open?: boolean; + setOpen?: (open: boolean) => void; }; export type chatMessagePropsType = { chat: ChatMessageType; lockChat: boolean; lastMessage: boolean; -}; - -export type formModalPropsType = { - open: boolean; - setOpen: Function; - flow: FlowType; + setLockChat: (lock: boolean) => void; + updateChat: ( + chat: ChatMessageType, + message: string, + stream_url?: string + ) => void; }; export type genericModalPropsType = { @@ -540,6 +580,18 @@ export type genericModalPropsType = { readonly?: boolean; }; +export type newFlowModalPropsType = { + open: boolean; + setOpen: (open: boolean) => void; +}; + +export type IOModalPropsType = { + children: JSX.Element; + open: boolean; + setOpen: (open: boolean) => void; + disable?: boolean; +}; + export type buttonBoxPropsType = { onClick: () => void; title: string; @@ -619,10 +671,11 @@ export type crashComponentPropsType = { export type validationStatusType = { id: string; + data: object | any; params: string; - progress: number; + progress?: number; valid: boolean; - duration: string; + duration?: string; }; export type ApiKey = { @@ -636,10 +689,55 @@ export type ApiKey = { export type fetchErrorComponentType = { message: string; description: string; + openModal?: boolean; + setRetry: () => void; + isLoadingHealth: boolean; }; export type dropdownButtonPropsType = { firstButtonName: string; onFirstBtnClick: () => void; options: Array<{ name: string; onBtnClick: () => void }>; + plusButton?: boolean; + dropdownOptions?: boolean; +}; + +export type IOFieldViewProps = { + type: InputOutput; + fieldType: string; + fieldId: string; + left?: boolean; +}; + +export type UndrawCardComponentProps = { flow: FlowType }; + +export type chatViewProps = { + sendMessage: (count?: number) => void; + chatValue: string; + setChatValue: (value: string) => void; + lockChat: boolean; + setLockChat: (lock: boolean) => void; +}; + +export type IOFileInputProps = { + field: TemplateVariableType; + updateValue: (e: any, type: string) => void; +}; + +export type toolbarSelectItemProps = { + isMac: boolean; + shift: boolean; + keyboardKey: string; + value: string; + icon: string; + styleObj?: { + iconClasses?: string; + commandClasses?: string; + shiftClasses?: string; + ctrlClasses?: string; + keyClasses?: string; + valueClasses?: string; + }; + dataTestId: string; + ping?: boolean; }; diff --git a/src/frontend/src/types/flow/index.ts b/src/frontend/src/types/flow/index.ts index 9f1821a08..8b259186a 100644 --- a/src/frontend/src/types/flow/index.ts +++ b/src/frontend/src/types/flow/index.ts @@ -1,4 +1,5 @@ import { ReactFlowJsonObject, XYPosition } from "reactflow"; +import { BuildStatus } from "../../constants/enums"; import { APIClassType } from "../api/index"; export type FlowType = { @@ -7,12 +8,17 @@ export type FlowType = { data: ReactFlowJsonObject | null; description: string; style?: FlowStyleType; - is_component: boolean; - parent?: string; - date_created?: string; - updated_at?: string; + is_component?: boolean; last_tested_version?: string; + updated_at?: string; + date_created?: string; + parent?: string; + folder?: string; + user_id?: string; + icon?: string; + icon_bg_color?: string; }; + export type NodeType = { id: string; type?: string; @@ -27,6 +33,7 @@ export type NodeDataType = { node?: APIClassType; id: string; output_types?: string[]; + buildStatus?: BuildStatus; }; // FlowStyleType is the type of the style object that is used to style the // Flow card with an emoji and a color. diff --git a/src/frontend/src/types/store/index.ts b/src/frontend/src/types/store/index.ts index 331e16e30..b116bbc3d 100644 --- a/src/frontend/src/types/store/index.ts +++ b/src/frontend/src/types/store/index.ts @@ -18,3 +18,8 @@ export type StoreComponentResponse = { authorized: boolean; results: storeComponent[]; }; + +export type shortcutsStoreType = { + openCodeModalWShortcut: boolean; + handleModalWShortcut: (str: string) => void; +}; diff --git a/src/frontend/src/types/zustand/alert/index.ts b/src/frontend/src/types/zustand/alert/index.ts index 1e273cc4e..7b2837517 100644 --- a/src/frontend/src/types/zustand/alert/index.ts +++ b/src/frontend/src/types/zustand/alert/index.ts @@ -3,19 +3,16 @@ import { AlertItemType } from "../../alerts"; export type AlertStoreType = { errorData: { title: string; list?: Array }; setErrorData: (newState: { title: string; list?: Array }) => void; - errorOpen: boolean; - setErrorOpen: (newState: boolean) => void; noticeData: { title: string; link?: string }; setNoticeData: (newState: { title: string; link?: string }) => void; - noticeOpen: boolean; - setNoticeOpen: (newState: boolean) => void; successData: { title: string }; setSuccessData: (newState: { title: string }) => void; - successOpen: boolean; - setSuccessOpen: (newState: boolean) => void; notificationCenter: boolean; setNotificationCenter: (newState: boolean) => void; notificationList: Array; + tempNotificationList: Array; + clearTempNotificationList: () => void; + removeFromTempNotificationList: (index: string) => void; clearNotificationList: () => void; removeFromNotificationList: (index: string) => void; loading: boolean; diff --git a/src/frontend/src/types/zustand/flow/index.ts b/src/frontend/src/types/zustand/flow/index.ts index 166f6220f..d88504909 100644 --- a/src/frontend/src/types/zustand/flow/index.ts +++ b/src/frontend/src/types/zustand/flow/index.ts @@ -7,11 +7,51 @@ import { ReactFlowInstance, Viewport, } from "reactflow"; +import { BuildStatus } from "../../../constants/enums"; import { FlowState } from "../../tabs"; +export type chatInputType = { + result: string; +}; + +export type ChatOutputType = { + message: string; + sender: string; + sender_name: string; + stream_url?: string; +}; + +export type FlowPoolObjectType = { + timestamp: string; + valid: boolean; + params: any; + data: { + artifacts: any | ChatOutputType | chatInputType; + results: any | ChatOutputType | chatInputType; + }; + duration?: string; + progress?: number; + id: string; + buildId: string; +}; + +export type VertexLayerElementType = { + id: string; + reference?: string; +}; + +export type FlowPoolType = { + [key: string]: Array; +}; + export type FlowStoreType = { - updateSSEData: (sseData: object) => void; - sseData: object; + flowPool: FlowPoolType; + inputs: Array<{ type: string; id: string; displayName: string }>; + outputs: Array<{ type: string; id: string; displayName: string }>; + hasIO: boolean; + setFlowPool: (flowPool: FlowPoolType) => void; + addDataToFlowPool: (data: FlowPoolObjectType, nodeId: string) => void; + CleanFlowPool: () => void; isBuilding: boolean; isPending: boolean; setIsBuilding: (isBuilding: boolean) => void; @@ -49,11 +89,47 @@ export type FlowStoreType = { newSelection: { nodes: any; edges: any } | null, isCrop?: boolean ) => void; - isBuilt: boolean; - setIsBuilt: (isBuilt: boolean) => void; cleanFlow: () => void; setFilterEdge: (newState) => void; getFilterEdge: any[]; onConnect: (connection: Connection) => void; unselectAll: () => void; + buildFlow: ({ + startNodeId, + stopNodeId, + input_value, + }: { + nodeId?: string; + startNodeId?: string; + stopNodeId?: string; + input_value?: string; + }) => Promise; + getFlow: () => { nodes: Node[]; edges: Edge[]; viewport: Viewport }; + updateVerticesBuild: ( + vertices: { + verticesIds: string[]; + verticesLayers: VertexLayerElementType[][]; + runId: string; + verticesToRun: string[]; + } | null + ) => void; + addToVerticesBuild: (vertices: string[]) => void; + removeFromVerticesBuild: (vertices: string[]) => void; + verticesBuild: { + verticesIds: string[]; + verticesLayers: VertexLayerElementType[][]; + runId: string; + verticesToRun: string[]; + } | null; + updateBuildStatus: (nodeId: string[], status: BuildStatus) => void; + revertBuiltStatusFromBuilding: () => void; + flowBuildStatus: { + [key: string]: { status: BuildStatus; timestamp?: string }; + }; + updateFlowPool: ( + nodeId: string, + data: FlowPoolObjectType | ChatOutputType | chatInputType, + buildId?: string + ) => void; + getNodePosition: (nodeId: string) => { x: number; y: number }; }; diff --git a/src/frontend/src/types/zustand/flowIOStore/index.ts b/src/frontend/src/types/zustand/flowIOStore/index.ts new file mode 100644 index 000000000..65833ced9 --- /dev/null +++ b/src/frontend/src/types/zustand/flowIOStore/index.ts @@ -0,0 +1,21 @@ +export type chatInputType = { + result: string; +}; + +export type ChatOutputType = { + message: string; + sender: string; + sender_name: string; +}; + +export type FlowPoolObjectType = { + timestamp: string; + valid: boolean; + params: any; + data: { artifacts: any; results: any | ChatOutputType | chatInputType }; + id: string; +}; + +export type FlowPoolType = { + [key: string]: Array; +}; diff --git a/src/frontend/src/types/zustand/flowsManager/index.ts b/src/frontend/src/types/zustand/flowsManager/index.ts index 2a20c20d8..817ddd3d1 100644 --- a/src/frontend/src/types/zustand/flowsManager/index.ts +++ b/src/frontend/src/types/zustand/flowsManager/index.ts @@ -7,10 +7,15 @@ export type FlowsManagerStoreType = { currentFlow: FlowType | undefined; currentFlowId: string; setCurrentFlowId: (currentFlowId: string) => void; + saveLoading: boolean; isLoading: boolean; setIsLoading: (isLoading: boolean) => void; refreshFlows: () => Promise; - saveFlow: (flow: FlowType, silent?: boolean) => Promise; + saveFlow: (flow: FlowType, silent?: boolean) => Promise | undefined; + saveFlowDebounce: ( + flow: FlowType, + silent?: boolean + ) => Promise | undefined; autoSaveCurrentFlow: ( nodes: Node[], edges: Edge[], @@ -43,6 +48,8 @@ export type FlowsManagerStoreType = { undo: () => void; redo: () => void; takeSnapshot: () => void; + examples: Array; + setExamples: (examples: FlowType[]) => void; }; export type UseUndoRedoOptions = { diff --git a/src/frontend/src/types/zustand/globalVariables/index.ts b/src/frontend/src/types/zustand/globalVariables/index.ts new file mode 100644 index 000000000..3e651179e --- /dev/null +++ b/src/frontend/src/types/zustand/globalVariables/index.ts @@ -0,0 +1,10 @@ +export type GlobalVariablesStore = { + globalVariablesEntries: Array; + globalVariables: { [name: string]: { id: string; type?: string } }; + setGlobalVariables: (variables: { + [name: string]: { id: string; type?: string }; + }) => void; + addGlobalVariable: (name: string, id: string, type?: string) => void; + removeGlobalVariable: (name: string) => void; + getVariableId: (name: string) => string | undefined; +}; diff --git a/src/frontend/src/utils/buildUtils.ts b/src/frontend/src/utils/buildUtils.ts new file mode 100644 index 000000000..bc2cc62e7 --- /dev/null +++ b/src/frontend/src/utils/buildUtils.ts @@ -0,0 +1,257 @@ +import { AxiosError } from "axios"; +import { BuildStatus } from "../constants/enums"; +import { getVerticesOrder, postBuildVertex } from "../controllers/API"; +import useAlertStore from "../stores/alertStore"; +import useFlowStore from "../stores/flowStore"; +import { VertexBuildTypeAPI } from "../types/api"; +import { VertexLayerElementType } from "../types/zustand/flow"; + +type BuildVerticesParams = { + flowId: string; // Assuming FlowType is the type for your flow + input_value?: any; // Replace any with the actual type if it's not any + startNodeId?: string | null; // Assuming nodeId is of type string, and it's optional + stopNodeId?: string | null; // Assuming nodeId is of type string, and it's optional + onGetOrderSuccess?: () => void; + onBuildUpdate?: ( + data: VertexBuildTypeAPI, + status: BuildStatus, + buildId: string + ) => void; // Replace any with the actual type if it's not any + onBuildComplete?: (allNodesValid: boolean) => void; + onBuildError?: (title, list, idList: VertexLayerElementType[]) => void; + onBuildStart?: (idList: VertexLayerElementType[]) => void; + onValidateNodes?: (nodes: string[]) => void; +}; + +function getInactiveVertexData(vertexId: string): VertexBuildTypeAPI { + // Build VertexBuildTypeAPI + let inactiveData = { + results: {}, + artifacts: { repr: "Inactive" }, + }; + let inactiveVertexData = { + id: vertexId, + data: inactiveData, + params: "Inactive", + inactivated_vertices: null, + run_id: "", + next_vertices_ids: [], + top_level_vertices: [], + inactive_vertices: null, + valid: false, + timestamp: new Date().toISOString(), + }; + + return inactiveVertexData; +} + +export async function updateVerticesOrder( + flowId: string, + startNodeId?: string | null, + stopNodeId?: string | null +): Promise<{ + verticesLayers: VertexLayerElementType[][]; + verticesIds: string[]; + runId: string; + verticesToRun: string[]; +}> { + return new Promise(async (resolve, reject) => { + const setErrorData = useAlertStore.getState().setErrorData; + let orderResponse; + try { + orderResponse = await getVerticesOrder(flowId, startNodeId, stopNodeId); + } catch (error: any) { + setErrorData({ + title: "Oops! Looks like you missed something", + list: [error.response?.data?.detail ?? "Unknown Error"], + }); + useFlowStore.getState().setIsBuilding(false); + throw new Error("Invalid nodes"); + } + // orderResponse.data.ids, + // for each id we need to build the VertexLayerElementType object as + // {id: id, reference: id} + let verticesLayers: Array> = + orderResponse.data.ids.map((id: string) => { + return [{ id: id, reference: id }]; + }); + + const runId = orderResponse.data.run_id; + const verticesToRun = orderResponse.data.vertices_to_run; + + const verticesIds = orderResponse.data.ids; + useFlowStore.getState().updateVerticesBuild({ + verticesLayers, + verticesIds, + runId, + verticesToRun, + }); + resolve({ verticesLayers, verticesIds, runId, verticesToRun }); + }); +} + +export async function buildVertices({ + flowId, + input_value, + startNodeId, + stopNodeId, + onGetOrderSuccess, + onBuildUpdate, + onBuildComplete, + onBuildError, + onBuildStart, + onValidateNodes, +}: BuildVerticesParams) { + let verticesBuild = useFlowStore.getState().verticesBuild; + // if startNodeId and stopNodeId are provided + // something is wrong + if (startNodeId && stopNodeId) { + return; + } + + if (!verticesBuild || startNodeId || stopNodeId) { + let verticesOrderResponse = await updateVerticesOrder( + flowId, + startNodeId, + stopNodeId + ); + if (onValidateNodes) { + try { + onValidateNodes(verticesOrderResponse.verticesToRun); + } catch (e) { + useFlowStore.getState().setIsBuilding(false); + + return; + } + } + if (onGetOrderSuccess) onGetOrderSuccess(); + verticesBuild = useFlowStore.getState().verticesBuild; + } + + const verticesIds = verticesBuild?.verticesIds!; + const verticesLayers = verticesBuild?.verticesLayers!; + const runId = verticesBuild?.runId!; + let stop = false; + + useFlowStore.getState().updateBuildStatus(verticesIds, BuildStatus.TO_BUILD); + useFlowStore.getState().setIsBuilding(true); + let currentLayerIndex = 0; // Start with the first layer + // Set each vertex state to building + const buildResults: Array = []; + + // Build each layer + while ( + currentLayerIndex < + (useFlowStore.getState().verticesBuild?.verticesLayers! || []).length + ) { + // Get the current layer + const currentLayer = + useFlowStore.getState().verticesBuild?.verticesLayers![currentLayerIndex]; + // If there are no more layers, we are done + if (!currentLayer) { + if (onBuildComplete) { + const allNodesValid = buildResults.every((result) => result); + onBuildComplete(allNodesValid); + useFlowStore.getState().setIsBuilding(false); + } + return; + } + // If there is a callback for the start of the build, call it + if (onBuildStart) onBuildStart(currentLayer); + // Build each vertex in the current layer + await Promise.all( + currentLayer.map(async (element) => { + // Check if id is in the list of inactive nodes + if ( + !useFlowStore + .getState() + .verticesBuild?.verticesIds.includes(element.id) && + onBuildUpdate + ) { + // If it is, skip building and set the state to inactive + onBuildUpdate( + getInactiveVertexData(element.id), + BuildStatus.INACTIVE, + runId + ); + buildResults.push(false); + return; + } + + // Build the vertex + await buildVertex({ + flowId, + id: element.id, + input_value, + onBuildUpdate: (data: VertexBuildTypeAPI, status: BuildStatus) => { + if (onBuildUpdate) onBuildUpdate(data, status, runId); + }, + onBuildError, + verticesIds, + buildResults, + stopBuild: () => { + stop = true; + }, + }); + if (stop) { + return; + } + }) + ); + // Once the current layer is built, move to the next layer + currentLayerIndex += 1; + + if (stop) { + break; + } + } + if (onBuildComplete) { + const allNodesValid = buildResults.every((result) => result); + onBuildComplete(allNodesValid); + useFlowStore.getState().setIsBuilding(false); + } +} +async function buildVertex({ + flowId, + id, + input_value, + onBuildUpdate, + onBuildError, + verticesIds, + buildResults, + stopBuild, +}: { + flowId: string; + id: string; + input_value: string; + onBuildUpdate?: (data: any, status: BuildStatus) => void; + onBuildError?: (title, list, idList: VertexLayerElementType[]) => void; + verticesIds: string[]; + buildResults: boolean[]; + stopBuild: () => void; +}) { + try { + const buildRes = await postBuildVertex(flowId, id, input_value); + + const buildData: VertexBuildTypeAPI = buildRes.data; + if (onBuildUpdate) { + if (!buildData.valid) { + onBuildError!( + "Error Building Component", + [buildData.params], + verticesIds.map((id) => ({ id })) + ); + stopBuild(); + } + onBuildUpdate(buildData, BuildStatus.BUILT); + } + buildResults.push(buildData.valid); + } catch (error) { + onBuildError!( + "Error Building Component", + [(error as AxiosError).response?.data?.detail ?? "Unknown Error"], + verticesIds.map((id) => ({ id })) + ); + stopBuild(); + } +} diff --git a/src/frontend/src/utils/parameterUtils.ts b/src/frontend/src/utils/parameterUtils.ts new file mode 100644 index 000000000..5972c6599 --- /dev/null +++ b/src/frontend/src/utils/parameterUtils.ts @@ -0,0 +1,45 @@ +import { debounce } from "lodash"; +import { SAVE_DEBOUNCE_TIME } from "../constants/constants"; +import { postCustomComponentUpdate } from "../controllers/API"; +import { ResponseErrorTypeAPI } from "../types/api"; +import { NodeDataType } from "../types/flow"; + +export const handleUpdateValues = async (name: string, data: NodeDataType) => { + const code = data.node?.template["code"]?.value; + if (!code) { + console.error("Code not found in the template"); + return; + } + const template = data.node?.template; + if (!template) { + console.error("No template found in the node."); + return; + } + try { + let newTemplate = await postCustomComponentUpdate( + code, + template, + name, + data.node?.template[name]?.value + ) + .then((res) => { + console.log("res", res); + if (res.status === 200 && data.node?.template) { + return res.data.template; + } + }) + .catch((error) => { + throw error; + }); + return newTemplate; + } catch (error) { + console.error("Error occurred while updating the node:", error); + let errorType = error as ResponseErrorTypeAPI; + throw errorType; + } +}; + +export const debouncedHandleUpdateValues = debounce( + handleUpdateValues, + SAVE_DEBOUNCE_TIME +); diff --git a/src/frontend/src/utils/reactflowUtils.ts b/src/frontend/src/utils/reactflowUtils.ts index 7d0e2a3ac..4cd19bf7e 100644 --- a/src/frontend/src/utils/reactflowUtils.ts +++ b/src/frontend/src/utils/reactflowUtils.ts @@ -9,7 +9,10 @@ import { } from "reactflow"; import ShortUniqueId from "short-unique-id"; import { + INPUT_TYPES, LANGFLOW_SUPPORTED_TYPES, + OUTPUT_TYPES, + SUCCESS_BUILD, specialCharsRegex, } from "../constants/constants"; import { downloadFlowsFromDatabase } from "../controllers/API"; @@ -41,6 +44,10 @@ import { } from "./utils"; const uid = new ShortUniqueId({ length: 5 }); +export function checkChatInput(nodes: Node[]) { + return nodes.some((node) => node.data.type === "ChatInput"); +} + export function cleanEdges(nodes: Node[], edges: Edge[]) { let newEdges = cloneDeep(edges); edges.forEach((edge) => { @@ -197,23 +204,33 @@ export const processDataFromFlow = (flow: FlowType, refreshIds = true) => { return data; }; -export function updateIds(newFlow: ReactFlowJsonObject) { +export function updateIds( + { edges, nodes }: { edges: Edge[]; nodes: Node[] }, + selection?: { edges: Edge[]; nodes: Node[] } +) { let idsMap = {}; - - if (newFlow.nodes) - newFlow.nodes.forEach((node: NodeType) => { + const selectionIds = selection?.nodes.map((n) => n.id); + if (nodes) { + nodes.forEach((node: NodeType) => { // Generate a unique node ID - let newId = getNodeId( - node.data.node?.flow ? "GroupNode" : node.data.type - ); + let newId = getNodeId(node.data.type); + if (selection && !selectionIds?.includes(node.id)) { + newId = node.id; + } idsMap[node.id] = newId; node.id = newId; node.data.id = newId; // Add the new node to the list of nodes in state }); - - if (newFlow.edges) - newFlow.edges.forEach((edge: Edge) => { + selection?.nodes.forEach((sNode: NodeType) => { + let newId = idsMap[sNode.id]; + sNode.id = newId; + sNode.data.id = newId; + }); + } + const concatedEdges = [...edges, ...(selection?.edges ?? [])]; + if (concatedEdges) + concatedEdges.forEach((edge: Edge) => { edge.source = idsMap[edge.source]; edge.target = idsMap[edge.target]; const sourceHandleObject: sourceHandleType = scapeJSONParse( @@ -257,7 +274,7 @@ export function buildTweaks(flow: FlowType) { export function validateNode(node: NodeType, edges: Edge[]): Array { if (!node.data?.node?.template || !Object.keys(node.data.node.template)) { return [ - "We've noticed a potential issue with a node in the flow. Please review it and, if necessary, submit a bug report with your exported flow file. Thank you for your help!", + "We've noticed a potential issue with a Component in the flow. Please review it and, if necessary, submit a bug report with your exported flow file. Thank you for your help!", ]; } @@ -266,6 +283,8 @@ export function validateNode(node: NodeType, edges: Edge[]): Array { node: { template }, } = node.data; + const displayName = node.data.node.display_name; + return Object.keys(template).reduce((errors: Array, t) => { if ( template[t].required && @@ -281,7 +300,9 @@ export function validateNode(node: NodeType, edges: Edge[]): Array { node.id ) ) { - errors.push(`${type} is missing ${getFieldTitle(template, t)}.`); + errors.push( + `${displayName || type} is missing ${getFieldTitle(template, t)}.` + ); } else if ( template[t].type === "dict" && template[t].required && @@ -292,27 +313,40 @@ export function validateNode(node: NodeType, edges: Edge[]): Array { ) { if (hasDuplicateKeys(template[t].value)) errors.push( - `${type} (${getFieldTitle( + `${displayName || type} (${getFieldTitle( template, t )}) contains duplicate keys with the same values.` ); if (hasEmptyKey(template[t].value)) errors.push( - `${type} (${getFieldTitle(template, t)}) field must not be empty.` + `${displayName || type} (${getFieldTitle( + template, + t + )}) field must not be empty.` ); } return errors; }, [] as string[]); } -export function validateNodes(nodes: Node[], edges: Edge[]) { +export function validateNodes( + nodes: Node[], + edges: Edge[] +): // this returns an array of tuples with the node id and the errors +Array<{ id: string; errors: Array }> { if (nodes.length === 0) { return [ - "No nodes found in the flow. Please add at least one node to the flow.", + { + id: "", + errors: [ + "No nodes found in the flow. Please add at least one node to the flow.", + ], + }, ]; } - return nodes.flatMap((n: NodeType) => validateNode(n, edges)); + // validateNode(n, edges) returns an array of errors for the node + return nodes.map((n) => ({ id: n.id, errors: validateNode(n, edges) })); } export function updateEdges(edges: Edge[]) { @@ -321,11 +355,7 @@ export function updateEdges(edges: Edge[]) { const targetHandleObject: targetHandleType = scapeJSONParse( edge.targetHandle! ); - edge.className = - (targetHandleObject.type === "Text" - ? "stroke-gray-800 " - : "stroke-gray-900 ") + " stroke-connection"; - edge.animated = targetHandleObject.type === "Text"; + edge.className = "stroke-gray-900 stroke-connection"; }); } @@ -630,10 +660,13 @@ export function generateFlow( } export function reconnectEdges(groupNode: NodeType, excludedEdges: Edge[]) { - let newEdges = cloneDeep(excludedEdges); if (!groupNode.data.node!.flow) return []; + let newEdges = cloneDeep(excludedEdges); const { nodes, edges } = groupNode.data.node!.flow!.data!; const lastNode = findLastNode(groupNode.data.node!.flow!.data!); + newEdges = newEdges.filter( + (e) => !(nodes.some((n) => n.id === e.source) && e.source !== lastNode?.id) + ); newEdges.forEach((edge) => { if (lastNode && edge.source === lastNode.id) { edge.source = groupNode.id; @@ -718,6 +751,7 @@ export function validateSelection( if (selection.edges.length === 0) { selection.edges = edges; } + // get only edges that are connected to the nodes in the selection // first creates a set of all the nodes ids let nodesSet = new Set(selection.nodes.map((n) => n.id)); @@ -733,7 +767,17 @@ export function validateSelection( if (selection.nodes.length < 2) { errorsArray.push("Please select more than one node"); } - + if ( + selection.nodes.some( + (node) => + isInputNode(node.data as NodeDataType) || + isOutputNode(node.data as NodeDataType) + ) + ) { + errorsArray.push( + "Please select only nodes that are not input or output nodes" + ); + } //check if there are two or more nodes with free outputs if ( selection.nodes.filter( @@ -769,7 +813,7 @@ function updateGroupNodeTemplate(template: APITemplateType) { template[key].advanced = true; } //prevent code fields from showing on the group node - if (type === "code") { + if (type === "code" && key === "code") { template[key].show = false; } }); @@ -937,7 +981,7 @@ export function connectedInputNodesOnHandle( return connectedNodes; } -function updateProxyIdsOnTemplate( +export function updateProxyIdsOnTemplate( template: APITemplateType, idsMap: { [key: string]: string } ) { @@ -948,12 +992,16 @@ function updateProxyIdsOnTemplate( }); } -function updateEdgesIds(edges: Edge[], idsMap: { [key: string]: string }) { +export function updateEdgesIds( + edges: Edge[], + idsMap: { [key: string]: string } +) { edges.forEach((edge) => { let targetHandle: targetHandleType = edge.data.targetHandle; if (targetHandle.proxy && idsMap[targetHandle.proxy!.id]) { targetHandle.proxy!.id = idsMap[targetHandle.proxy!.id]; } + console.log("edge", edge); edge.data.targetHandle = targetHandle; edge.targetHandle = scapedJSONStringfy(targetHandle); }); @@ -1078,7 +1126,7 @@ export function getGroupStatus( flow: FlowType, ssData: { [key: string]: { valid: boolean; params: string } } ) { - let status = { valid: true, params: "Built sucessfully ✨" }; + let status = { valid: true, params: SUCCESS_BUILD }; const { nodes } = flow.data!; const ids = nodes.map((n: NodeType) => n.data.id); ids.forEach((id) => { @@ -1125,7 +1173,7 @@ export function downloadNode(NodeFLow: FlowType) { type: "application/json", }); element.href = URL.createObjectURL(file); - element.download = `${NodeFLow.name}.json`; + element.download = `${NodeFLow?.name ?? "node"}.json`; element.click(); } @@ -1147,6 +1195,20 @@ export function removeFileNameFromComponents(flow: FlowType) { }); } +export function removeGlobalVariableFromComponents(flow: FlowType) { + flow.data!.nodes.forEach((node: NodeType) => { + Object.keys(node.data.node!.template).forEach((field) => { + if (node.data?.node?.template[field]?.load_from_db) { + node.data.node!.template[field].value = ""; + node.data.node!.template[field].load_from_db = false; + } + }); + if (node.data.node?.flow) { + removeGlobalVariableFromComponents(node.data.node.flow); + } + }); +} + export function typesGenerator(data: APIObjectType) { return Object.keys(data) .reverse() @@ -1225,3 +1287,34 @@ export const createNewFlow = ( is_component: flow?.is_component ?? false, }; }; + +export function isInputNode(nodeData: NodeDataType): boolean { + return INPUT_TYPES.has(nodeData.type); +} + +export function isOutputNode(nodeData: NodeDataType): boolean { + return OUTPUT_TYPES.has(nodeData.type); +} + +export function isInputType(type: string): boolean { + return INPUT_TYPES.has(type); +} + +export function isOutputType(type: string): boolean { + return OUTPUT_TYPES.has(type); +} + +export function updateGroupRecursion(groupNode: NodeType, edges: Edge[]) { + if (groupNode.data.node?.flow) { + groupNode.data.node.flow.data!.nodes.forEach((node) => { + if (node.data.node?.flow) { + updateGroupRecursion(node, node.data.node.flow.data!.edges); + } + }); + let newFlow = groupNode.data.node!.flow; + const idsMap = updateIds(newFlow.data!); + updateProxyIdsOnTemplate(groupNode.data.node!.template, idsMap); + let flowEdges = edges; + updateEdgesIds(flowEdges, idsMap); + } +} diff --git a/src/frontend/src/utils/storeUtils.ts b/src/frontend/src/utils/storeUtils.ts index 8738bac75..e51cf8933 100644 --- a/src/frontend/src/utils/storeUtils.ts +++ b/src/frontend/src/utils/storeUtils.ts @@ -1,5 +1,7 @@ import { cloneDeep } from "lodash"; -import { FlowType } from "../types/flow"; +import { Node } from "reactflow"; +import { FlowType, NodeDataType } from "../types/flow"; +import { isInputNode, isOutputNode } from "./reactflowUtils"; export default function cloneFLowWithParent( flow: FlowType, @@ -21,3 +23,26 @@ export function getTagsIds( .map((tag) => tagListId.find((tagObj) => tagObj.name === tag))! .map((tag) => tag!.id); } + +export function getInputsAndOutputs(nodes: Node[]) { + let inputs: { type: string; id: string; displayName: string }[] = []; + let outputs: { type: string; id: string; displayName: string }[] = []; + nodes.forEach((node) => { + const nodeData: NodeDataType = node.data as NodeDataType; + if (isOutputNode(nodeData)) { + outputs.push({ + type: nodeData.type, + id: nodeData.id, + displayName: nodeData.node?.display_name ?? nodeData.id, + }); + } + if (isInputNode(nodeData)) { + inputs.push({ + type: nodeData.type, + id: nodeData.id, + displayName: nodeData.node?.display_name ?? nodeData.id, + }); + } + }); + return { inputs, outputs }; +} diff --git a/src/frontend/src/utils/styleUtils.ts b/src/frontend/src/utils/styleUtils.ts index b0432fe7e..a0c9c9756 100644 --- a/src/frontend/src/utils/styleUtils.ts +++ b/src/frontend/src/utils/styleUtils.ts @@ -1,25 +1,40 @@ import { + AlertCircle, + ArrowBigUp, + ArrowLeft, ArrowUpToLine, Bell, + Binary, BookMarked, BookmarkPlus, + Bot, Boxes, + Braces, + BrainCircuit, Check, CheckCircle2, ChevronDown, ChevronLeft, ChevronRight, + ChevronRightSquare, ChevronUp, ChevronsLeft, ChevronsRight, ChevronsUpDown, + ChevronsUpDownIcon, Circle, + CircleDot, Clipboard, + Code, Code2, Combine, + Command, Compass, Copy, Cpu, + Database, + Delete, + Dot, Download, DownloadCloud, Edit, @@ -28,18 +43,23 @@ import { Eye, EyeOff, File, + FileClock, FileDown, FileSearch, FileSearch2, + FileSliders, FileText, + FileType2, FileUp, - Fingerprint, + FlaskConical, FolderPlus, + FormInput, Forward, Gift, GitBranchPlus, GitFork, GithubIcon, + Globe, Group, Hammer, Heart, @@ -49,7 +69,6 @@ import { Key, Laptop2, Layers, - Lightbulb, Link, Loader2, Lock, @@ -59,34 +78,49 @@ import { Menu, MessageCircle, MessageSquare, + MessageSquareMore, MessagesSquare, Minimize2, Minus, MoonIcon, MoreHorizontal, Network, + Package2, Paperclip, Pencil, + PencilLine, + Pin, + Play, Plus, + PlusCircle, + PlusSquare, + PocketKnife, Redo, RefreshCcw, - Rocket, + Repeat, Save, SaveAll, Scissors, + ScreenShare, Search, Settings2, Share, Share2, Shield, + Sliders, + Snowflake, Sparkles, Square, + SquarePen, Store, SunIcon, TerminalIcon, TerminalSquare, + TextCursorInput, + TextSearch, ToyBrick, Trash2, + Type, Undo, Ungroup, Unplug, @@ -99,7 +133,6 @@ import { Variable, Wand2, Workflow, - Wrench, X, XCircle, Zap, @@ -108,7 +141,10 @@ import { FaApple, FaGithub } from "react-icons/fa"; import { AWSIcon } from "../icons/AWS"; import { AirbyteIcon } from "../icons/Airbyte"; import { AnthropicIcon } from "../icons/Anthropic"; +import { AstraDBIcon } from "../icons/AstraDB"; +import { AzureIcon } from "../icons/Azure"; import { BingIcon } from "../icons/Bing"; +import { BotMessageSquareIcon } from "../icons/BotMessageSquare"; import { ChromaIcon } from "../icons/ChromaIcon"; import { CohereIcon } from "../icons/Cohere"; import { ElasticsearchIcon } from "../icons/ElasticsearchStore"; @@ -116,6 +152,7 @@ import { EvernoteIcon } from "../icons/Evernote"; import { FBIcon } from "../icons/FacebookMessenger"; import { GitBookIcon } from "../icons/GitBook"; import { GoogleIcon } from "../icons/Google"; +import { GoogleGenerativeAIIcon } from "../icons/GoogleGenerativeAI"; import { GradientInfinity, GradientSave, @@ -127,9 +164,14 @@ import { MetaIcon } from "../icons/Meta"; import { MidjourneyIcon } from "../icons/Midjorney"; import { MongoDBIcon } from "../icons/MongoDB"; import { NotionIcon } from "../icons/Notion"; +import { OllamaIcon } from "../icons/Ollama"; import { OpenAiIcon } from "../icons/OpenAi"; import { PineconeIcon } from "../icons/Pinecone"; +import { PostgresIcon } from "../icons/Postgres"; +import { PythonIcon } from "../icons/Python"; import { QDrantIcon } from "../icons/QDrant"; +import { QianFanChatIcon } from "../icons/QianFanChat"; +import { RedisIcon } from "../icons/Redis"; import { SearxIcon } from "../icons/Searx"; import { ShareIcon } from "../icons/Share"; import { Share2Icon } from "../icons/Share2"; @@ -178,8 +220,12 @@ export const gradients = [ ]; export const nodeColors: { [char: string]: string } = { + inputs: "#10B981", + outputs: "#AA2411", + data: "#4367BF", prompts: "#4367BF", - llms: "#6344BE", + models: "#6344BE", + model_specs: "#6344BE", chains: "#FE7500", Document: "#7AAE42", list: "#9AAE42", @@ -193,20 +239,30 @@ export const nodeColors: { [char: string]: string } = { embeddings: "#42BAA7", documentloaders: "#7AAE42", vectorstores: "#AA8742", + vectorsearch: "#AA8742", textsplitters: "#B47CB5", toolkits: "#DB2C2C", wrappers: "#E6277A", - utilities: "#31A3CC", + helpers: "#31A3CC", + experimental: "#E6277A", + langchain_utilities: "#31A3CC", output_parsers: "#E6A627", - str: "#049524", + str: "#31a3cc", + Text: "#31a3cc", retrievers: "#e6b25a", unknown: "#9CA3AF", custom_components: "#ab11ab", + Records: "#31a3cc", + Record: "#31a3cc", }; export const nodeNames: { [char: string]: string } = { + inputs: "Inputs", + outputs: "Outputs", + data: "Data", prompts: "Prompts", - llms: "LLMs", + models: "Models", + model_specs: "Model Specs", chains: "Chains", agents: "Agents", tools: "Tools", @@ -217,27 +273,58 @@ export const nodeNames: { [char: string]: string } = { embeddings: "Embeddings", documentloaders: "Loaders", vectorstores: "Vector Stores", + vectorsearch: "Vector Search", toolkits: "Toolkits", wrappers: "Wrappers", textsplitters: "Text Splitters", retrievers: "Retrievers", - utilities: "Utilities", + helpers: "Helpers", + experimental: "Experimental", + langchain_utilities: "Utilities", output_parsers: "Output Parsers", custom_components: "Custom", unknown: "Other", }; export const nodeIconsLucide: iconsType = { + X: X, + Notify: Bell, + ListFlows: Group, + ClearMessageHistory: FileClock, + Python: PythonIcon, + ChatOutput: BotMessageSquareIcon, + ChatInput: MessagesSquare, + inputs: Download, + outputs: Upload, + data: Database, + AzureChatOpenAi: AzureIcon, + Ollama: OllamaIcon, + ChatOllama: OllamaIcon, + AzureOpenAiEmbeddings: AzureIcon, + Azure: AzureIcon, + OllamaEmbeddings: OllamaIcon, + ChatOllamaModel: OllamaIcon, + Faiss: MetaIcon, + FaissSearch: MetaIcon, + AzureOpenAiModel: AzureIcon, + Redis: RedisIcon, + RedisSearch: RedisIcon, + PostgresChatMessageHistory: PostgresIcon, + BaiduQianfan: QianFanChatIcon, + Play, Vectara: VectaraIcon, ArrowUpToLine: ArrowUpToLine, Chroma: ChromaIcon, AirbyteJSONLoader: AirbyteIcon, AmazonBedrockEmbeddings: AWSIcon, + Amazon: AWSIcon, Anthropic: AnthropicIcon, ChatAnthropic: AnthropicIcon, + AstraDB: AstraDBIcon, BingSearchAPIWrapper: BingIcon, BingSearchRun: BingIcon, Cohere: CohereIcon, + ChevronsUpDownIcon, CohereEmbeddings: CohereIcon, EverNoteLoader: EvernoteIcon, FacebookChatLoader: FBIcon, @@ -245,13 +332,18 @@ export const nodeIconsLucide: iconsType = { GoogleSearchAPIWrapper: GoogleIcon, GoogleSearchResults: GoogleIcon, GoogleSearchRun: GoogleIcon, + Google: GoogleIcon, + GoogleGenerativeAI: GoogleGenerativeAIIcon, HNLoader: HackerNewsIcon, HuggingFaceHub: HuggingFaceIcon, + HuggingFace: HuggingFaceIcon, HuggingFaceEmbeddings: HuggingFaceIcon, IFixitLoader: IFixIcon, Meta: MetaIcon, Midjorney: MidjourneyIcon, MongoDBAtlasVectorSearch: MongoDBIcon, + MongoDB: MongoDBIcon, + MongoDBChatMessageHistory: MongoDBIcon, NotionDirectoryLoader: NotionIcon, ChatOpenAI: OpenAiIcon, AzureChatOpenAI: OpenAiIcon, @@ -264,30 +356,35 @@ export const nodeIconsLucide: iconsType = { Searx: SearxIcon, SlackDirectoryLoader: SvgSlackIcon, SupabaseVectorStore: SupabaseIcon, + Supabase: SupabaseIcon, VertexAI: VertexAIIcon, ChatVertexAI: VertexAIIcon, VertexAIEmbeddings: VertexAIIcon, Share3: ShareIcon, Share4: Share2Icon, - agents: Rocket, + agents: Bot, Workflow, User, WikipediaAPIWrapper: SvgWikipedia, chains: Link, memories: Cpu, - llms: Lightbulb, + models: BrainCircuit, + model_specs: FileSliders, prompts: TerminalSquare, - tools: Wrench, + tools: Hammer, advanced: Laptop2, chat: MessageCircle, - embeddings: Fingerprint, + embeddings: Binary, saved_components: GradientSave, documentloaders: Paperclip, vectorstores: Layers, - toolkits: Hammer, + vectorsearch: TextSearch, + toolkits: Package2, textsplitters: Scissors, wrappers: Gift, - utilities: Wand2, + helpers: Wand2, + experimental: FlaskConical, + langchain_utilities: PocketKnife, WolframAlphaAPIWrapper: SvgWolfram, output_parsers: Compass, retrievers: FileSearch, @@ -300,10 +397,10 @@ export const nodeIconsLucide: iconsType = { Trash2, Boxes, Network, - X, XCircle, Info, CheckCircle2, + SquarePen, Zap, MessagesSquare, ExternalLink, @@ -316,17 +413,24 @@ export const nodeIconsLucide: iconsType = { Bell, ChevronLeft, ChevronDown, + ArrowLeft, Shield, Plus, Redo, Settings2, + FileType2, Undo, FileSearch2, ChevronRight, Circle, + CircleDot, Clipboard, + PlusCircle, + PlusSquare, Code2, + Globe, Variable, + Snowflake, Store, Download, Eraser, @@ -363,13 +467,17 @@ export const nodeIconsLucide: iconsType = { Group, LogIn, ChevronUp, + PencilLine, Ungroup, BookMarked, Minus, Square, Minimize2, Maximize2, + FormInput, + ChevronRightSquare, SaveAll, + MessageSquareMore, Forward, Share2, Share, @@ -377,9 +485,25 @@ export const nodeIconsLucide: iconsType = { Loader2, BookmarkPlus, Heart, + Pin, Link, ToyBrick, RefreshCcw, Combine, TerminalIcon, + TerminalSquare, + TextCursorInput, + Repeat, + Sliders, + ScreenShare, + Code, + Type, + Braces, + FlaskConical, + AlertCircle, + Bot, + Delete, + Command, + ArrowBigUp, + Dot, }; diff --git a/src/frontend/src/utils/utils.ts b/src/frontend/src/utils/utils.ts index f1e534c1a..91d7a72f9 100644 --- a/src/frontend/src/utils/utils.ts +++ b/src/frontend/src/utils/utils.ts @@ -1,5 +1,6 @@ import clsx, { ClassValue } from "clsx"; import { twMerge } from "tailwind-merge"; +import { priorityFields } from "../constants/constants"; import { ADJECTIVES, DESCRIPTIONS, NOUNS } from "../flow_constants"; import { APIDataType, @@ -13,7 +14,7 @@ import { tweakType, } from "../types/components"; import { FlowType, NodeType } from "../types/flow"; -import { FlowState, FlowsState } from "../types/tabs"; +import { FlowState } from "../types/tabs"; import { buildTweaks } from "./reactflowUtils"; export function classNames(...classes: Array): string { @@ -58,11 +59,15 @@ export function normalCaseToSnakeCase(str: string): string { .join("_"); } -export function toTitleCase(str: string | undefined): string { +export function toTitleCase( + str: string | undefined, + isNodeField?: boolean +): string { if (!str) return ""; let result = str .split("_") .map((word, index) => { + if (isNodeField) return word; if (index === 0) { return checkUpperWords( word[0].toUpperCase() + word.slice(1).toLowerCase() @@ -75,6 +80,7 @@ export function toTitleCase(str: string | undefined): string { return result .split("-") .map((word, index) => { + if (isNodeField) return word; if (index === 0) { return checkUpperWords( word[0].toUpperCase() + word.slice(1).toLowerCase() @@ -119,15 +125,7 @@ export function groupByFamily( display_name?: string; }> = []; let checkedNodes = new Map(); - const excludeTypes = new Set([ - "str", - "bool", - "float", - "code", - "prompt", - "file", - "int", - ]); + const excludeTypes = new Set(["bool", "float", "code", "file", "int"]); const checkBaseClass = (template: TemplateVariableType) => { return ( @@ -146,7 +144,7 @@ export function groupByFamily( // se existir o flow for (const node of flow) { // para cada node do flow - if (node!.data!.node!.flow) break; // não faz nada se o node for um group + if (node!.data!.node!.flow || !node!.data!.node!.template) break; // não faz nada se o node for um group const nodeData = node.data; const foundNode = checkedNodes.get(nodeData.type); // verifica se o tipo do node já foi checado @@ -220,12 +218,8 @@ export function groupByFamily( })); } -export function buildInputs(flowState?: FlowState): string { - return flowState && - flowState.input_keys && - Object.keys(flowState.input_keys!).length > 0 - ? JSON.stringify(flowState.input_keys) - : '{"input": "message"}'; +export function buildInputs(): string { + return '{"input_value": "message"}'; } export function getRandomElement(array: T[]): T { @@ -295,11 +289,10 @@ export function buildTweakObject(tweak: tweakType) { /** * Function to get Chat Input Field - * @param {FlowType} flow - The current flow. * @param {FlowsState} tabsState - The current tabs state. * @returns {string} - The chat input field */ -export function getChatInputField(flow: FlowType, flowState?: FlowState) { +export function getChatInputField(flowState?: FlowState) { let chat_input_field = "text"; if (flowState && flowState.input_keys) { @@ -311,13 +304,14 @@ export function getChatInputField(flow: FlowType, flowState?: FlowState) { /** * Function to get the python code for the API * @param {string} flowId - The id of the flow + * @param {boolean} isAuth - If the API is authenticated + * @param {any[]} tweak - The tweaks * @returns {string} - The python code */ export function getPythonApiCode( flow: FlowType, isAuth: boolean, - tweak?: any[], - flowState?: FlowState + tweak?: any[] ): string { const flowId = flow.id; @@ -326,13 +320,10 @@ export function getPythonApiCode( // node.data.id // } const tweaks = buildTweaks(flow); - const inputs = buildInputs(flowState); return `import requests from typing import Optional -BASE_API_URL = "${window.location.protocol}//${ - window.location.host - }/api/v1/process" +BASE_API_URL = "${window.location.protocol}//${window.location.host}/api/v1/run" FLOW_ID = "${flowId}" # You can tweak the flow by adding a tweaks dictionary # e.g {"OpenAI-XXXXX": {"model_name": "gpt-4"}} @@ -342,9 +333,12 @@ TWEAKS = ${ : JSON.stringify(tweaks, null, 2) } -def run_flow(inputs: dict, flow_id: str, tweaks: Optional[dict] = None${ - !isAuth ? `, api_key: Optional[str] = None` : "" - }) -> dict: +def run_flow(message: str, + flow_id: str, + output_type: str = "chat", + input_type: str = "chat", + tweaks: Optional[dict] = None, + api_key: Optional[str] = None) -> dict: """ Run a flow with a given message and optional tweaks. @@ -355,7 +349,11 @@ def run_flow(inputs: dict, flow_id: str, tweaks: Optional[dict] = None${ """ api_url = f"{BASE_API_URL}/{flow_id}" - payload = {"inputs": inputs} + payload = { + "input_value": message, + "output_type": output_type, + "input_type": input_type, + } headers = None if tweaks: payload["tweaks"] = tweaks @@ -365,9 +363,9 @@ def run_flow(inputs: dict, flow_id: str, tweaks: Optional[dict] = None${ return response.json() # Setup any tweaks you want to apply to the flow -inputs = ${inputs} +message = "message" ${!isAuth ? `api_key = ""` : ""} -print(run_flow(inputs, flow_id=FLOW_ID, tweaks=TWEAKS${ +print(run_flow(message=message, flow_id=FLOW_ID, tweaks=TWEAKS${ !isAuth ? `, api_key=api_key` : "" }))`; } @@ -375,55 +373,72 @@ print(run_flow(inputs, flow_id=FLOW_ID, tweaks=TWEAKS${ /** * Function to get the curl code for the API * @param {string} flowId - The id of the flow + * @param {boolean} isAuth - If the API is authenticated * @returns {string} - The curl code */ export function getCurlCode( flow: FlowType, isAuth: boolean, - tweak?: any[], - flowState?: FlowState + tweak?: any[] ): string { const flowId = flow.id; const tweaks = buildTweaks(flow); - const inputs = buildInputs(flowState); return `curl -X POST \\ ${window.location.protocol}//${ window.location.host - }/api/v1/process/${flowId} \\ + }/api/v1/run/${flowId}?stream=false \\ -H 'Content-Type: application/json'\\${ !isAuth ? `\n -H 'x-api-key: '\\` : "" } - -d '{"inputs": ${inputs}, "tweaks": ${ + -d '{"input_value": "message", + "output_type": "chat", + "input_type": "chat", + "tweaks": ${ tweak && tweak.length > 0 ? buildTweakObject(tweak) : JSON.stringify(tweaks, null, 2) - }}'`; + }}' + `; +} + +export function getOutputIds(flow) { + const nodes = flow.data!.nodes; + + const arrayOfOutputs = nodes.reduce((acc: string[], node) => { + if (node.data.type.toLowerCase().includes("output")) { + acc.push(node.id); + } + return acc; + }, []); + + const arrayOfOutputsJoin = arrayOfOutputs + .map((output) => `"${output}"`) + .join(", "); + + return arrayOfOutputsJoin; } /** * Function to get the python code for the API * @param {string} flow - The current flow + * @param {any[]} tweak - The tweaks * @returns {string} - The python code */ -export function getPythonCode( - flow: FlowType, - tweak?: any[], - flowState?: FlowState -): string { +export function getPythonCode(flow: FlowType, tweak?: any[]): string { const flowName = flow.name; const tweaks = buildTweaks(flow); - const inputs = buildInputs(flowState); - return `from langflow import load_flow_from_json + + return `from langflow.load import run_flow_from_json TWEAKS = ${ tweak && tweak.length > 0 ? buildTweakObject(tweak) : JSON.stringify(tweaks, null, 2) } -flow = load_flow_from_json("${flowName}.json", tweaks=TWEAKS) -# Now you can use it like any chain -inputs = ${inputs} -flow(inputs)`; + +result = run_flow_from_json(flow="${flowName}.json", + input_value="message", + tweaks=TWEAKS)`; } /** @@ -438,24 +453,15 @@ export function getWidgetCode( ): string { const flowId = flow.id; const flowName = flow.name; - const inputs = buildInputs(flowState); - let chat_input_field = getChatInputField(flow, flowState); + const inputs = buildInputs(); + let chat_input_field = getChatInputField(flowState); - return ` + return ` - Union[Text, Record]:\n return super().build(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n session_id=session_id,\n return_record=return_record,\n )\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "input_value": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Message", + "advanced": false, + "input_types": ["Text"], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "return_record": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "return_record", + "display_name": "Return Record", + "advanced": false, + "dynamic": false, + "info": "Return the message as a record containing the sender, sender_name, and session_id.", + "load_from_db": false, + "title_case": false + }, + "sender": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "User", + "fileTypes": [], + "file_path": "", + "password": false, + "options": ["Machine", "User"], + "name": "sender", + "display_name": "Sender Type", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": ["Text"] + }, + "sender_name": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "User", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "sender_name", + "display_name": "Sender Name", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": ["Text"] + }, + "session_id": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "session_id", + "display_name": "Session ID", + "advanced": true, + "dynamic": false, + "info": "If provided, the message will be stored in the memory.", + "load_from_db": false, + "title_case": false, + "input_types": ["Text"] + }, + "_type": "CustomComponent" + }, + "description": "Used to get user input from the chat.", + "icon": "ChatInput", + "base_classes": ["Text", "object", "str", "Record"], + "display_name": "Chat Input", + "documentation": "", + "custom_fields": { + "sender": null, + "sender_name": null, + "input_value": null, + "session_id": null, + "return_record": null + }, + "output_types": ["Text", "Record"], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "ChatInput-7hPDT" + }, + "selected": false, + "width": 384, + "height": 569, + "positionAbsolute": { + "x": 687, + "y": 41.9375 + }, + "dragging": false + }, + { + "id": "ChatOutput-4sm9Z", + "type": "genericNode", + "position": { + "x": 4.939451516507972, + "y": 103.3695231904992 + }, + "data": { + "type": "ChatOutput", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional, Union\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.field_typing import Text\nfrom langflow.schema import Record\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Used to send a message to the chat.\"\n icon = \"ChatOutput\"\n\n def build(\n self,\n sender: Optional[str] = \"Machine\",\n sender_name: Optional[str] = \"AI\",\n input_value: Optional[str] = None,\n session_id: Optional[str] = None,\n return_record: Optional[bool] = False,\n ) -> Union[Text, Record]:\n return super().build(\n sender=sender,\n sender_name=sender_name,\n input_value=input_value,\n session_id=session_id,\n return_record=return_record,\n )\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "input_value": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "input_value", + "display_name": "Message", + "advanced": false, + "input_types": ["Text"], + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false + }, + "return_record": { + "type": "bool", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "return_record", + "display_name": "Return Record", + "advanced": false, + "dynamic": false, + "info": "Return the message as a record containing the sender, sender_name, and session_id.", + "load_from_db": false, + "title_case": false + }, + "sender": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "Machine", + "fileTypes": [], + "file_path": "", + "password": false, + "options": ["Machine", "User"], + "name": "sender", + "display_name": "Sender Type", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": ["Text"] + }, + "sender_name": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "AI", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "sender_name", + "display_name": "Sender Name", + "advanced": false, + "dynamic": false, + "info": "", + "load_from_db": false, + "title_case": false, + "input_types": ["Text"] + }, + "session_id": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "session_id", + "display_name": "Session ID", + "advanced": true, + "dynamic": false, + "info": "If provided, the message will be stored in the memory.", + "load_from_db": false, + "title_case": false, + "input_types": ["Text"] + }, + "_type": "CustomComponent" + }, + "description": "Used to send a message to the chat.", + "icon": "ChatOutput", + "base_classes": ["Text", "object", "str", "Record"], + "display_name": "Chat Output", + "documentation": "", + "custom_fields": { + "sender": null, + "sender_name": null, + "input_value": null, + "session_id": null, + "return_record": null + }, + "output_types": ["Text", "Record"], + "field_formatters": {}, + "frozen": false, + "field_order": [], + "beta": false + }, + "id": "ChatOutput-4sm9Z" + }, + "selected": true, + "width": 384, + "height": 569, + "positionAbsolute": { + "x": 4.939451516507972, + "y": 103.3695231904992 + }, + "dragging": false + } + ], + "edges": [ + { + "source": "ChatOutput-4sm9Z", + "sourceHandle": "{œbaseClassesœ:[œTextœ,œobjectœ,œstrœ,œRecordœ],œdataTypeœ:œChatOutputœ,œidœ:œChatOutput-4sm9Zœ}", + "target": "ChatInput-7hPDT", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œChatInput-7hPDTœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}", + "data": { + "targetHandle": { + "fieldName": "input_value", + "id": "ChatInput-7hPDT", + "inputTypes": ["Text"], + "type": "str" + }, + "sourceHandle": { + "baseClasses": ["Text", "object", "str", "Record"], + "dataType": "ChatOutput", + "id": "ChatOutput-4sm9Z" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 stroke-connection", + "id": "reactflow__edge-ChatOutput-4sm9Z{œbaseClassesœ:[œTextœ,œobjectœ,œstrœ,œRecordœ],œdataTypeœ:œChatOutputœ,œidœ:œChatOutput-4sm9Zœ}-ChatInput-7hPDT{œfieldNameœ:œinput_valueœ,œidœ:œChatInput-7hPDTœ,œinputTypesœ:[œTextœ],œtypeœ:œstrœ}" + } + ], + "viewport": { + "x": 316.78239920440234, + "y": 182.84104875768622, + "zoom": 0.6070974421975234 + } + }, + "description": "flow to test ChatInput and output", + "name": "ChatITest", + "last_tested_version": "1.0.0a0", + "is_component": false +} diff --git a/src/frontend/tests/onlyFront/assets/collection.json b/src/frontend/tests/end-to-end/assets/collection.json similarity index 88% rename from src/frontend/tests/onlyFront/assets/collection.json rename to src/frontend/tests/end-to-end/assets/collection.json index 3872089d0..269afc8c9 100644 --- a/src/frontend/tests/onlyFront/assets/collection.json +++ b/src/frontend/tests/end-to-end/assets/collection.json @@ -10,7 +10,10 @@ "height": 631, "id": "ChatOpenAI-Hz56M", "type": "genericNode", - "position": { "x": 543.1816229116944, "y": 942.891611351432 }, + "position": { + "x": 543.1816229116944, + "y": 942.891611351432 + }, "data": { "type": "ChatOpenAI", "node": { @@ -238,7 +241,10 @@ "height": 387, "id": "AgentInitializer-QiQ4x", "type": "genericNode", - "position": { "x": 1036.6064439140812, "y": 645.1919693466587 }, + "position": { + "x": 1036.6064439140812, + "y": 645.1919693466587 + }, "data": { "type": "AgentInitializer", "node": { @@ -316,7 +322,10 @@ "height": 437, "id": "PythonFunctionTool-kX99N", "type": "genericNode", - "position": { "x": 553.050119331742, "y": 412.9533535948685 }, + "position": { + "x": 553.050119331742, + "y": 412.9533535948685 + }, "data": { "type": "PythonFunctionTool", "node": { @@ -380,7 +389,9 @@ "sourceHandle": "{œbaseClassesœ:[œSerializableœ,œBaseChatModelœ,œChatOpenAIœ,œBaseLanguageModelœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-Hz56Mœ}", "target": "AgentInitializer-QiQ4x", "targetHandle": "{œfieldNameœ:œllmœ,œidœ:œAgentInitializer-QiQ4xœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}", - "style": { "stroke": "#555" }, + "style": { + "stroke": "#555" + }, "className": "stroke-gray-900 stroke-connection", "animated": false, "id": "reactflow__edge-ChatOpenAI-Hz56M{œbaseClassesœ:[œSerializableœ,œBaseChatModelœ,œChatOpenAIœ,œBaseLanguageModelœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-Hz56Mœ}-AgentInitializer-QiQ4x{œfieldNameœ:œllmœ,œidœ:œAgentInitializer-QiQ4xœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}", @@ -409,7 +420,9 @@ "sourceHandle": "{œbaseClassesœ:[œToolœ],œdataTypeœ:œPythonFunctionToolœ,œidœ:œPythonFunctionTool-kX99Nœ}", "target": "AgentInitializer-QiQ4x", "targetHandle": "{œfieldNameœ:œtoolsœ,œidœ:œAgentInitializer-QiQ4xœ,œinputTypesœ:null,œtypeœ:œToolœ}", - "style": { "stroke": "#555" }, + "style": { + "stroke": "#555" + }, "className": "stroke-gray-900 stroke-connection", "animated": false, "id": "reactflow__edge-PythonFunctionTool-kX99N{œbaseClassesœ:[œToolœ],œdataTypeœ:œPythonFunctionToolœ,œidœ:œPythonFunctionTool-kX99Nœ}-AgentInitializer-QiQ4x{œfieldNameœ:œtoolsœ,œidœ:œAgentInitializer-QiQ4xœ,œinputTypesœ:null,œtypeœ:œToolœ}", @@ -446,7 +459,10 @@ { "id": "CustomComponent-w4WCp", "type": "genericNode", - "position": { "x": 536, "y": 337 }, + "position": { + "x": 536, + "y": 337 + }, "data": { "type": "CustomComponent", "node": { @@ -456,7 +472,7 @@ "placeholder": "", "show": true, "multiline": true, - "value": "from langflow import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n", + "value": "from langflow.custom import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n", "password": false, "name": "code", "advanced": false, @@ -478,11 +494,18 @@ }, "id": "CustomComponent-w4WCp" }, - "positionAbsolute": { "x": 536, "y": 337 } + "positionAbsolute": { + "x": 536, + "y": 337 + } } ], "edges": [], - "viewport": { "x": 0, "y": 0, "zoom": 1 } + "viewport": { + "x": 0, + "y": 0, + "zoom": 1 + } }, "id": "e43cf2c8-cd64-4936-8170-b207a8b109c4", "user_id": "6f6ebc2c-9e7a-4c35-84fc-51760db10d9b" @@ -497,7 +520,10 @@ "height": 631, "id": "ChatOpenAI-7GFF0", "type": "genericNode", - "position": { "x": 543.1816229116944, "y": 942.891611351432 }, + "position": { + "x": 543.1816229116944, + "y": 942.891611351432 + }, "data": { "type": "ChatOpenAI", "node": { @@ -725,7 +751,10 @@ "height": 387, "id": "AgentInitializer-YJgqs", "type": "genericNode", - "position": { "x": 1036.6064439140812, "y": 645.1919693466587 }, + "position": { + "x": 1036.6064439140812, + "y": 645.1919693466587 + }, "data": { "type": "AgentInitializer", "node": { @@ -803,7 +832,10 @@ "height": 437, "id": "PythonFunctionTool-gqQDg", "type": "genericNode", - "position": { "x": 553.050119331742, "y": 412.9533535948685 }, + "position": { + "x": 553.050119331742, + "y": 412.9533535948685 + }, "data": { "type": "PythonFunctionTool", "node": { @@ -867,7 +899,9 @@ "sourceHandle": "{œbaseClassesœ:[œSerializableœ,œBaseChatModelœ,œChatOpenAIœ,œBaseLanguageModelœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-7GFF0œ}", "target": "AgentInitializer-YJgqs", "targetHandle": "{œfieldNameœ:œllmœ,œidœ:œAgentInitializer-YJgqsœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}", - "style": { "stroke": "#555" }, + "style": { + "stroke": "#555" + }, "className": "stroke-gray-900 stroke-connection", "animated": false, "id": "reactflow__edge-ChatOpenAI-7GFF0{œbaseClassesœ:[œSerializableœ,œBaseChatModelœ,œChatOpenAIœ,œBaseLanguageModelœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-7GFF0œ}-AgentInitializer-YJgqs{œfieldNameœ:œllmœ,œidœ:œAgentInitializer-YJgqsœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}", @@ -896,7 +930,9 @@ "sourceHandle": "{œbaseClassesœ:[œToolœ],œdataTypeœ:œPythonFunctionToolœ,œidœ:œPythonFunctionTool-gqQDgœ}", "target": "AgentInitializer-YJgqs", "targetHandle": "{œfieldNameœ:œtoolsœ,œidœ:œAgentInitializer-YJgqsœ,œinputTypesœ:null,œtypeœ:œToolœ}", - "style": { "stroke": "#555" }, + "style": { + "stroke": "#555" + }, "className": "stroke-gray-900 stroke-connection", "animated": false, "id": "reactflow__edge-PythonFunctionTool-gqQDg{œbaseClassesœ:[œToolœ],œdataTypeœ:œPythonFunctionToolœ,œidœ:œPythonFunctionTool-gqQDgœ}-AgentInitializer-YJgqs{œfieldNameœ:œtoolsœ,œidœ:œAgentInitializer-YJgqsœ,œinputTypesœ:null,œtypeœ:œToolœ}", @@ -933,7 +969,10 @@ { "id": "CustomComponent-iF9Zr", "type": "genericNode", - "position": { "x": 536, "y": 337 }, + "position": { + "x": 536, + "y": 337 + }, "data": { "type": "CustomComponent", "node": { @@ -943,7 +982,7 @@ "placeholder": "", "show": true, "multiline": true, - "value": "from langflow import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n", + "value": "from langflow.custom import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n", "password": false, "name": "code", "advanced": false, @@ -965,11 +1004,18 @@ }, "id": "CustomComponent-iF9Zr" }, - "positionAbsolute": { "x": 536, "y": 337 } + "positionAbsolute": { + "x": 536, + "y": 337 + } } ], "edges": [], - "viewport": { "x": 0, "y": 0, "zoom": 1 } + "viewport": { + "x": 0, + "y": 0, + "zoom": 1 + } }, "id": "88a0e6a1-8144-4bff-b28c-d312ae5c8a10", "user_id": "6f6ebc2c-9e7a-4c35-84fc-51760db10d9b" @@ -984,7 +1030,10 @@ "height": 631, "id": "ChatOpenAI-cljAK", "type": "genericNode", - "position": { "x": 543.1816229116944, "y": 942.891611351432 }, + "position": { + "x": 543.1816229116944, + "y": 942.891611351432 + }, "data": { "type": "ChatOpenAI", "node": { @@ -1212,7 +1261,10 @@ "height": 387, "id": "AgentInitializer-grV0u", "type": "genericNode", - "position": { "x": 1036.6064439140812, "y": 645.1919693466587 }, + "position": { + "x": 1036.6064439140812, + "y": 645.1919693466587 + }, "data": { "type": "AgentInitializer", "node": { @@ -1290,7 +1342,10 @@ "height": 437, "id": "PythonFunctionTool-SctM2", "type": "genericNode", - "position": { "x": 553.050119331742, "y": 412.9533535948685 }, + "position": { + "x": 553.050119331742, + "y": 412.9533535948685 + }, "data": { "type": "PythonFunctionTool", "node": { @@ -1354,7 +1409,9 @@ "sourceHandle": "{œbaseClassesœ:[œSerializableœ,œBaseChatModelœ,œChatOpenAIœ,œBaseLanguageModelœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-cljAKœ}", "target": "AgentInitializer-grV0u", "targetHandle": "{œfieldNameœ:œllmœ,œidœ:œAgentInitializer-grV0uœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}", - "style": { "stroke": "#555" }, + "style": { + "stroke": "#555" + }, "className": "stroke-gray-900 stroke-connection", "animated": false, "id": "reactflow__edge-ChatOpenAI-cljAK{œbaseClassesœ:[œSerializableœ,œBaseChatModelœ,œChatOpenAIœ,œBaseLanguageModelœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-cljAKœ}-AgentInitializer-grV0u{œfieldNameœ:œllmœ,œidœ:œAgentInitializer-grV0uœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}", @@ -1383,7 +1440,9 @@ "sourceHandle": "{œbaseClassesœ:[œToolœ],œdataTypeœ:œPythonFunctionToolœ,œidœ:œPythonFunctionTool-SctM2œ}", "target": "AgentInitializer-grV0u", "targetHandle": "{œfieldNameœ:œtoolsœ,œidœ:œAgentInitializer-grV0uœ,œinputTypesœ:null,œtypeœ:œToolœ}", - "style": { "stroke": "#555" }, + "style": { + "stroke": "#555" + }, "className": "stroke-gray-900 stroke-connection", "animated": false, "id": "reactflow__edge-PythonFunctionTool-SctM2{œbaseClassesœ:[œToolœ],œdataTypeœ:œPythonFunctionToolœ,œidœ:œPythonFunctionTool-SctM2œ}-AgentInitializer-grV0u{œfieldNameœ:œtoolsœ,œidœ:œAgentInitializer-grV0uœ,œinputTypesœ:null,œtypeœ:œToolœ}", @@ -1420,7 +1479,10 @@ { "id": "CustomComponent-z5kAP", "type": "genericNode", - "position": { "x": 536, "y": 337 }, + "position": { + "x": 536, + "y": 337 + }, "data": { "type": "CustomComponent", "node": { @@ -1430,7 +1492,7 @@ "placeholder": "", "show": true, "multiline": true, - "value": "from langflow import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n", + "value": "from langflow.custom import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n", "password": false, "name": "code", "advanced": false, @@ -1452,11 +1514,18 @@ }, "id": "CustomComponent-z5kAP" }, - "positionAbsolute": { "x": 536, "y": 337 } + "positionAbsolute": { + "x": 536, + "y": 337 + } } ], "edges": [], - "viewport": { "x": 0, "y": 0, "zoom": 1 } + "viewport": { + "x": 0, + "y": 0, + "zoom": 1 + } }, "id": "3128b556-35c7-4ced-a834-70fbeb1a410f", "user_id": "6f6ebc2c-9e7a-4c35-84fc-51760db10d9b" @@ -1469,7 +1538,10 @@ { "id": "CustomComponent-ZieNZ", "type": "genericNode", - "position": { "x": 536, "y": 337 }, + "position": { + "x": 536, + "y": 337 + }, "data": { "type": "CustomComponent", "node": { @@ -1479,7 +1551,7 @@ "placeholder": "", "show": true, "multiline": true, - "value": "from langflow import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n", + "value": "from langflow.custom import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n", "password": false, "name": "code", "advanced": false, @@ -1501,11 +1573,18 @@ }, "id": "CustomComponent-ZieNZ" }, - "positionAbsolute": { "x": 536, "y": 337 } + "positionAbsolute": { + "x": 536, + "y": 337 + } } ], "edges": [], - "viewport": { "x": 0, "y": 0, "zoom": 1 } + "viewport": { + "x": 0, + "y": 0, + "zoom": 1 + } }, "id": "d3f2c379-9df5-49a0-b33d-d855c2085949", "user_id": "6f6ebc2c-9e7a-4c35-84fc-51760db10d9b" @@ -1518,7 +1597,10 @@ { "id": "CustomComponent-CcHG0", "type": "genericNode", - "position": { "x": 536, "y": 337 }, + "position": { + "x": 536, + "y": 337 + }, "data": { "type": "CustomComponent", "node": { @@ -1528,7 +1610,7 @@ "placeholder": "", "show": true, "multiline": true, - "value": "from langflow import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n", + "value": "from langflow.custom import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n", "password": false, "name": "code", "advanced": false, @@ -1550,11 +1632,18 @@ }, "id": "CustomComponent-CcHG0" }, - "positionAbsolute": { "x": 536, "y": 337 } + "positionAbsolute": { + "x": 536, + "y": 337 + } } ], "edges": [], - "viewport": { "x": 0, "y": 0, "zoom": 1 } + "viewport": { + "x": 0, + "y": 0, + "zoom": 1 + } }, "id": "74afff1f-b540-43d5-bc66-d18f39d65d57", "user_id": "6f6ebc2c-9e7a-4c35-84fc-51760db10d9b" @@ -1567,7 +1656,10 @@ { "id": "CustomComponent-Q8qSr", "type": "genericNode", - "position": { "x": 536, "y": 337 }, + "position": { + "x": 536, + "y": 337 + }, "data": { "type": "CustomComponent", "node": { @@ -1577,7 +1669,7 @@ "placeholder": "", "show": true, "multiline": true, - "value": "from langflow import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n", + "value": "from langflow.custom import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n", "password": false, "name": "code", "advanced": false, @@ -1599,11 +1691,18 @@ }, "id": "CustomComponent-Q8qSr" }, - "positionAbsolute": { "x": 536, "y": 337 } + "positionAbsolute": { + "x": 536, + "y": 337 + } } ], "edges": [], - "viewport": { "x": 0, "y": 0, "zoom": 1 } + "viewport": { + "x": 0, + "y": 0, + "zoom": 1 + } }, "id": "b0b1c893-6194-4748-ae10-b5f604b271c2", "user_id": "6f6ebc2c-9e7a-4c35-84fc-51760db10d9b" @@ -1616,7 +1715,10 @@ { "id": "CustomComponent-Lgoca", "type": "genericNode", - "position": { "x": 536, "y": 337 }, + "position": { + "x": 536, + "y": 337 + }, "data": { "type": "CustomComponent", "node": { @@ -1626,7 +1728,7 @@ "placeholder": "", "show": true, "multiline": true, - "value": "from langflow import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n", + "value": "from langflow.custom import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n", "password": false, "name": "code", "advanced": false, @@ -1648,11 +1750,18 @@ }, "id": "CustomComponent-Lgoca" }, - "positionAbsolute": { "x": 536, "y": 337 } + "positionAbsolute": { + "x": 536, + "y": 337 + } } ], "edges": [], - "viewport": { "x": 0, "y": 0, "zoom": 1 } + "viewport": { + "x": 0, + "y": 0, + "zoom": 1 + } }, "id": "edf1051d-509b-46a2-84c6-b94bdcdc3a4f", "user_id": "6f6ebc2c-9e7a-4c35-84fc-51760db10d9b" @@ -1665,7 +1774,10 @@ { "id": "CustomComponent-6OJGW", "type": "genericNode", - "position": { "x": 536, "y": 337 }, + "position": { + "x": 536, + "y": 337 + }, "data": { "type": "CustomComponent", "node": { @@ -1675,7 +1787,7 @@ "placeholder": "", "show": true, "multiline": true, - "value": "from langflow import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n", + "value": "from langflow.custom import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n", "password": false, "name": "code", "advanced": false, @@ -1697,11 +1809,18 @@ }, "id": "CustomComponent-6OJGW" }, - "positionAbsolute": { "x": 536, "y": 337 } + "positionAbsolute": { + "x": 536, + "y": 337 + } } ], "edges": [], - "viewport": { "x": 0, "y": 0, "zoom": 1 } + "viewport": { + "x": 0, + "y": 0, + "zoom": 1 + } }, "id": "65b2a4e0-4084-418a-aa86-ee914acb0ab5", "user_id": "6f6ebc2c-9e7a-4c35-84fc-51760db10d9b" @@ -1714,7 +1833,10 @@ { "id": "CustomComponent-tcE83", "type": "genericNode", - "position": { "x": 536, "y": 337 }, + "position": { + "x": 536, + "y": 337 + }, "data": { "type": "CustomComponent", "node": { @@ -1724,7 +1846,7 @@ "placeholder": "", "show": true, "multiline": true, - "value": "from langflow import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n", + "value": "from langflow.custom import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n", "password": false, "name": "code", "advanced": false, @@ -1746,11 +1868,18 @@ }, "id": "CustomComponent-tcE83" }, - "positionAbsolute": { "x": 536, "y": 337 } + "positionAbsolute": { + "x": 536, + "y": 337 + } } ], "edges": [], - "viewport": { "x": 0, "y": 0, "zoom": 1 } + "viewport": { + "x": 0, + "y": 0, + "zoom": 1 + } }, "id": "534e412b-d37b-4133-8029-e5ed139fd55c", "user_id": "6f6ebc2c-9e7a-4c35-84fc-51760db10d9b" @@ -1765,7 +1894,10 @@ "height": 631, "id": "ChatOpenAI-mQEi3", "type": "genericNode", - "position": { "x": 543.1816229116944, "y": 942.891611351432 }, + "position": { + "x": 543.1816229116944, + "y": 942.891611351432 + }, "data": { "type": "ChatOpenAI", "node": { @@ -1993,7 +2125,10 @@ "height": 387, "id": "AgentInitializer-EE8R4", "type": "genericNode", - "position": { "x": 1036.6064439140812, "y": 645.1919693466587 }, + "position": { + "x": 1036.6064439140812, + "y": 645.1919693466587 + }, "data": { "type": "AgentInitializer", "node": { @@ -2071,7 +2206,10 @@ "height": 437, "id": "PythonFunctionTool-YKkDL", "type": "genericNode", - "position": { "x": 553.050119331742, "y": 412.9533535948685 }, + "position": { + "x": 553.050119331742, + "y": 412.9533535948685 + }, "data": { "type": "PythonFunctionTool", "node": { @@ -2135,7 +2273,9 @@ "sourceHandle": "{œbaseClassesœ:[œSerializableœ,œBaseChatModelœ,œChatOpenAIœ,œBaseLanguageModelœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-mQEi3œ}", "target": "AgentInitializer-EE8R4", "targetHandle": "{œfieldNameœ:œllmœ,œidœ:œAgentInitializer-EE8R4œ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}", - "style": { "stroke": "#555" }, + "style": { + "stroke": "#555" + }, "className": "stroke-gray-900 stroke-connection", "animated": false, "id": "reactflow__edge-ChatOpenAI-mQEi3{œbaseClassesœ:[œSerializableœ,œBaseChatModelœ,œChatOpenAIœ,œBaseLanguageModelœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-mQEi3œ}-AgentInitializer-EE8R4{œfieldNameœ:œllmœ,œidœ:œAgentInitializer-EE8R4œ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}", @@ -2164,7 +2304,9 @@ "sourceHandle": "{œbaseClassesœ:[œToolœ],œdataTypeœ:œPythonFunctionToolœ,œidœ:œPythonFunctionTool-YKkDLœ}", "target": "AgentInitializer-EE8R4", "targetHandle": "{œfieldNameœ:œtoolsœ,œidœ:œAgentInitializer-EE8R4œ,œinputTypesœ:null,œtypeœ:œToolœ}", - "style": { "stroke": "#555" }, + "style": { + "stroke": "#555" + }, "className": "stroke-gray-900 stroke-connection", "animated": false, "id": "reactflow__edge-PythonFunctionTool-YKkDL{œbaseClassesœ:[œToolœ],œdataTypeœ:œPythonFunctionToolœ,œidœ:œPythonFunctionTool-YKkDLœ}-AgentInitializer-EE8R4{œfieldNameœ:œtoolsœ,œidœ:œAgentInitializer-EE8R4œ,œinputTypesœ:null,œtypeœ:œToolœ}", @@ -2201,7 +2343,10 @@ { "id": "CustomComponent-T38LS", "type": "genericNode", - "position": { "x": 536, "y": 337 }, + "position": { + "x": 536, + "y": 337 + }, "data": { "type": "CustomComponent", "node": { @@ -2211,7 +2356,7 @@ "placeholder": "", "show": true, "multiline": true, - "value": "from langflow import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n", + "value": "from langflow.custom import CustomComponent\n\nfrom langchain.llms.base import BaseLLM\nfrom langchain.chains import LLMChain\nfrom langchain.prompts import PromptTemplate\nfrom langchain.schema import Document\n\nimport requests\n\nclass YourComponent(CustomComponent):\n display_name: str = \"Custom Component\"\n description: str = \"Create any custom component you want!\"\n\n def build_config(self):\n return { \"url\": { \"multiline\": True, \"required\": True } }\n\n def build(self, url: str, llm: BaseLLM, prompt: PromptTemplate) -> Document:\n response = requests.get(url)\n chain = LLMChain(llm=llm, prompt=prompt)\n result = chain.run(response.text[:300])\n return Document(page_content=str(result))\n", "password": false, "name": "code", "advanced": false, @@ -2233,11 +2378,18 @@ }, "id": "CustomComponent-T38LS" }, - "positionAbsolute": { "x": 536, "y": 337 } + "positionAbsolute": { + "x": 536, + "y": 337 + } } ], "edges": [], - "viewport": { "x": 0, "y": 0, "zoom": 1 } + "viewport": { + "x": 0, + "y": 0, + "zoom": 1 + } }, "id": "ec36a3b7-7b5f-4663-983c-833bcec4d851", "user_id": "6f6ebc2c-9e7a-4c35-84fc-51760db10d9b" @@ -2252,7 +2404,10 @@ "height": 631, "id": "ChatOpenAI-E1XSb", "type": "genericNode", - "position": { "x": 543.1816229116944, "y": 942.891611351432 }, + "position": { + "x": 543.1816229116944, + "y": 942.891611351432 + }, "data": { "type": "ChatOpenAI", "node": { @@ -2480,7 +2635,10 @@ "height": 387, "id": "AgentInitializer-goPm2", "type": "genericNode", - "position": { "x": 1036.6064439140812, "y": 645.1919693466587 }, + "position": { + "x": 1036.6064439140812, + "y": 645.1919693466587 + }, "data": { "type": "AgentInitializer", "node": { @@ -2558,7 +2716,10 @@ "height": 437, "id": "PythonFunctionTool-SQikY", "type": "genericNode", - "position": { "x": 553.050119331742, "y": 412.9533535948685 }, + "position": { + "x": 553.050119331742, + "y": 412.9533535948685 + }, "data": { "type": "PythonFunctionTool", "node": { @@ -2622,7 +2783,9 @@ "sourceHandle": "{œbaseClassesœ:[œSerializableœ,œBaseChatModelœ,œChatOpenAIœ,œBaseLanguageModelœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-E1XSbœ}", "target": "AgentInitializer-goPm2", "targetHandle": "{œfieldNameœ:œllmœ,œidœ:œAgentInitializer-goPm2œ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}", - "style": { "stroke": "#555" }, + "style": { + "stroke": "#555" + }, "className": "stroke-gray-900 stroke-connection", "animated": false, "id": "reactflow__edge-ChatOpenAI-E1XSb{œbaseClassesœ:[œSerializableœ,œBaseChatModelœ,œChatOpenAIœ,œBaseLanguageModelœ],œdataTypeœ:œChatOpenAIœ,œidœ:œChatOpenAI-E1XSbœ}-AgentInitializer-goPm2{œfieldNameœ:œllmœ,œidœ:œAgentInitializer-goPm2œ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}", @@ -2651,7 +2814,9 @@ "sourceHandle": "{œbaseClassesœ:[œToolœ],œdataTypeœ:œPythonFunctionToolœ,œidœ:œPythonFunctionTool-SQikYœ}", "target": "AgentInitializer-goPm2", "targetHandle": "{œfieldNameœ:œtoolsœ,œidœ:œAgentInitializer-goPm2œ,œinputTypesœ:null,œtypeœ:œToolœ}", - "style": { "stroke": "#555" }, + "style": { + "stroke": "#555" + }, "className": "stroke-gray-900 stroke-connection", "animated": false, "id": "reactflow__edge-PythonFunctionTool-SQikY{œbaseClassesœ:[œToolœ],œdataTypeœ:œPythonFunctionToolœ,œidœ:œPythonFunctionTool-SQikYœ}-AgentInitializer-goPm2{œfieldNameœ:œtoolsœ,œidœ:œAgentInitializer-goPm2œ,œinputTypesœ:null,œtypeœ:œToolœ}", diff --git a/src/frontend/tests/onlyFront/assets/flow.json b/src/frontend/tests/end-to-end/assets/flow.json similarity index 100% rename from src/frontend/tests/onlyFront/assets/flow.json rename to src/frontend/tests/end-to-end/assets/flow.json diff --git a/src/frontend/tests/end-to-end/assets/flow_group_test.json b/src/frontend/tests/end-to-end/assets/flow_group_test.json new file mode 100644 index 000000000..c88576305 --- /dev/null +++ b/src/frontend/tests/end-to-end/assets/flow_group_test.json @@ -0,0 +1,532 @@ +{ + "id": "8404c1fc-1bce-43b4-a8bc-3febea587fc8", + "data": { + "nodes": [ + { + "id": "PythonFunctionTool-RfJui", + "type": "genericNode", + "position": { + "x": 117.54690105175428, + "y": -84.2465475108354 + }, + "data": { + "type": "PythonFunctionTool", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "\ndef python_function(text: str) -> str:\n \"\"\"This is a default python function that returns the input text\"\"\"\n return text\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": false, + "dynamic": false, + "info": "", + "title_case": false + }, + "description": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "Returns the Text you send. This is a testing tool.", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "description", + "advanced": false, + "dynamic": false, + "info": "", + "title_case": false, + "input_types": ["Text"] + }, + "name": { + "type": "str", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": "PythonFunction", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "name", + "advanced": false, + "dynamic": false, + "info": "", + "title_case": false, + "input_types": ["Text"] + }, + "return_direct": { + "type": "bool", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "return_direct", + "advanced": false, + "dynamic": false, + "info": "", + "title_case": false + }, + "_type": "PythonFunctionTool" + }, + "description": "Python function to be executed.", + "base_classes": ["BaseTool", "Tool"], + "display_name": "PythonFunctionTool", + "documentation": "", + "custom_fields": {}, + "output_types": [], + "field_formatters": {}, + "pinned": false, + "beta": false + }, + "id": "PythonFunctionTool-RfJui" + }, + "selected": true, + "width": 384, + "height": 466, + "positionAbsolute": { + "x": 117.54690105175428, + "y": -84.2465475108354 + }, + "dragging": false + }, + { + "id": "AgentInitializer-tPdJw", + "type": "genericNode", + "position": { + "x": 677.68677055088, + "y": 127.19859565276168 + }, + "data": { + "type": "AgentInitializer", + "node": { + "template": { + "llm": { + "type": "BaseLanguageModel", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "llm", + "display_name": "Language Model", + "advanced": false, + "dynamic": false, + "info": "", + "title_case": false + }, + "memory": { + "type": "BaseChatMemory", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "memory", + "display_name": "Memory", + "advanced": false, + "dynamic": false, + "info": "", + "title_case": false + }, + "tools": { + "type": "Tool", + "required": true, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "tools", + "display_name": "Tools", + "advanced": false, + "dynamic": false, + "info": "", + "title_case": false + }, + "agent": { + "type": "str", + "required": true, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "zero-shot-react-description", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "zero-shot-react-description", + "react-docstore", + "self-ask-with-search", + "conversational-react-description", + "chat-zero-shot-react-description", + "chat-conversational-react-description", + "structured-chat-zero-shot-react-description", + "openai-functions", + "openai-multi-functions", + "JsonAgent", + "CSVAgent", + "VectorStoreAgent", + "VectorStoreRouterAgent", + "SQLAgent" + ], + "name": "agent", + "display_name": "Agent Type", + "advanced": false, + "dynamic": false, + "info": "", + "title_case": false, + "input_types": ["Text"] + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Callable, List, Optional, Union\n\nfrom langchain.agents import AgentExecutor, AgentType, initialize_agent, types\nfrom langflow.custom import CustomComponent\nfrom langflow.field_typing import BaseChatMemory, BaseLanguageModel, Tool\n\n\nclass AgentInitializerComponent(CustomComponent):\n display_name: str = \"Agent Initializer\"\n description: str = \"Initialize a Langchain Agent.\"\n documentation: str = \"https://python.langchain.com/docs/modules/agents/agent_types/\"\n\n def build_config(self):\n agents = list(types.AGENT_TO_CLASS.keys())\n # field_type and required are optional\n return {\n \"agent\": {\"options\": agents, \"value\": agents[0], \"display_name\": \"Agent Type\"},\n \"max_iterations\": {\"display_name\": \"Max Iterations\", \"value\": 10},\n \"memory\": {\"display_name\": \"Memory\"},\n \"tools\": {\"display_name\": \"Tools\"},\n \"llm\": {\"display_name\": \"Language Model\"},\n \"code\": {\"advanced\": True},\n }\n\n def build(\n self,\n agent: str,\n llm: BaseLanguageModel,\n tools: List[Tool],\n max_iterations: int,\n memory: Optional[BaseChatMemory] = None,\n ) -> Union[AgentExecutor, Callable]:\n agent = AgentType(agent)\n if memory:\n return initialize_agent(\n tools=tools,\n llm=llm,\n agent=agent,\n memory=memory,\n return_intermediate_steps=True,\n handle_parsing_errors=True,\n max_iterations=max_iterations,\n )\n return initialize_agent(\n tools=tools,\n llm=llm,\n agent=agent,\n return_intermediate_steps=True,\n handle_parsing_errors=True,\n max_iterations=max_iterations,\n )\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "title_case": false + }, + "max_iterations": { + "type": "int", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 10, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "max_iterations", + "display_name": "Max Iterations", + "advanced": false, + "dynamic": false, + "info": "", + "title_case": false + }, + "_type": "CustomComponent" + }, + "description": "Initialize a Langchain Agent.", + "base_classes": [ + "Runnable", + "Chain", + "Serializable", + "object", + "AgentExecutor", + "Generic", + "RunnableSerializable", + "Callable" + ], + "display_name": "Agent Initializer", + "documentation": "https://python.langchain.com/docs/modules/agents/agent_types/", + "custom_fields": { + "agent": null, + "llm": null, + "tools": null, + "max_iterations": null, + "memory": null + }, + "output_types": ["AgentExecutor", "Callable"], + "field_formatters": {}, + "pinned": false, + "beta": true + }, + "id": "AgentInitializer-tPdJw" + }, + "selected": false, + "width": 384, + "height": 522 + }, + { + "id": "ChatOpenAISpecs-stxRM", + "type": "genericNode", + "position": { + "x": 18.226716205350385, + "y": 432.6122491402193 + }, + "data": { + "type": "ChatOpenAISpecs", + "node": { + "template": { + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from typing import Optional, Union\n\nfrom langchain.llms import BaseLLM\nfrom langchain_community.chat_models.openai import ChatOpenAI\nfrom langflow.custom import CustomComponent\nfrom langflow.field_typing import BaseLanguageModel, NestedDict\n\n\nclass ChatOpenAIComponent(CustomComponent):\n display_name = \"ChatOpenAI\"\n description = \"`OpenAI` Chat large language models API.\"\n icon = \"OpenAI\"\n\n def build_config(self):\n return {\n \"max_tokens\": {\n \"display_name\": \"Max Tokens\",\n \"advanced\": False,\n \"required\": False,\n },\n \"model_kwargs\": {\n \"display_name\": \"Model Kwargs\",\n \"advanced\": True,\n \"required\": False,\n },\n \"model_name\": {\n \"display_name\": \"Model Name\",\n \"advanced\": False,\n \"required\": False,\n \"options\": [\n \"gpt-4-turbo-preview\",\n \"gpt-4-0125-preview\",\n \"gpt-4-1106-preview\",\n \"gpt-4-vision-preview\",\n \"gpt-3.5-turbo-0125\",\n \"gpt-3.5-turbo-1106\",\n ],\n },\n \"openai_api_base\": {\n \"display_name\": \"OpenAI API Base\",\n \"advanced\": False,\n \"required\": False,\n \"info\": (\n \"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\\n\\n\"\n \"You can change this to use other APIs like JinaChat, LocalAI and Prem.\"\n ),\n },\n \"openai_api_key\": {\n \"display_name\": \"OpenAI API Key\",\n \"advanced\": False,\n \"required\": False,\n \"password\": True,\n },\n \"temperature\": {\n \"display_name\": \"Temperature\",\n \"advanced\": False,\n \"required\": False,\n \"value\": 0.7,\n },\n }\n\n def build(\n self,\n max_tokens: Optional[int] = 256,\n model_kwargs: NestedDict = {},\n model_name: str = \"gpt-4-1106-preview\",\n openai_api_base: Optional[str] = None,\n openai_api_key: Optional[str] = None,\n temperature: float = 0.7,\n ) -> Union[BaseLanguageModel, BaseLLM]:\n if not openai_api_base:\n openai_api_base = \"https://api.openai.com/v1\"\n return ChatOpenAI(\n max_tokens=max_tokens,\n model_kwargs=model_kwargs,\n model=model_name,\n base_url=openai_api_base,\n api_key=openai_api_key,\n temperature=temperature,\n )\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": false, + "dynamic": true, + "info": "", + "title_case": false + }, + "max_tokens": { + "type": "int", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 256, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "max_tokens", + "display_name": "Max Tokens", + "advanced": false, + "dynamic": false, + "info": "", + "title_case": false + }, + "model_kwargs": { + "type": "NestedDict", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": {}, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "model_kwargs", + "display_name": "Model Kwargs", + "advanced": true, + "dynamic": false, + "info": "", + "title_case": false + }, + "model_name": { + "type": "str", + "required": false, + "placeholder": "", + "list": true, + "show": true, + "multiline": false, + "value": "gpt-4-1106-preview", + "fileTypes": [], + "file_path": "", + "password": false, + "options": [ + "gpt-4-turbo-preview", + "gpt-4-0125-preview", + "gpt-4-1106-preview", + "gpt-4-vision-preview", + "gpt-3.5-turbo-0125", + "gpt-3.5-turbo-1106" + ], + "name": "model_name", + "display_name": "Model Name", + "advanced": false, + "dynamic": false, + "info": "", + "title_case": false, + "input_types": ["Text"] + }, + "openai_api_base": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "openai_api_base", + "display_name": "OpenAI API Base", + "advanced": false, + "dynamic": false, + "info": "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.", + "title_case": false, + "input_types": ["Text"] + }, + "openai_api_key": { + "type": "str", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "fileTypes": [], + "file_path": "", + "password": true, + "name": "openai_api_key", + "display_name": "OpenAI API Key", + "advanced": false, + "dynamic": false, + "info": "", + "title_case": false, + "input_types": ["Text"] + }, + "temperature": { + "type": "float", + "required": false, + "placeholder": "", + "list": false, + "show": true, + "multiline": false, + "value": 0.7, + "fileTypes": [], + "file_path": "", + "password": false, + "name": "temperature", + "display_name": "Temperature", + "advanced": false, + "dynamic": false, + "info": "", + "rangeSpec": { + "min": -1, + "max": 1, + "step": 0.1 + }, + "title_case": false + }, + "_type": "CustomComponent" + }, + "description": "`OpenAI` Chat large language models API.", + "icon": "OpenAI", + "base_classes": [ + "Runnable", + "BaseLLM", + "Serializable", + "BaseLanguageModel", + "object", + "Generic", + "RunnableSerializable" + ], + "display_name": "ChatOpenAI", + "documentation": "", + "custom_fields": { + "max_tokens": null, + "model_kwargs": null, + "model_name": null, + "openai_api_base": null, + "openai_api_key": null, + "temperature": null + }, + "output_types": ["BaseLanguageModel", "BaseLLM"], + "field_formatters": {}, + "pinned": false, + "beta": true + }, + "id": "ChatOpenAISpecs-stxRM" + }, + "selected": false, + "width": 384, + "height": 666, + "positionAbsolute": { + "x": 18.226716205350385, + "y": 432.6122491402193 + }, + "dragging": false + } + ], + "edges": [ + { + "source": "ChatOpenAISpecs-stxRM", + "sourceHandle": "{œbaseClassesœ:[œRunnableœ,œBaseLLMœ,œSerializableœ,œBaseLanguageModelœ,œobjectœ,œGenericœ,œRunnableSerializableœ],œdataTypeœ:œChatOpenAISpecsœ,œidœ:œChatOpenAISpecs-stxRMœ}", + "target": "AgentInitializer-tPdJw", + "targetHandle": "{œfieldNameœ:œllmœ,œidœ:œAgentInitializer-tPdJwœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}", + "data": { + "targetHandle": { + "fieldName": "llm", + "id": "AgentInitializer-tPdJw", + "inputTypes": null, + "type": "BaseLanguageModel" + }, + "sourceHandle": { + "baseClasses": [ + "Runnable", + "BaseLLM", + "Serializable", + "BaseLanguageModel", + "object", + "Generic", + "RunnableSerializable" + ], + "dataType": "ChatOpenAISpecs", + "id": "ChatOpenAISpecs-stxRM" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-foreground stroke-connection", + "id": "reactflow__edge-ChatOpenAISpecs-stxRM{œbaseClassesœ:[œRunnableœ,œBaseLLMœ,œSerializableœ,œBaseLanguageModelœ,œobjectœ,œGenericœ,œRunnableSerializableœ],œdataTypeœ:œChatOpenAISpecsœ,œidœ:œChatOpenAISpecs-stxRMœ}-AgentInitializer-tPdJw{œfieldNameœ:œllmœ,œidœ:œAgentInitializer-tPdJwœ,œinputTypesœ:null,œtypeœ:œBaseLanguageModelœ}" + }, + { + "source": "PythonFunctionTool-RfJui", + "sourceHandle": "{œbaseClassesœ:[œBaseToolœ,œToolœ],œdataTypeœ:œPythonFunctionToolœ,œidœ:œPythonFunctionTool-RfJuiœ}", + "target": "AgentInitializer-tPdJw", + "targetHandle": "{œfieldNameœ:œtoolsœ,œidœ:œAgentInitializer-tPdJwœ,œinputTypesœ:null,œtypeœ:œToolœ}", + "data": { + "targetHandle": { + "fieldName": "tools", + "id": "AgentInitializer-tPdJw", + "inputTypes": null, + "type": "Tool" + }, + "sourceHandle": { + "baseClasses": ["BaseTool", "Tool"], + "dataType": "PythonFunctionTool", + "id": "PythonFunctionTool-RfJui" + } + }, + "style": { + "stroke": "#555" + }, + "className": "stroke-foreground stroke-connection", + "id": "reactflow__edge-PythonFunctionTool-RfJui{œbaseClassesœ:[œBaseToolœ,œToolœ],œdataTypeœ:œPythonFunctionToolœ,œidœ:œPythonFunctionTool-RfJuiœ}-AgentInitializer-tPdJw{œfieldNameœ:œtoolsœ,œidœ:œAgentInitializer-tPdJwœ,œinputTypesœ:null,œtypeœ:œToolœ}" + } + ], + "viewport": { + "x": 37.63043052737157, + "y": 71.47518177614131, + "zoom": 0.5140569133280332 + } + }, + "description": "Uncover Business Opportunities with NLP.", + "name": "Untitled document (20)", + "last_tested_version": "0.7.0a0", + "is_component": false +} diff --git a/src/frontend/tests/onlyFront/assets/flowtest.json b/src/frontend/tests/end-to-end/assets/flowtest.json similarity index 54% rename from src/frontend/tests/onlyFront/assets/flowtest.json rename to src/frontend/tests/end-to-end/assets/flowtest.json index 8b83ee270..c4de3d778 100644 --- a/src/frontend/tests/onlyFront/assets/flowtest.json +++ b/src/frontend/tests/end-to-end/assets/flowtest.json @@ -8,7 +8,10 @@ "height": 461, "id": "CustomComponent-MtJjl", "type": "genericNode", - "position": { "x": 534.3712097224906, "y": -135.01908566635723 }, + "position": { + "x": 534.3712097224906, + "y": -135.01908566635723 + }, "data": { "type": "CustomComponent", "node": { @@ -20,7 +23,7 @@ "list": false, "show": true, "multiline": true, - "value": "from langflow import CustomComponent\nfrom langflow.field_typing import Data\nfrom pathlib import Path\nfrom platformdirs import user_cache_dir\nimport os\n\nclass Component(CustomComponent):\n documentation: str = \"http://docs.langflow.org/components/custom\"\n\n def build_config(self):\n return {\"text_input\":{\"display_name\":\"Text Input\", \"input_types\":[\"str\"]},\"save_path\":{\"display_name\":\"Save Path\",\n \"info\":\"Put the full path with the file name and extension\",\"value\":Path(user_cache_dir(\"langflow\"))/\"text.t1.txt\"}}\n\n def build(self, text_input:str,save_path:str) -> str:\n try:\n # Create the directory if it doesn't exist\n os.makedirs(os.path.dirname(save_path), exist_ok=True)\n\n # Open the file in write mode and save the text\n with open(save_path, 'w') as file:\n file.write(text_input)\n except Exception as e:\n raise e\n self.status = text_input\n return text_input", + "value": "from langflow.custom import CustomComponent\nfrom langflow.field_typing import Data\nfrom pathlib import Path\nfrom platformdirs import user_cache_dir\nimport os\n\nclass Component(CustomComponent):\n documentation: str = \"http://docs.langflow.org/components/custom\"\n\n def build_config(self):\n return {\"text_input\":{\"display_name\":\"Text Input\", \"input_types\":[\"str\"]},\"save_path\":{\"display_name\":\"Save Path\",\n \"info\":\"Put the full path with the file name and extension\",\"value\":Path(user_cache_dir(\"langflow\"))/\"text.t1.txt\"}}\n\n def build(self, text_input:str,save_path:str) -> str:\n try:\n # Create the directory if it doesn't exist\n os.makedirs(os.path.dirname(save_path), exist_ok=True)\n\n # Open the file in write mode and save the text\n with open(save_path, 'w') as file:\n file.write(text_input)\n except Exception as e:\n raise e\n self.status = text_input\n return text_input", "fileTypes": [], "file_path": "", "password": false, @@ -69,7 +72,10 @@ "base_classes": ["str"], "display_name": "text checkpoint", "documentation": "http://docs.langflow.org/components/custom", - "custom_fields": { "save_path": null, "text_input": null }, + "custom_fields": { + "save_path": null, + "text_input": null + }, "output_types": ["str"], "field_formatters": {}, "beta": true @@ -78,14 +84,20 @@ }, "selected": false, "dragging": false, - "positionAbsolute": { "x": 534.3712097224906, "y": -135.01908566635723 } + "positionAbsolute": { + "x": 534.3712097224906, + "y": -135.01908566635723 + } }, { "width": 384, "height": 453, "id": "CustomComponent-7NQoq", "type": "genericNode", - "position": { "x": 27.487979888011637, "y": -414.43998171034826 }, + "position": { + "x": 27.487979888011637, + "y": -414.43998171034826 + }, "data": { "type": "CustomComponent", "node": { @@ -131,7 +143,7 @@ "list": false, "show": true, "multiline": true, - "value": "from langflow import CustomComponent\nfrom typing import Optional, List, Dict, Union\nfrom langflow.field_typing import (\n AgentExecutor,\n BaseChatMemory,\n BaseLanguageModel,\n BaseLLM,\n BaseLoader,\n BaseMemory,\n BaseOutputParser,\n BasePromptTemplate,\n BaseRetriever,\n Callable,\n Chain,\n ChatPromptTemplate,\n Data,\n Document,\n Embeddings,\n NestedDict,\n Object,\n PromptTemplate,\n TextSplitter,\n Tool,\n VectorStore,\n)\n\nfrom openai import OpenAI\nimport os\nimport ffmpeg\n\nclass Component(CustomComponent):\n display_name: str = \"Whisper Transcriber\"\n description: str = \"Converts audio to text using OpenAI's Whisper.\"\n\n def build_config(self):\n return {\"audio\": {\"field_type\": \"file\", \"suffixes\": [\".mp3\", \".mp4\", \".m4a\"]}, \"OpenAIKey\": {\"field_type\": \"str\", \"password\": True}}\n\n def calculate_segment_duration(self, audio_path, target_chunk_size_mb=24):\n # Calculate the target chunk size in bytes\n target_chunk_size_bytes = target_chunk_size_mb * 1024 * 1024\n\n # Use ffprobe to get the audio file information\n ffprobe_output = ffmpeg.probe(audio_path)\n print(ffprobe_output)\n # Convert duration to float\n duration = float(ffprobe_output[\"format\"][\"duration\"])\n\n # Calculate the approximate bitrate\n bitrate = os.path.getsize(audio_path) / duration\n\n # Calculate the segment duration to achieve the target chunk size\n segment_duration = target_chunk_size_bytes / bitrate\n\n return segment_duration\n\n def split_audio_into_chunks(self, audio_path, target_chunk_size_mb=24):\n # Calculate the segment duration\n segment_duration = self.calculate_segment_duration(audio_path, target_chunk_size_mb)\n\n # Create a directory to store the chunks\n output_directory = f\"{os.path.splitext(audio_path)[0]}_chunks\"\n os.makedirs(output_directory, exist_ok=True)\n\n # Use ffmpeg-python to split the audio file into chunks\n (\n ffmpeg.input(audio_path)\n .output(f\"{output_directory}/%03d{os.path.splitext(audio_path)[1]}\", codec=\"copy\", f=\"segment\", segment_time=segment_duration)\n .run()\n )\n\n # Get the list of generated chunk files\n chunks = [os.path.join(output_directory, file) for file in os.listdir(output_directory)]\n\n return chunks\n\n def build(self, audio: str, OpenAIKey: str) -> str:\n # Split audio into chunks\n audio_chunks = self.split_audio_into_chunks(audio)\n\n client = OpenAI(api_key=OpenAIKey)\n transcripts = []\n\n try:\n for chunk in audio_chunks:\n with open(chunk, \"rb\") as chunk_file:\n transcript = client.audio.transcriptions.create(\n model=\"whisper-1\",\n file=chunk_file,\n response_format=\"text\"\n )\n transcripts.append(transcript)\n finally:\n # Clean up temporary chunk files\n for chunk in audio_chunks:\n os.remove(chunk)\n\n # Concatenate transcripts into the final response\n final_response = \"\\n\".join(transcripts)\n self.status = final_response\n return final_response\n", + "value": "from langflow.custom import CustomComponent\nfrom typing import Optional, List, Dict, Union\nfrom langflow.field_typing import (\n AgentExecutor,\n BaseChatMemory,\n BaseLanguageModel,\n BaseLLM,\n BaseLoader,\n BaseMemory,\n BaseOutputParser,\n BasePromptTemplate,\n BaseRetriever,\n Callable,\n Chain,\n ChatPromptTemplate,\n Data,\n Document,\n Embeddings,\n NestedDict,\n Object,\n PromptTemplate,\n TextSplitter,\n Tool,\n VectorStore,\n)\n\nfrom openai import OpenAI\nimport os\nimport ffmpeg\n\nclass Component(CustomComponent):\n display_name: str = \"Whisper Transcriber\"\n description: str = \"Converts audio to text using OpenAI's Whisper.\"\n\n def build_config(self):\n return {\"audio\": {\"field_type\": \"file\", \"suffixes\": [\".mp3\", \".mp4\", \".m4a\"]}, \"OpenAIKey\": {\"field_type\": \"str\", \"password\": True}}\n\n def calculate_segment_duration(self, audio_path, target_chunk_size_mb=24):\n # Calculate the target chunk size in bytes\n target_chunk_size_bytes = target_chunk_size_mb * 1024 * 1024\n\n # Use ffprobe to get the audio file information\n ffprobe_output = ffmpeg.probe(audio_path)\n print(ffprobe_output)\n # Convert duration to float\n duration = float(ffprobe_output[\"format\"][\"duration\"])\n\n # Calculate the approximate bitrate\n bitrate = os.path.getsize(audio_path) / duration\n\n # Calculate the segment duration to achieve the target chunk size\n segment_duration = target_chunk_size_bytes / bitrate\n\n return segment_duration\n\n def split_audio_into_chunks(self, audio_path, target_chunk_size_mb=24):\n # Calculate the segment duration\n segment_duration = self.calculate_segment_duration(audio_path, target_chunk_size_mb)\n\n # Create a directory to store the chunks\n output_directory = f\"{os.path.splitext(audio_path)[0]}_chunks\"\n os.makedirs(output_directory, exist_ok=True)\n\n # Use ffmpeg-python to split the audio file into chunks\n (\n ffmpeg.input(audio_path)\n .output(f\"{output_directory}/%03d{os.path.splitext(audio_path)[1]}\", codec=\"copy\", f=\"segment\", segment_time=segment_duration)\n .run()\n )\n\n # Get the list of generated chunk files\n chunks = [os.path.join(output_directory, file) for file in os.listdir(output_directory)]\n\n return chunks\n\n def build(self, audio: str, OpenAIKey: str) -> str:\n # Split audio into chunks\n audio_chunks = self.split_audio_into_chunks(audio)\n\n client = OpenAI(api_key=OpenAIKey)\n transcripts = []\n\n try:\n for chunk in audio_chunks:\n with open(chunk, \"rb\") as chunk_file:\n transcript = client.audio.transcriptions.create(\n model=\"whisper-1\",\n file=chunk_file,\n response_format=\"text\"\n )\n transcripts.append(transcript)\n finally:\n # Clean up temporary chunk files\n for chunk in audio_chunks:\n os.remove(chunk)\n\n # Concatenate transcripts into the final response\n final_response = \"\\n\".join(transcripts)\n self.status = final_response\n return final_response\n", "fileTypes": [], "file_path": "", "password": false, @@ -146,7 +158,10 @@ "base_classes": ["str"], "display_name": "Whisper Transcriber", "documentation": "", - "custom_fields": { "OpenAIKey": null, "audio": null }, + "custom_fields": { + "OpenAIKey": null, + "audio": null + }, "output_types": ["str"], "field_formatters": {}, "beta": true @@ -180,13 +195,19 @@ "id": "CustomComponent-7NQoq" } }, - "style": { "stroke": "#555" }, + "style": { + "stroke": "#555" + }, "className": "stroke-gray-900 stroke-connection", "animated": false, "id": "reactflow__edge-CustomComponent-7NQoq{œbaseClassesœ:[œstrœ],œdataTypeœ:œCustomComponentœ,œidœ:œCustomComponent-7NQoqœ}-CustomComponent-MtJjl{œfieldNameœ:œtext_inputœ,œidœ:œCustomComponent-MtJjlœ,œinputTypesœ:[œstrœ],œtypeœ:œstrœ}" } ], - "viewport": { "x": 119.37759169012509, "y": 351.3082742479685, "zoom": 1 } + "viewport": { + "x": 119.37759169012509, + "y": 351.3082742479685, + "zoom": 1 + } }, "is_component": false, "updated_at": "2023-12-13T23:51:56.874099", diff --git a/src/frontend/tests/onlyFront/auto_login.spec.ts b/src/frontend/tests/end-to-end/auto_login.spec.ts similarity index 52% rename from src/frontend/tests/onlyFront/auto_login.spec.ts rename to src/frontend/tests/end-to-end/auto_login.spec.ts index cdceca5e5..582e52bb8 100644 --- a/src/frontend/tests/onlyFront/auto_login.spec.ts +++ b/src/frontend/tests/end-to-end/auto_login.spec.ts @@ -1,27 +1,29 @@ import { test } from "@playwright/test"; - +test.beforeEach(async ({ page }) => { + // await page.waitForTimeout(16000); + // test.setTimeout(140000); +}); test.describe("Auto_login tests", () => { test("auto_login sign in", async ({ page }) => { - await page.routeFromHAR("harFiles/langflow.har", { - url: "**/api/v1/**", - update: false, - }); - await page.goto("http:localhost:3000/"); + await page.goto("/"); await page.locator('//*[@id="new-project-btn"]').click(); }); test("auto_login block_admin", async ({ page }) => { - await page.routeFromHAR("harFiles/langflow.har", { - url: "**/api/v1/**", - update: false, - }); - await page.goto("http:localhost:3000/"); + await page.goto("/"); await page.locator('//*[@id="new-project-btn"]').click(); - await page.goto("http:localhost:3000/login"); + await page.waitForTimeout(5000); + + await page.goto("/login"); await page.locator('//*[@id="new-project-btn"]').click(); - await page.goto("http:localhost:3000/admin"); + await page.waitForTimeout(5000); + + await page.goto("/admin"); await page.locator('//*[@id="new-project-btn"]').click(); - await page.goto("http:localhost:3000/admin/login"); + await page.waitForTimeout(5000); + + await page.goto("/admin/login"); await page.locator('//*[@id="new-project-btn"]').click(); + await page.waitForTimeout(5000); }); }); diff --git a/src/frontend/tests/end-to-end/chat_io.spec.ts b/src/frontend/tests/end-to-end/chat_io.spec.ts new file mode 100644 index 000000000..b37ebfede --- /dev/null +++ b/src/frontend/tests/end-to-end/chat_io.spec.ts @@ -0,0 +1,46 @@ +import { test } from "@playwright/test"; +import { readFileSync } from "fs"; +test.beforeEach(async ({ page }) => { + // await page.waitForTimeout(20000); + // test.setTimeout(120000); +}); +test("chat_io_teste", async ({ page }) => { + await page.goto("/"); + await page.locator("span").filter({ hasText: "My Collection" }).isVisible(); + // Read your file into a buffer. + const jsonContent = readFileSync( + "tests/end-to-end/assets/ChatTest.json", + "utf-8" + ); + + // Create the DataTransfer and File + const dataTransfer = await page.evaluateHandle((data) => { + const dt = new DataTransfer(); + // Convert the buffer to a hex array + const file = new File([data], "ChatTest.json", { + type: "application/json", + }); + dt.items.add(file); + return dt; + }, jsonContent); + + await page.locator('//*[@id="new-project-btn"]').click(); + await page.waitForTimeout(2000); + + await page.getByTestId("blank-flow").click(); + await page.waitForTimeout(2000); + + // Now dispatch + await page.dispatchEvent( + '//*[@id="react-flow-id"]/div[1]/div[1]/div', + "drop", + { + dataTransfer, + } + ); + await page.getByLabel("fit view").click(); + await page.getByText("Run", { exact: true }).click(); + await page.getByPlaceholder("Send a message...").click(); + await page.getByPlaceholder("Send a message...").fill("teste"); + await page.getByRole("button").nth(1).click(); +}); diff --git a/src/frontend/tests/end-to-end/codeAreaModalComponent.spec.ts b/src/frontend/tests/end-to-end/codeAreaModalComponent.spec.ts index 8a604bd3d..322070faa 100644 --- a/src/frontend/tests/end-to-end/codeAreaModalComponent.spec.ts +++ b/src/frontend/tests/end-to-end/codeAreaModalComponent.spec.ts @@ -1,5 +1,8 @@ import { expect, test } from "@playwright/test"; - +test.beforeEach(async ({ page }) => { + await page.waitForTimeout(2000); + test.setTimeout(120000); +}); test("CodeAreaModalComponent", async ({ page }) => { await page.goto("http://localhost:3000/"); await page.waitForTimeout(2000); @@ -7,6 +10,9 @@ test("CodeAreaModalComponent", async ({ page }) => { await page.locator('//*[@id="new-project-btn"]').click(); await page.waitForTimeout(2000); + await page.getByTestId("blank-flow").click(); + await page.waitForTimeout(2000); + await page.getByPlaceholder("Search").click(); await page.getByPlaceholder("Search").fill("pythonfunctiontool"); @@ -18,117 +24,35 @@ test("CodeAreaModalComponent", async ({ page }) => { await page.mouse.up(); await page.mouse.down(); - await page.locator('//*[@id="code-input-0"]').click(); + await page.getByTestId("div-generic-node").click(); + await page.getByTestId("code-button-modal").click(); let value = await page.locator('//*[@id="codeValue"]').inputValue(); - - if ( - value != - 'def python_function(text: str) -> str: """This is a default python function that returns the input text""" return text' - ) { - expect(false).toBeTruthy(); - } - + const code = + 'def python_function(text: str) -> str:\n """This is a default python function that returns the input text"""\n return text'; + const wCode = + 'def python_function(text: str) -> st: """This is a default python function that returns the input text""" return text'; + const assertCode = + 'def python_function(text: str) -> str: """This is a default python function that returns the input text""" return text'; + await page + .locator("#CodeEditor div") + .filter({ hasText: "def python_function(text: str" }) + .nth(1) + .click(); + await page.locator("textarea").press("Control+a"); + await page.locator("textarea").fill(wCode); await page.locator('//*[@id="checkAndSaveBtn"]').click(); - - await page.getByTestId("more-options-modal").click(); - await page.getByTestId("edit-button-modal").click(); - - await page.locator('//*[@id="showcode"]').click(); - expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeFalsy(); - - await page.locator('//*[@id="showdescription"]').click(); + await page.waitForTimeout(1000); expect( - await page.locator('//*[@id="showdescription"]').isChecked() - ).toBeFalsy(); - - await page.locator('//*[@id="showname"]').click(); - expect(await page.locator('//*[@id="showname"]').isChecked()).toBeFalsy(); - - await page.locator('//*[@id="showreturn_direct"]').click(); - expect( - await page.locator('//*[@id="showreturn_direct"]').isChecked() - ).toBeFalsy(); - - await page.locator('//*[@id="showcode"]').click(); - expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeTruthy(); - - await page.locator('//*[@id="showdescription"]').click(); - expect( - await page.locator('//*[@id="showdescription"]').isChecked() + await page.getByText("invalid syntax (, line 1)").isVisible() ).toBeTruthy(); - - await page.locator('//*[@id="showname"]').click(); - expect(await page.locator('//*[@id="showname"]').isChecked()).toBeTruthy(); - - await page.locator('//*[@id="showreturn_direct"]').click(); - expect( - await page.locator('//*[@id="showreturn_direct"]').isChecked() - ).toBeTruthy(); - - await page.locator('//*[@id="showcode"]').click(); - expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeFalsy(); - - await page.locator('//*[@id="showdescription"]').click(); - expect( - await page.locator('//*[@id="showdescription"]').isChecked() - ).toBeFalsy(); - - await page.locator('//*[@id="showname"]').click(); - expect(await page.locator('//*[@id="showname"]').isChecked()).toBeFalsy(); - - await page.locator('//*[@id="showreturn_direct"]').click(); - expect( - await page.locator('//*[@id="showreturn_direct"]').isChecked() - ).toBeFalsy(); - - await page.locator('//*[@id="showcode"]').click(); - expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeTruthy(); - - await page.locator('//*[@id="showdescription"]').click(); - expect( - await page.locator('//*[@id="showdescription"]').isChecked() - ).toBeTruthy(); - - await page.locator('//*[@id="showname"]').click(); - expect(await page.locator('//*[@id="showname"]').isChecked()).toBeTruthy(); - - await page.locator('//*[@id="showreturn_direct"]').click(); - expect( - await page.locator('//*[@id="showreturn_direct"]').isChecked() - ).toBeTruthy(); - - await page.locator('//*[@id="showcode"]').click(); - expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeFalsy(); - - await page.locator('//*[@id="saveChangesBtn"]').click(); - - const plusButtonLocator = page.locator('//*[@id="code-input-0"]'); - const elementCount = await plusButtonLocator.count(); - if (elementCount === 0) { - expect(true).toBeTruthy(); - - await page.getByTestId("more-options-modal").click(); - await page.getByTestId("edit-button-modal").click(); - - await page.locator('//*[@id="showcode"]').click(); - expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeTruthy(); - - await page.locator('//*[@id="code-area-edit0"]').click(); - - let value = await page.locator('//*[@id="codeValue"]').inputValue(); - - if ( - value != - 'def python_function(text: str) -> str: """This is a default python function that returns the input text""" return text' - ) { - expect(false).toBeTruthy(); - } - - await page.locator('//*[@id="checkAndSaveBtn"]').click(); - - await page.locator('//*[@id="saveChangesBtn"]').click(); - - await page.locator('//*[@id="code-input-0"]').click(); - } + await page.locator("textarea").press("Control+a"); + await page.locator("textarea").fill(wCode); + await page.locator("textarea").fill(code); + await page.locator('//*[@id="checkAndSaveBtn"]').click(); + expect(await page.getByText("Code is ready to run").isVisible()).toBeTruthy(); + await page.getByTestId("code-button-modal").click(); + expect(await page.locator('//*[@id="codeValue"]').inputValue()).toBe( + assertCode + ); }); diff --git a/src/frontend/tests/end-to-end/curl_api_generation.spec.ts b/src/frontend/tests/end-to-end/curl_api_generation.spec.ts new file mode 100644 index 000000000..b725badb1 --- /dev/null +++ b/src/frontend/tests/end-to-end/curl_api_generation.spec.ts @@ -0,0 +1,17 @@ +import { expect, test } from "@playwright/test"; + +test("curl_api_generation", async ({ page, context }) => { + await page.goto("/"); + await page.locator('//*[@id="new-project-btn"]').click(); + await context.grantPermissions(["clipboard-read", "clipboard-write"]); + await page.getByRole("heading", { name: "Data Ingestion" }).click(); + await page.waitForTimeout(2000); + await page.getByText("API", { exact: true }).click(); + await page.getByRole("tab", { name: "cURL" }).click(); + await page.getByRole("button", { name: "Copy Code" }).click(); + const handle = await page.evaluateHandle(() => + navigator.clipboard.readText() + ); + const clipboardContent = await handle.jsonValue(); + expect(clipboardContent.length).toBeGreaterThan(0); +}); diff --git a/src/frontend/tests/onlyFront/dragAndDrop.spec.ts b/src/frontend/tests/end-to-end/dragAndDrop.spec.ts similarity index 68% rename from src/frontend/tests/onlyFront/dragAndDrop.spec.ts rename to src/frontend/tests/end-to-end/dragAndDrop.spec.ts index 09ed9b669..144835cd0 100644 --- a/src/frontend/tests/onlyFront/dragAndDrop.spec.ts +++ b/src/frontend/tests/end-to-end/dragAndDrop.spec.ts @@ -1,24 +1,17 @@ import { expect, test } from "@playwright/test"; import { readFileSync } from "fs"; - +test.beforeEach(async ({ page }) => { + // await page.waitForTimeout(3000); + // test.setTimeout(120000); +}); test.describe("drag and drop test", () => { /// test("drop collection", async ({ page }) => { - await page.routeFromHAR("harFiles/langflow.har", { - url: "**/api/v1/**", - update: false, - }); - await page.route("**/api/v1/flows/", async (route) => { - const json = { - id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210", - }; - await route.fulfill({ json, status: 201 }); - }); - await page.goto("http:localhost:3000/"); + await page.goto("/"); await page.locator("span").filter({ hasText: "My Collection" }).isVisible(); // Read your file into a buffer. const jsonContent = readFileSync( - "tests/onlyFront/assets/collection.json", + "tests/end-to-end/assets/collection.json", "utf-8" ); @@ -42,9 +35,7 @@ test.describe("drag and drop test", () => { } ); - await page - .getByTestId("edit-flow-button-e9ac1bdc-429b-475d-ac03-d26f9a2a3210-0") - .click(); + await page.getByText("Edit Flow").first().click(); await page.waitForTimeout(2000); const genericNoda = page.getByTestId("div-generic-node"); diff --git a/src/frontend/tests/end-to-end/dropdownComponent.spec.ts b/src/frontend/tests/end-to-end/dropdownComponent.spec.ts new file mode 100644 index 000000000..a0995a3e0 --- /dev/null +++ b/src/frontend/tests/end-to-end/dropdownComponent.spec.ts @@ -0,0 +1,260 @@ +import { expect, test } from "@playwright/test"; +test.beforeEach(async ({ page }) => { + // await page.waitForTimeout(4000); + // test.setTimeout(120000); +}); +test("dropDownComponent", async ({ page }) => { + await page.goto("/"); + await page.waitForTimeout(2000); + + await page.locator('//*[@id="new-project-btn"]').click(); + await page.waitForTimeout(2000); + + await page.getByTestId("blank-flow").click(); + await page.waitForTimeout(2000); + + await page.getByPlaceholder("Search").click(); + await page.getByPlaceholder("Search").fill("amazon"); + + await page.waitForTimeout(2000); + + await page + .getByTestId("model_specsAmazon Bedrock") + .first() + .dragTo(page.locator('//*[@id="react-flow-id"]')); + await page.mouse.up(); + await page.mouse.down(); + + await page.getByTestId("dropdown-model_id-display").click(); + await page.getByTestId("ai21.j2-grande-instruct-0-option").click(); + + let value = await page.getByTestId("dropdown-model_id-display").innerText(); + if (value !== "ai21.j2-grande-instruct") { + expect(false).toBeTruthy(); + } + + await page.getByTestId("dropdown-model_id-display").click(); + await page.getByTestId("ai21.j2-jumbo-instruct-1-option").click(); + + value = await page.getByTestId("dropdown-model_id-display").innerText(); + if (value !== "ai21.j2-jumbo-instruct") { + expect(false).toBeTruthy(); + } + + await page.getByTestId("more-options-modal").click(); + await page.getByTestId("edit-button-modal").click(); + + value = await page.getByTestId("dropdown-edit-model_id-display").innerText(); + if (value !== "ai21.j2-jumbo-instruct") { + expect(false).toBeTruthy(); + } + + await page.locator('//*[@id="showcache"]').click(); + expect(await page.locator('//*[@id="showcache"]').isChecked()).toBeFalsy(); + + await page.locator('//*[@id="showcache"]').click(); + expect(await page.locator('//*[@id="showcache"]').isChecked()).toBeTruthy(); + + await page.locator('//*[@id="showcredentials_profile_name"]').click(); + expect( + await page.locator('//*[@id="showcredentials_profile_name"]').isChecked() + ).toBeFalsy(); + + await page.locator('//*[@id="showcredentials_profile_name"]').click(); + expect( + await page.locator('//*[@id="showcredentials_profile_name"]').isChecked() + ).toBeTruthy(); + + await page.locator('//*[@id="showendpoint_url"]').click(); + expect( + await page.locator('//*[@id="showendpoint_url"]').isChecked() + ).toBeFalsy(); + + await page.locator('//*[@id="showendpoint_url"]').click(); + expect( + await page.locator('//*[@id="showendpoint_url"]').isChecked() + ).toBeTruthy(); + + await page.locator('//*[@id="showmodel_kwargs"]').click(); + expect( + await page.locator('//*[@id="showmodel_kwargs"]').isChecked() + ).toBeFalsy(); + + await page.locator('//*[@id="showmodel_kwargs"]').click(); + expect( + await page.locator('//*[@id="showmodel_kwargs"]').isChecked() + ).toBeTruthy(); + + await page.locator('//*[@id="showregion_name"]').click(); + expect( + await page.locator('//*[@id="showregion_name"]').isChecked() + ).toBeFalsy(); + + await page.locator('//*[@id="showregion_name"]').click(); + expect( + await page.locator('//*[@id="showregion_name"]').isChecked() + ).toBeTruthy(); + + await page.locator('//*[@id="showstreaming"]').click(); + expect( + await page.locator('//*[@id="showstreaming"]').isChecked() + ).toBeFalsy(); + + await page.locator('//*[@id="showstreaming"]').click(); + expect( + await page.locator('//*[@id="showstreaming"]').isChecked() + ).toBeTruthy(); + + // showmodel_id + await page.locator('//*[@id="showmodel_id"]').click(); + expect(await page.locator('//*[@id="showmodel_id"]').isChecked()).toBeFalsy(); + + // showmodel_id + await page.locator('//*[@id="showmodel_id"]').click(); + expect( + await page.locator('//*[@id="showmodel_id"]').isChecked() + ).toBeTruthy(); + + await page.locator('//*[@id="showcache"]').click(); + expect(await page.locator('//*[@id="showcache"]').isChecked()).toBeFalsy(); + + await page.locator('//*[@id="showcache"]').click(); + expect(await page.locator('//*[@id="showcache"]').isChecked()).toBeTruthy(); + + await page.locator('//*[@id="showcredentials_profile_name"]').click(); + expect( + await page.locator('//*[@id="showcredentials_profile_name"]').isChecked() + ).toBeFalsy(); + + await page.locator('//*[@id="showcredentials_profile_name"]').click(); + expect( + await page.locator('//*[@id="showcredentials_profile_name"]').isChecked() + ).toBeTruthy(); + + await page.locator('//*[@id="showendpoint_url"]').click(); + expect( + await page.locator('//*[@id="showendpoint_url"]').isChecked() + ).toBeFalsy(); + + await page.locator('//*[@id="showendpoint_url"]').click(); + expect( + await page.locator('//*[@id="showendpoint_url"]').isChecked() + ).toBeTruthy(); + + await page.locator('//*[@id="showmodel_kwargs"]').click(); + expect( + await page.locator('//*[@id="showmodel_kwargs"]').isChecked() + ).toBeFalsy(); + + await page.locator('//*[@id="showmodel_kwargs"]').click(); + expect( + await page.locator('//*[@id="showmodel_kwargs"]').isChecked() + ).toBeTruthy(); + + await page.locator('//*[@id="showregion_name"]').click(); + expect( + await page.locator('//*[@id="showregion_name"]').isChecked() + ).toBeFalsy(); + + await page.locator('//*[@id="showregion_name"]').click(); + expect( + await page.locator('//*[@id="showregion_name"]').isChecked() + ).toBeTruthy(); + + await page.locator('//*[@id="showstreaming"]').click(); + expect( + await page.locator('//*[@id="showstreaming"]').isChecked() + ).toBeFalsy(); + + await page.locator('//*[@id="showstreaming"]').click(); + expect( + await page.locator('//*[@id="showstreaming"]').isChecked() + ).toBeTruthy(); + + // showmodel_id + await page.locator('//*[@id="showmodel_id"]').click(); + expect(await page.locator('//*[@id="showmodel_id"]').isChecked()).toBeFalsy(); + + // showmodel_id + await page.locator('//*[@id="showmodel_id"]').click(); + expect( + await page.locator('//*[@id="showmodel_id"]').isChecked() + ).toBeTruthy(); + + await page.getByTestId("dropdown-edit-model_id-display").click(); + await page.getByTestId("ai21.j2-ultra-v1-5-option").click(); + + value = await page.getByTestId("dropdown-edit-model_id-display").innerText(); + if (value !== "ai21.j2-ultra-v1") { + expect(false).toBeTruthy(); + } + + await page.locator('//*[@id="saveChangesBtn"]').click(); + + value = await page.getByTestId("dropdown-model_id-display").innerText(); + if (value !== "ai21.j2-ultra-v1") { + expect(false).toBeTruthy(); + } + await page.getByTestId("code-button-modal").click(); + await page + .locator("#CodeEditor div") + .filter({ hasText: "from typing import" }) + .nth(1) + .click(); + await page.locator("textarea").press("Control+a"); + const emptyOptionsCode = `from typing import Optional +from langchain.llms.base import BaseLLM +from langchain_community.llms.bedrock import Bedrock + +from langflow.interface.custom.custom_component import CustomComponent + + +class AmazonBedrockComponent(CustomComponent): + display_name: str = "Amazon Bedrock" + description: str = "LLM model from Amazon Bedrock." + icon = "Amazon" + + def build_config(self): + return { + "model_id": { + "display_name": "Model Id", + "options": [], + }, + "credentials_profile_name": {"display_name": "Credentials Profile Name"}, + "streaming": {"display_name": "Streaming", "field_type": "bool"}, + "endpoint_url": {"display_name": "Endpoint URL"}, + "region_name": {"display_name": "Region Name"}, + "model_kwargs": {"display_name": "Model Kwargs"}, + "cache": {"display_name": "Cache"}, + "code": {"advanced": True}, + } + + def build( + self, + model_id: str = "anthropic.claude-instant-v1", + credentials_profile_name: Optional[str] = None, + region_name: Optional[str] = None, + model_kwargs: Optional[dict] = None, + endpoint_url: Optional[str] = None, + streaming: bool = False, + cache: Optional[bool] = None, + ) -> BaseLLM: + try: + output = Bedrock( + credentials_profile_name=credentials_profile_name, + model_id=model_id, + region_name=region_name, + model_kwargs=model_kwargs, + endpoint_url=endpoint_url, + streaming=streaming, + cache=cache, + ) # type: ignore + except Exception as e: + raise ValueError("Could not connect to AmazonBedrock API.") from e + return output + + `; + await page.locator("textarea").fill(emptyOptionsCode); + await page.getByRole("button", { name: "Check & Save" }).click(); + await page.getByText("No parameters are available for display.").isVisible(); +}); diff --git a/src/frontend/tests/onlyFront/floatComponent.spec.ts b/src/frontend/tests/end-to-end/floatComponent.spec.ts similarity index 91% rename from src/frontend/tests/onlyFront/floatComponent.spec.ts rename to src/frontend/tests/end-to-end/floatComponent.spec.ts index e3b55cbad..2e0a2a8ad 100644 --- a/src/frontend/tests/onlyFront/floatComponent.spec.ts +++ b/src/frontend/tests/end-to-end/floatComponent.spec.ts @@ -1,29 +1,25 @@ import { expect, test } from "@playwright/test"; - +test.beforeEach(async ({ page }) => { + // await page.waitForTimeout(5000); + // test.setTimeout(120000); +}); test("FloatComponent", async ({ page }) => { - await page.routeFromHAR("harFiles/backend_12112023.har", { - url: "**/api/v1/**", - update: false, - }); - await page.route("**/api/v1/flows/", async (route) => { - const json = { - id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210", - }; - await route.fulfill({ json, status: 201 }); - }); - await page.goto("http://localhost:3000/"); + await page.goto("/"); await page.waitForTimeout(2000); await page.locator('//*[@id="new-project-btn"]').click(); await page.waitForTimeout(2000); + await page.getByTestId("blank-flow").click(); + await page.waitForTimeout(2000); + await page.getByPlaceholder("Search").click(); await page.getByPlaceholder("Search").fill("llamacpp"); await page.waitForTimeout(2000); await page - .locator('//*[@id="llmsLlamaCpp"]') + .locator('//*[@id="model_specsLlamaCpp"]') .dragTo(page.locator('//*[@id="react-flow-id"]')); await page.mouse.up(); await page.mouse.down(); @@ -102,18 +98,6 @@ test("FloatComponent", async ({ page }) => { await page.locator('//*[@id="showmax_tokens"]').isChecked() ).toBeTruthy(); - // showmetadata - await page.locator('//*[@id="showmetadata"]').click(); - expect( - await page.locator('//*[@id="showmetadata"]').isChecked() - ).toBeTruthy(); - - // showmodel_kwargs - await page.locator('//*[@id="showmodel_kwargs"]').click(); - expect( - await page.locator('//*[@id="showmodel_kwargs"]').isChecked() - ).toBeTruthy(); - // showmodel_path await page.locator('//*[@id="showmodel_path"]').click(); expect( @@ -271,16 +255,6 @@ test("FloatComponent", async ({ page }) => { await page.locator('//*[@id="showmax_tokens"]').isChecked() ).toBeFalsy(); - // showmetadata - await page.locator('//*[@id="showmetadata"]').click(); - expect(await page.locator('//*[@id="showmetadata"]').isChecked()).toBeFalsy(); - - // showmodel_kwargs - await page.locator('//*[@id="showmodel_kwargs"]').click(); - expect( - await page.locator('//*[@id="showmodel_kwargs"]').isChecked() - ).toBeFalsy(); - // showmodel_path await page.locator('//*[@id="showmodel_path"]').click(); expect( diff --git a/src/frontend/tests/onlyFront/flowPage.spec.ts b/src/frontend/tests/end-to-end/flowPage.spec.ts similarity index 62% rename from src/frontend/tests/onlyFront/flowPage.spec.ts rename to src/frontend/tests/end-to-end/flowPage.spec.ts index 5c5d1a412..a5e628a53 100644 --- a/src/frontend/tests/onlyFront/flowPage.spec.ts +++ b/src/frontend/tests/end-to-end/flowPage.spec.ts @@ -1,35 +1,32 @@ import { Page, test } from "@playwright/test"; +test.beforeEach(async ({ page }) => { + // await page.waitForTimeout(6000); + // test.setTimeout(120000); +}); test.describe("Flow Page tests", () => { async function goToFlowPage(page: Page) { - await page.goto("http://localhost:3000/"); + await page.goto("/"); await page.getByRole("button", { name: "New Project" }).click(); } test("save", async ({ page }) => { - await page.routeFromHAR("harFiles/backend_12112023.har", { - url: "**/api/v1/**", - update: false, - }); - await page.route("**/api/v1/flows/", async (route) => { - const json = { - id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210", - }; - await route.fulfill({ json, status: 201 }); - }); - await page.goto("http://localhost:3000/"); + await page.goto("/"); await page.waitForTimeout(2000); await page.locator('//*[@id="new-project-btn"]').click(); await page.waitForTimeout(2000); + await page.getByTestId("blank-flow").click(); + await page.waitForTimeout(2000); + await page.getByPlaceholder("Search").click(); await page.getByPlaceholder("Search").fill("custom"); await page.waitForTimeout(2000); await page - .locator('//*[@id="custom_componentsCustomComponent"]') + .locator('//*[@id="helpersCustom Component"]') .dragTo(page.locator('//*[@id="react-flow-id"]')); await page.mouse.up(); await page.mouse.down(); diff --git a/src/frontend/tests/end-to-end/group.spec.ts b/src/frontend/tests/end-to-end/group.spec.ts new file mode 100644 index 000000000..633997915 --- /dev/null +++ b/src/frontend/tests/end-to-end/group.spec.ts @@ -0,0 +1,29 @@ +import { expect, test } from "@playwright/test"; + +test.describe("group node test", () => { + /// + test("group and ungroup updating values", async ({ page }) => { + await page.goto("/"); + await page.locator('//*[@id="new-project-btn"]').click(); + + await page.getByRole("heading", { name: "Data Ingestion" }).click(); + await page.waitForTimeout(2000); + await page.getByLabel("fit view").click(); + await page.keyboard.down("Control"); + await page + .getByTestId("title-OpenAIEmbeddings") + .click({ modifiers: ["Control"] }); + await page.getByTestId("title-URL").click({ modifiers: ["Control"] }); + await page + .getByTestId("title-Recursive Character Text Splitter") + .click({ modifiers: ["Control"] }); + await page.keyboard.up("Control"); + await page.getByRole("button", { name: "Group" }).click(); + await page.getByTestId(/input-collection_name_Chroma-.*/).click(); + await page.getByTestId(/input-collection_name_Chroma-.*/).fill("test"); + await page.getByTestId("title-Group").click(); + await page.keyboard.press("Control+g"); + const value = await page.getByTestId("input-collection_name").inputValue(); + expect(value).toBe("test"); + }); +}); diff --git a/src/frontend/tests/onlyFront/inputComponent.spec.ts b/src/frontend/tests/end-to-end/inputComponent.spec.ts similarity index 62% rename from src/frontend/tests/onlyFront/inputComponent.spec.ts rename to src/frontend/tests/end-to-end/inputComponent.spec.ts index 47f589059..c702da4f5 100644 --- a/src/frontend/tests/onlyFront/inputComponent.spec.ts +++ b/src/frontend/tests/end-to-end/inputComponent.spec.ts @@ -1,22 +1,18 @@ import { expect, test } from "@playwright/test"; - +test.beforeEach(async ({ page }) => { + // await page.waitForTimeout(8000); + // test.setTimeout(120000); +}); test("InputComponent", async ({ page }) => { - await page.routeFromHAR("harFiles/langflow.har", { - url: "**/api/v1/**", - update: false, - }); - await page.route("**/api/v1/flows/", async (route) => { - const json = { - id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210", - }; - await route.fulfill({ json, status: 201 }); - }); - await page.goto("http://localhost:3000/"); + await page.goto("/"); await page.waitForTimeout(2000); await page.locator('//*[@id="new-project-btn"]').click(); await page.waitForTimeout(2000); + await page.getByTestId("blank-flow").click(); + await page.waitForTimeout(2000); + await page.getByPlaceholder("Search").click(); await page.getByPlaceholder("Search").fill("Chroma"); @@ -28,12 +24,12 @@ test("InputComponent", async ({ page }) => { await page.mouse.up(); await page.mouse.down(); - await page.locator("#input-8").click(); + await page.getByTestId("input-collection_name").click(); await page - .locator("#input-8") + .getByTestId("input-collection_name") .fill("collection_name_test_123123123!@#$&*(&%$@"); - let value = await page.locator("#input-8").inputValue(); + let value = await page.getByTestId("input-collection_name").inputValue(); if (value != "collection_name_test_123123123!@#$&*(&%$@") { expect(false).toBeTruthy(); @@ -61,9 +57,9 @@ test("InputComponent", async ({ page }) => { await page.locator('//*[@id="showchroma_server_host"]').isChecked() ).toBeTruthy(); - await page.locator('//*[@id="showchroma_server_http_port"]').click(); + await page.locator('//*[@id="showchroma_server_port"]').click(); expect( - await page.locator('//*[@id="showchroma_server_http_port"]').isChecked() + await page.locator('//*[@id="showchroma_server_port"]').isChecked() ).toBeTruthy(); await page.locator('//*[@id="showchroma_server_ssl_enabled"]').click(); @@ -76,19 +72,11 @@ test("InputComponent", async ({ page }) => { await page.locator('//*[@id="showcollection_name"]').isChecked() ).toBeFalsy(); - await page.locator('//*[@id="showpersist"]').click(); - expect(await page.locator('//*[@id="showpersist"]').isChecked()).toBeFalsy(); - - await page.locator('//*[@id="showpersist_directory"]').click(); + await page.locator('//*[@id="showindex_directory"]').click(); expect( - await page.locator('//*[@id="showpersist_directory"]').isChecked() + await page.locator('//*[@id="showindex_directory"]').isChecked() ).toBeFalsy(); - await page.locator('//*[@id="showsearch_kwargs"]').click(); - expect( - await page.locator('//*[@id="showsearch_kwargs"]').isChecked() - ).toBeTruthy(); - await page.locator('//*[@id="showchroma_server_cors_allow_origins"]').click(); expect( await page @@ -106,9 +94,9 @@ test("InputComponent", async ({ page }) => { await page.locator('//*[@id="showchroma_server_host"]').isChecked() ).toBeFalsy(); - await page.locator('//*[@id="showchroma_server_http_port"]').click(); + await page.locator('//*[@id="showchroma_server_port"]').click(); expect( - await page.locator('//*[@id="showchroma_server_http_port"]').isChecked() + await page.locator('//*[@id="showchroma_server_port"]').isChecked() ).toBeFalsy(); await page.locator('//*[@id="showchroma_server_ssl_enabled"]').click(); @@ -116,33 +104,27 @@ test("InputComponent", async ({ page }) => { await page.locator('//*[@id="showchroma_server_ssl_enabled"]').isChecked() ).toBeFalsy(); - await page.locator('//*[@id="showpersist"]').click(); - expect(await page.locator('//*[@id="showpersist"]').isChecked()).toBeTruthy(); - - await page.locator('//*[@id="showpersist_directory"]').click(); + await page.locator('//*[@id="showindex_directory"]').click(); expect( - await page.locator('//*[@id="showpersist_directory"]').isChecked() + await page.locator('//*[@id="showindex_directory"]').isChecked() ).toBeTruthy(); - await page.locator('//*[@id="showsearch_kwargs"]').click(); - expect( - await page.locator('//*[@id="showsearch_kwargs"]').isChecked() - ).toBeFalsy(); - - let valueEditNode = await page.locator('//*[@id="input-5"]').inputValue(); + let valueEditNode = await page + .getByTestId("input-collection_name-edit") + .inputValue(); if (valueEditNode != "collection_name_test_123123123!@#$&*(&%$@") { expect(false).toBeTruthy(); } - await page.locator('//*[@id="input-5"]').click(); + await page.getByTestId("input-collection_name-edit").click(); await page - .locator('//*[@id="input-5"]') - .fill("NEW_collection_name_test_123123123!@#$&*(&%$@"); + .getByTestId("input-collection_name-edit") + .fill("NEW_collection_name_test_123123123!@#$&*(&%$@ÇÇÇÀõe"); await page.locator('//*[@id="saveChangesBtn"]').click(); - const plusButtonLocator = page.locator("#input-8"); + const plusButtonLocator = page.getByTestId("input-collection_name"); const elementCount = await plusButtonLocator.count(); if (elementCount === 0) { expect(true).toBeTruthy(); @@ -159,9 +141,9 @@ test("InputComponent", async ({ page }) => { await page.locator('//*[@id="saveChangesBtn"]').click(); - let value = await page.locator("#input-8").inputValue(); + let value = await page.getByTestId("input-collection_name").inputValue(); - if (value != "NEW_collection_name_test_123123123!@#$&*(&%$@") { + if (value != "NEW_collection_name_test_123123123!@#$&*(&%$@ÇÇÇÀõe") { expect(false).toBeTruthy(); } } diff --git a/src/frontend/tests/end-to-end/intComponent.spec.ts b/src/frontend/tests/end-to-end/intComponent.spec.ts new file mode 100644 index 000000000..a802e898a --- /dev/null +++ b/src/frontend/tests/end-to-end/intComponent.spec.ts @@ -0,0 +1,203 @@ +import { expect, test } from "@playwright/test"; +test.beforeEach(async ({ page }) => { + // await page.waitForTimeout(9000); + // test.setTimeout(120000); +}); +test("IntComponent", async ({ page }) => { + await page.goto("/"); + await page.waitForTimeout(2000); + + await page.locator('//*[@id="new-project-btn"]').click(); + await page.waitForTimeout(2000); + + await page.getByTestId("blank-flow").click(); + await page.waitForTimeout(2000); + + await page.getByPlaceholder("Search").click(); + await page.getByPlaceholder("Search").fill("openai"); + + await page.waitForTimeout(2000); + + await page + .getByTestId("modelsOpenAI") + .first() + .dragTo(page.locator('//*[@id="react-flow-id"]')); + await page.mouse.up(); + await page.mouse.down(); + + await page.getByTestId("int-input-max_tokens").click(); + await page + .getByTestId("int-input-max_tokens") + .fill("123456789123456789123456789"); + + let value = await page.getByTestId("int-input-max_tokens").inputValue(); + + if (value != "123456789123456789123456789") { + expect(false).toBeTruthy(); + } + + await page.getByTestId("int-input-max_tokens").click(); + await page.getByTestId("int-input-max_tokens").fill("0"); + + value = await page.getByTestId("int-input-max_tokens").inputValue(); + + if (value != "0") { + expect(false).toBeTruthy(); + } + + await page.getByTestId("more-options-modal").click(); + await page.getByTestId("edit-button-modal").click(); + + value = await page.getByTestId("edit-int-input-max_tokens").inputValue(); + + if (value != "0") { + expect(false).toBeTruthy(); + } + + await page.getByTestId("edit-int-input-max_tokens").click(); + await page + .getByTestId("edit-int-input-max_tokens") + .fill("123456789123456789123456789"); + + await page.locator('//*[@id="showinput_value"]').click(); + expect( + await page.locator('//*[@id="showinput_value"]').isChecked() + ).toBeFalsy(); + + await page.locator('//*[@id="showmodel_kwargs"]').click(); + expect( + await page.locator('//*[@id="showmodel_kwargs"]').isChecked() + ).toBeTruthy(); + + await page.locator('//*[@id="showmodel_name"]').click(); + expect( + await page.locator('//*[@id="showmodel_name"]').isChecked() + ).toBeFalsy(); + + await page.locator('//*[@id="showopenai_api_base"]').click(); + expect( + await page.locator('//*[@id="showopenai_api_base"]').isChecked() + ).toBeFalsy(); + + await page.locator('//*[@id="showopenai_api_key"]').click(); + expect( + await page.locator('//*[@id="showopenai_api_key"]').isChecked() + ).toBeFalsy(); + + await page.locator('//*[@id="showstream"]').click(); + expect(await page.locator('//*[@id="showstream"]').isChecked()).toBeFalsy(); + + await page.locator('//*[@id="showtemperature"]').click(); + expect( + await page.locator('//*[@id="showtemperature"]').isChecked() + ).toBeFalsy(); + + await page.locator('//*[@id="showinput_value"]').click(); + expect( + await page.locator('//*[@id="showinput_value"]').isChecked() + ).toBeTruthy(); + + await page.locator('//*[@id="showmodel_kwargs"]').click(); + expect( + await page.locator('//*[@id="showmodel_kwargs"]').isChecked() + ).toBeFalsy(); + + await page.locator('//*[@id="showmodel_name"]').click(); + expect( + await page.locator('//*[@id="showmodel_name"]').isChecked() + ).toBeTruthy(); + + await page.locator('//*[@id="showopenai_api_base"]').click(); + expect( + await page.locator('//*[@id="showopenai_api_base"]').isChecked() + ).toBeTruthy(); + + await page.locator('//*[@id="showopenai_api_key"]').click(); + expect( + await page.locator('//*[@id="showopenai_api_key"]').isChecked() + ).toBeTruthy(); + + await page.locator('//*[@id="showstream"]').click(); + expect(await page.locator('//*[@id="showstream"]').isChecked()).toBeTruthy(); + + await page.locator('//*[@id="showtemperature"]').click(); + expect( + await page.locator('//*[@id="showtemperature"]').isChecked() + ).toBeTruthy(); + + await page.locator('//*[@id="showinput_value"]').click(); + expect( + await page.locator('//*[@id="showinput_value"]').isChecked() + ).toBeFalsy(); + + await page.locator('//*[@id="showmodel_kwargs"]').click(); + expect( + await page.locator('//*[@id="showmodel_kwargs"]').isChecked() + ).toBeTruthy(); + + await page.locator('//*[@id="showmodel_name"]').click(); + expect( + await page.locator('//*[@id="showmodel_name"]').isChecked() + ).toBeFalsy(); + + await page.locator('//*[@id="showopenai_api_base"]').click(); + expect( + await page.locator('//*[@id="showopenai_api_base"]').isChecked() + ).toBeFalsy(); + + await page.locator('//*[@id="showopenai_api_key"]').click(); + expect( + await page.locator('//*[@id="showopenai_api_key"]').isChecked() + ).toBeFalsy(); + + await page.locator('//*[@id="showstream"]').click(); + expect(await page.locator('//*[@id="showstream"]').isChecked()).toBeFalsy(); + + await page.locator('//*[@id="showtemperature"]').click(); + expect( + await page.locator('//*[@id="showtemperature"]').isChecked() + ).toBeFalsy(); + + await page.locator('//*[@id="saveChangesBtn"]').click(); + + const plusButtonLocator = page.getByTestId("int-input-max_tokens"); + const elementCount = await plusButtonLocator.count(); + if (elementCount === 0) { + expect(true).toBeTruthy(); + + await page.getByTestId("more-options-modal").click(); + await page.getByTestId("edit-button-modal").click(); + + await page.locator('//*[@id="showtimeout"]').click(); + expect( + await page.locator('//*[@id="showtimeout"]').isChecked() + ).toBeTruthy(); + + const valueEditNode = await page + .getByTestId("edit-int-input-max_tokens") + .inputValue(); + + if (valueEditNode != "123456789123456789123456789") { + expect(false).toBeTruthy(); + } + + await page.locator('//*[@id="saveChangesBtn"]').click(); + await page.getByTestId("int-input-max_tokens").click(); + await page.getByTestId("int-input-max_tokens").fill("3"); + + let value = await page.getByTestId("int-input-max_tokens").inputValue(); + + if (value != "3") { + expect(false).toBeTruthy(); + } + + await page.getByTestId("int-input-max_tokens").click(); + await page.getByTestId("int-input-max_tokens").fill("-3"); + + value = await page.getByTestId("int-input-max_tokens").inputValue(); + + if (value != "0") { + expect(false).toBeTruthy(); + } + } +}); diff --git a/src/frontend/tests/onlyFront/keyPairListComponent.spec.ts b/src/frontend/tests/end-to-end/keyPairListComponent.spec.ts similarity index 55% rename from src/frontend/tests/onlyFront/keyPairListComponent.spec.ts rename to src/frontend/tests/end-to-end/keyPairListComponent.spec.ts index 96530698e..1ef6eeb2f 100644 --- a/src/frontend/tests/onlyFront/keyPairListComponent.spec.ts +++ b/src/frontend/tests/end-to-end/keyPairListComponent.spec.ts @@ -1,22 +1,18 @@ import { expect, test } from "@playwright/test"; - +test.beforeEach(async ({ page }) => { + // await page.waitForTimeout(20000); + // test.setTimeout(120000); +}); test("KeypairListComponent", async ({ page }) => { - await page.routeFromHAR("harFiles/backend_12112023.har", { - url: "**/api/v1/**", - update: false, - }); - await page.route("**/api/v1/flows/", async (route) => { - const json = { - id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210", - }; - await route.fulfill({ json, status: 201 }); - }); - await page.goto("http://localhost:3000/"); + await page.goto("/"); await page.waitForTimeout(2000); await page.locator('//*[@id="new-project-btn"]').click(); await page.waitForTimeout(2000); + await page.getByTestId("blank-flow").click(); + await page.waitForTimeout(2000); + await page.getByPlaceholder("Search").click(); await page.getByPlaceholder("Search").fill("csv"); @@ -51,32 +47,14 @@ test("KeypairListComponent", async ({ page }) => { } await page.getByTestId("div-generic-node").click(); - await page.locator('//*[@id="keypair1"]').click(); - await page.locator('//*[@id="keypair1"]').fill("testtesttesttest1"); + await page.locator('//*[@id="keypair0"]').click(); + await page.locator('//*[@id="keypair0"]').fill("testtesttesttest1"); await page.getByTestId("div-generic-node").click(); - await page.locator('//*[@id="keypair101"]').click(); - await page.locator('//*[@id="keypair101"]').fill("testtesttesttesttesttest1"); - await page.getByTestId("div-generic-node").click(); - - await page.locator('//*[@id="plusbtn1"]').click(); - await page.getByTestId("div-generic-node").click(); - - await page.locator('//*[@id="keypair2"]').click(); - await page.locator('//*[@id="keypair2"]').fill("testtesttesttest2"); - await page.getByTestId("div-generic-node").click(); - - await page.locator('//*[@id="keypair102"]').click(); - await page.locator('//*[@id="keypair102"]').fill("testtesttesttesttesttest2"); - await page.getByTestId("div-generic-node").click(); - - await page.locator('//*[@id="minusbtn1"]').click(); - await page.getByTestId("div-generic-node").click(); - - const keyPairVerification = page.locator('//*[@id="keypair102"]'); + const keyPairVerification = page.locator('//*[@id="keypair100"]'); const elementKeyCount = await keyPairVerification.count(); - if (elementKeyCount === 0) { + if (elementKeyCount === 1) { expect(true).toBeTruthy(); } else { expect(false).toBeTruthy(); @@ -113,53 +91,22 @@ test("KeypairListComponent", async ({ page }) => { await page.locator('//*[@id="editNodekeypair0"]').click(); await page.locator('//*[@id="editNodekeypair0"]').fill("testtesttesttest"); - await page.locator('//*[@id="editNodekeypair100"]').click(); - await page - .locator('//*[@id="editNodekeypair100"]') - .fill("test test test test test test"); - const plusButtonLocator = page.locator('//*[@id="plusbtn0"]'); - const elementCount = await plusButtonLocator.count(); - if (elementCount > 0) { - await plusButtonLocator.click(); - } - - await page.locator('//*[@id="editNodekeypair1"]').click(); - await page.locator('//*[@id="editNodekeypair1"]').fill("testtesttesttest1"); - await page.locator('//*[@id="editNodekeypair101"]').first().click(); - await page - .locator('//*[@id="editNodekeypair101"]') - .fill("testtesttesttesttesttest1"); - await page.locator('//*[@id="editNodeplusbtn1"]').click(); - - await page.locator('//*[@id="editNodekeypair2"]').click(); - await page.locator('//*[@id="editNodekeypair2"]').fill("testtesttesttest2"); - await page.locator('//*[@id="editNodekeypair102"]').click(); - await page - .locator('//*[@id="editNodekeypair102"]') - .fill("testtesttesttesttesttest2"); - - await page.locator('//*[@id="editNodeminusbtn1"]').click(); - - const keyPairVerification = page.locator('//*[@id="editNodekeypair102"]'); + const keyPairVerification = page.locator('//*[@id="editNodekeypair0"]'); const elementKeyCount = await keyPairVerification.count(); - if (elementKeyCount === 0) { + if (elementKeyCount === 1) { await page.locator('//*[@id="saveChangesBtn"]').click(); await page.getByTestId("div-generic-node").click(); const key1 = await page.locator('//*[@id="keypair0"]').inputValue(); const value1 = await page.locator('//*[@id="keypair100"]').inputValue(); - const key2 = await page.locator('//*[@id="keypair1"]').inputValue(); - const value2 = await page.locator('//*[@id="keypair101"]').inputValue(); await page.getByTestId("div-generic-node").click(); if ( key1 === "testtesttesttest" && - value1 === "test test test test test test" && - key2 === "testtesttesttest2" && - value2 === "testtesttesttesttesttest2" + value1 === "test test test test test test" ) { expect(true).toBeTruthy(); } else { diff --git a/src/frontend/tests/end-to-end/langflowShortcuts.spec.ts b/src/frontend/tests/end-to-end/langflowShortcuts.spec.ts new file mode 100644 index 000000000..157fc4459 --- /dev/null +++ b/src/frontend/tests/end-to-end/langflowShortcuts.spec.ts @@ -0,0 +1,90 @@ +import { expect, test } from "@playwright/test"; +import uaParser from "ua-parser-js"; +test.beforeEach(async ({ page }) => { + // await page.waitForTimeout(11000); + // test.setTimeout(120000); +}); +test("LangflowShortcuts", async ({ page }) => { + const getUA = await page.evaluate(() => navigator.userAgent); + const userAgentInfo = uaParser(getUA); + let control = "Control"; + + if (userAgentInfo.os.name.includes("Mac")) { + control = "Meta"; + } + + await page.goto("/"); + await page.waitForTimeout(1000); + + await page.locator('//*[@id="new-project-btn"]').click(); + await page.waitForTimeout(1000); + + await page.getByTestId("blank-flow").click(); + await page.waitForTimeout(1000); + + await page.getByPlaceholder("Search").click(); + await page.getByPlaceholder("Search").fill("llamacpp"); + + await page.waitForTimeout(1000); + + await page + .locator('//*[@id="model_specsLlamaCpp"]') + .dragTo(page.locator('//*[@id="react-flow-id"]')); + await page.mouse.up(); + await page.mouse.down(); + + await page.getByTestId("title-LlamaCpp").click(); + await page.keyboard.press(`${control}+e`); + await page.locator('//*[@id="saveChangesBtn"]').click(); + + await page.getByTestId("title-LlamaCpp").click(); + await page.keyboard.press(`${control}+d`); + + let numberOfNodes = await page.getByTestId("title-LlamaCpp").count(); + if (numberOfNodes != 2) { + expect(false).toBeTruthy(); + } + + await page + .locator( + '//*[@id="react-flow-id"]/div[1]/div[1]/div[1]/div/div[2]/div[2]/div/div[1]/div/div[1]/div/div/div[1]' + ) + .click(); + await page.keyboard.press("Backspace"); + + numberOfNodes = await page.getByTestId("title-LlamaCpp").count(); + if (numberOfNodes != 1) { + expect(false).toBeTruthy(); + } + + await page.getByTestId("title-LlamaCpp").click(); + await page.keyboard.press(`${control}+c`); + + await page.getByTestId("title-LlamaCpp").click(); + await page.keyboard.press(`${control}+v`); + + numberOfNodes = await page.getByTestId("title-LlamaCpp").count(); + if (numberOfNodes != 2) { + expect(false).toBeTruthy(); + } + + await page + .locator( + '//*[@id="react-flow-id"]/div[1]/div[1]/div[1]/div/div[2]/div[2]/div/div[1]/div/div[1]/div/div/div[1]' + ) + .click(); + await page.keyboard.press("Backspace"); + + await page.getByTestId("title-LlamaCpp").click(); + await page.keyboard.press(`${control}+x`); + + numberOfNodes = await page.getByTestId("title-LlamaCpp").count(); + if (numberOfNodes != 0) { + expect(false).toBeTruthy(); + } + await page.keyboard.press(`${control}+v`); + numberOfNodes = await page.getByTestId("title-LlamaCpp").count(); + if (numberOfNodes != 1) { + expect(false).toBeTruthy(); + } +}); diff --git a/src/frontend/tests/onlyFront/nestedComponent.spec.ts b/src/frontend/tests/end-to-end/nestedComponent.spec.ts similarity index 80% rename from src/frontend/tests/onlyFront/nestedComponent.spec.ts rename to src/frontend/tests/end-to-end/nestedComponent.spec.ts index 0a90533f4..053c72db2 100644 --- a/src/frontend/tests/onlyFront/nestedComponent.spec.ts +++ b/src/frontend/tests/end-to-end/nestedComponent.spec.ts @@ -1,22 +1,18 @@ import { expect, test } from "@playwright/test"; - +test.beforeEach(async ({ page }) => { + // await page.waitForTimeout(12000); + // test.setTimeout(120000); +}); test("NestedComponent", async ({ page }) => { - await page.routeFromHAR("harFiles/backend_12112023.har", { - url: "**/api/v1/**", - update: false, - }); - await page.route("**/api/v1/flows/", async (route) => { - const json = { - id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210", - }; - await route.fulfill({ json, status: 201 }); - }); - await page.goto("http://localhost:3000/"); + await page.goto("/"); await page.waitForTimeout(2000); await page.locator('//*[@id="new-project-btn"]').click(); await page.waitForTimeout(2000); + await page.getByTestId("blank-flow").click(); + await page.waitForTimeout(2000); + await page.getByPlaceholder("Search").click(); await page.getByPlaceholder("Search").fill("pinecone"); @@ -31,75 +27,17 @@ test("NestedComponent", async ({ page }) => { await page.getByTestId("more-options-modal").click(); await page.getByTestId("edit-button-modal").click(); - // showindex_name - await page.locator('//*[@id="showindex_name"]').click(); + //showpool_threads + await page.locator('//*[@id="showpool_threads"]').click(); expect( - await page.locator('//*[@id="showindex_name"]').isChecked() - ).toBeFalsy(); - - // shownamespace - await page.locator('//*[@id="shownamespace"]').click(); - - expect( - await page.locator('//*[@id="shownamespace"]').isChecked() - ).toBeFalsy(); - - // showpinecone_api_key - await page.locator('//*[@id="showpinecone_api_key"]').click(); - - expect( - await page.locator('//*[@id="showpinecone_api_key"]').isChecked() + await page.locator('//*[@id="showpool_threads"]').isChecked() ).toBeTruthy(); - // showpinecone_env - await page.locator('//*[@id="showpinecone_env"]').click(); + //showtext_key + await page.locator('//*[@id="showtext_key"]').click(); - expect( - await page.locator('//*[@id="showpinecone_env"]').isChecked() - ).toBeTruthy(); - - // showsearch_kwargs - await page.locator('//*[@id="showsearch_kwargs"]').click(); - - expect( - await page.locator('//*[@id="showsearch_kwargs"]').isChecked() - ).toBeTruthy(); - - // showindex_name - await page.locator('//*[@id="showindex_name"]').click(); - - expect( - await page.locator('//*[@id="showindex_name"]').isChecked() - ).toBeTruthy(); - - // shownamespace - await page.locator('//*[@id="shownamespace"]').click(); - - expect( - await page.locator('//*[@id="shownamespace"]').isChecked() - ).toBeTruthy(); - - // showpinecone_api_key - await page.locator('//*[@id="showpinecone_api_key"]').click(); - - expect( - await page.locator('//*[@id="showpinecone_api_key"]').isChecked() - ).toBeFalsy(); - - // showpinecone_env - await page.locator('//*[@id="showpinecone_env"]').click(); - - expect( - await page.locator('//*[@id="showpinecone_env"]').isChecked() - ).toBeFalsy(); - - // showsearch_kwargs - await page.locator('//*[@id="showsearch_kwargs"]').click(); - - expect( - await page.locator('//*[@id="showsearch_kwargs"]').isChecked() - ).toBeFalsy(); + expect(await page.locator('//*[@id="showtext_key"]').isChecked()).toBeFalsy(); // showindex_name await page.locator('//*[@id="showindex_name"]').click(); @@ -120,21 +58,14 @@ test("NestedComponent", async ({ page }) => { expect( await page.locator('//*[@id="showpinecone_api_key"]').isChecked() - ).toBeTruthy(); + ).toBeFalsy(); // showpinecone_env await page.locator('//*[@id="showpinecone_env"]').click(); expect( await page.locator('//*[@id="showpinecone_env"]').isChecked() - ).toBeTruthy(); - - // showsearch_kwargs - await page.locator('//*[@id="showsearch_kwargs"]').click(); - - expect( - await page.locator('//*[@id="showsearch_kwargs"]').isChecked() - ).toBeTruthy(); + ).toBeFalsy(); // showindex_name await page.locator('//*[@id="showindex_name"]').click(); @@ -155,21 +86,14 @@ test("NestedComponent", async ({ page }) => { expect( await page.locator('//*[@id="showpinecone_api_key"]').isChecked() - ).toBeFalsy(); + ).toBeTruthy(); // showpinecone_env await page.locator('//*[@id="showpinecone_env"]').click(); expect( await page.locator('//*[@id="showpinecone_env"]').isChecked() - ).toBeFalsy(); - - // showsearch_kwargs - await page.locator('//*[@id="showsearch_kwargs"]').click(); - - expect( - await page.locator('//*[@id="showsearch_kwargs"]').isChecked() - ).toBeFalsy(); + ).toBeTruthy(); // showindex_name await page.locator('//*[@id="showindex_name"]').click(); @@ -190,21 +114,14 @@ test("NestedComponent", async ({ page }) => { expect( await page.locator('//*[@id="showpinecone_api_key"]').isChecked() - ).toBeTruthy(); + ).toBeFalsy(); // showpinecone_env await page.locator('//*[@id="showpinecone_env"]').click(); expect( await page.locator('//*[@id="showpinecone_env"]').isChecked() - ).toBeTruthy(); - - // showsearch_kwargs - await page.locator('//*[@id="showsearch_kwargs"]').click(); - - expect( - await page.locator('//*[@id="showsearch_kwargs"]').isChecked() - ).toBeTruthy(); + ).toBeFalsy(); // showindex_name await page.locator('//*[@id="showindex_name"]').click(); @@ -223,6 +140,34 @@ test("NestedComponent", async ({ page }) => { // showpinecone_api_key await page.locator('//*[@id="showpinecone_api_key"]').click(); + expect( + await page.locator('//*[@id="showpinecone_api_key"]').isChecked() + ).toBeTruthy(); + + // showpinecone_env + await page.locator('//*[@id="showpinecone_env"]').click(); + + expect( + await page.locator('//*[@id="showpinecone_env"]').isChecked() + ).toBeTruthy(); + + // showindex_name + await page.locator('//*[@id="showindex_name"]').click(); + + expect( + await page.locator('//*[@id="showindex_name"]').isChecked() + ).toBeFalsy(); + + // shownamespace + await page.locator('//*[@id="shownamespace"]').click(); + + expect( + await page.locator('//*[@id="shownamespace"]').isChecked() + ).toBeFalsy(); + + // showpinecone_api_key + await page.locator('//*[@id="showpinecone_api_key"]').click(); + expect( await page.locator('//*[@id="showpinecone_api_key"]').isChecked() ).toBeFalsy(); @@ -234,7 +179,47 @@ test("NestedComponent", async ({ page }) => { await page.locator('//*[@id="showpinecone_env"]').isChecked() ).toBeFalsy(); + // showindex_name + await page.locator('//*[@id="showindex_name"]').click(); + + expect( + await page.locator('//*[@id="showindex_name"]').isChecked() + ).toBeTruthy(); + + // shownamespace + await page.locator('//*[@id="shownamespace"]').click(); + + expect( + await page.locator('//*[@id="shownamespace"]').isChecked() + ).toBeTruthy(); + + // showpinecone_api_key + await page.locator('//*[@id="showpinecone_api_key"]').click(); + + expect( + await page.locator('//*[@id="showpinecone_api_key"]').isChecked() + ).toBeTruthy(); + + // showpinecone_env + await page.locator('//*[@id="showpinecone_env"]').click(); + + expect( + await page.locator('//*[@id="showpinecone_env"]').isChecked() + ).toBeTruthy(); + + //showpool_threads + await page.locator('//*[@id="showpool_threads"]').click(); + + expect( + await page.locator('//*[@id="showpool_threads"]').isChecked() + ).toBeFalsy(); + + //showtext_key + await page.locator('//*[@id="showtext_key"]').click(); + + expect( + await page.locator('//*[@id="showtext_key"]').isChecked() + ).toBeTruthy(); + await page.locator('//*[@id="saveChangesBtn"]').click(); - - await page.getByTestId("div-dict-input").click(); }); diff --git a/src/frontend/tests/end-to-end/promptModalComponent.spec.ts b/src/frontend/tests/end-to-end/promptModalComponent.spec.ts index 690ec2d05..f0d118094 100644 --- a/src/frontend/tests/end-to-end/promptModalComponent.spec.ts +++ b/src/frontend/tests/end-to-end/promptModalComponent.spec.ts @@ -1,32 +1,40 @@ import { expect, test } from "@playwright/test"; - +test.beforeEach(async ({ page }) => { + // await page.waitForTimeout(13000); + // test.setTimeout(120000); +}); test("PromptTemplateComponent", async ({ page }) => { - await page.goto("http://localhost:3000/"); + await page.goto("/"); await page.waitForTimeout(2000); await page.locator('//*[@id="new-project-btn"]').click(); await page.waitForTimeout(2000); + await page.getByTestId("blank-flow").click(); + await page.waitForTimeout(2000); + await page.getByPlaceholder("Search").click(); - await page.getByPlaceholder("Search").fill("promptTemplate"); + await page.getByPlaceholder("Search").fill("prompt"); await page.waitForTimeout(2000); await page - .locator('//*[@id="promptsPromptTemplate"]') + .locator('//*[@id="inputsPrompt"]') .dragTo(page.locator('//*[@id="react-flow-id"]')); await page.mouse.up(); await page.mouse.down(); - await page.getByTestId("prompt-input-0").click(); + await page.getByTestId("prompt-input-template").click(); // await page.getByTestId("edit-prompt-sanitized").click(); // await page.getByTestId("modal-title").click(); await page - .getByTestId("modal-prompt-input-0") + .getByTestId("modal-prompt-input-template") .fill("{prompt} example {prompt1}"); - let value = await page.getByTestId("modal-prompt-input-0").inputValue(); + let value = await page + .getByTestId("modal-prompt-input-template") + .inputValue(); if (value != "{prompt} example {prompt1}") { expect(false).toBeTruthy(); @@ -45,35 +53,38 @@ test("PromptTemplateComponent", async ({ page }) => { await page.getByTestId("genericModalBtnSave").click(); await page.getByTestId("div-textarea-prompt").click(); - await page.getByTestId("text-area-modal").fill("prompt_value_!@#!@#"); + await page.getByTestId("textarea-prompt").fill("prompt_value_!@#!@#"); - value = await page.getByTestId("text-area-modal").inputValue(); + value = await page.getByTestId("textarea-prompt").inputValue(); if (value != "prompt_value_!@#!@#") { expect(false).toBeTruthy(); } - await page.getByTestId("genericModalBtnSave").click(); + await page.getByTestId("save-button-modal").click(); + + const replace = await page.getByTestId("replace-button"); + if (replace) { + await page.getByTestId("replace-button").click(); + } await page.getByTestId("div-textarea-prompt1").click(); await page - .getByTestId("text-area-modal") + .getByTestId("textarea-prompt1") .fill("prompt_name_test_123123!@#!@#"); - value = await page.getByTestId("text-area-modal").inputValue(); + value = await page.getByTestId("textarea-prompt1").inputValue(); if (value != "prompt_name_test_123123!@#!@#") { expect(false).toBeTruthy(); } - value = await page.getByTestId("text-area-modal").inputValue(); + value = await page.getByTestId("textarea-prompt1").inputValue(); if (value != "prompt_name_test_123123!@#!@#") { expect(false).toBeTruthy(); } - await page.getByTestId("genericModalBtnSave").click(); - await page.getByTestId("more-options-modal").click(); await page.getByTestId("edit-button-modal").click(); diff --git a/src/frontend/tests/end-to-end/python_api_generation.spec.ts b/src/frontend/tests/end-to-end/python_api_generation.spec.ts new file mode 100644 index 000000000..2d7a6af0d --- /dev/null +++ b/src/frontend/tests/end-to-end/python_api_generation.spec.ts @@ -0,0 +1,17 @@ +import { expect, test } from "@playwright/test"; + +test("python_api_generation", async ({ page, context }) => { + await page.goto("/"); + await page.locator('//*[@id="new-project-btn"]').click(); + await context.grantPermissions(["clipboard-read", "clipboard-write"]); + await page.getByRole("heading", { name: "Data Ingestion" }).click(); + await page.waitForTimeout(2000); + await page.getByText("API", { exact: true }).click(); + await page.getByRole("tab", { name: "Python API" }).click(); + await page.getByRole("button", { name: "Copy Code" }).click(); + const handle = await page.evaluateHandle(() => + navigator.clipboard.readText() + ); + const clipboardContent = await handle.jsonValue(); + expect(clipboardContent.length).toBeGreaterThan(0); +}); diff --git a/src/frontend/tests/onlyFront/saveComponents.spec.ts b/src/frontend/tests/end-to-end/saveComponents.spec.ts similarity index 73% rename from src/frontend/tests/onlyFront/saveComponents.spec.ts rename to src/frontend/tests/end-to-end/saveComponents.spec.ts index 10a0c9c77..772894b5a 100644 --- a/src/frontend/tests/onlyFront/saveComponents.spec.ts +++ b/src/frontend/tests/end-to-end/saveComponents.spec.ts @@ -1,6 +1,9 @@ import { Page, expect, test } from "@playwright/test"; import { readFileSync } from "fs"; - +test.beforeEach(async ({ page }) => { + // await page.waitForTimeout(14000); + // test.setTimeout(120000); +}); test.describe("save component tests", () => { async function saveComponent(page: Page, pattern: RegExp, n: number) { for (let i = 0; i < n; i++) { @@ -11,22 +14,15 @@ test.describe("save component tests", () => { /// test("save group component tests", async ({ page }) => { - //make front work withoput backend - await page.routeFromHAR("harFiles/langflow.har", { - url: "**/api/v1/**", - update: false, - }); - await page.route("**/api/v1/flows/", async (route) => { - const json = { - id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210", - }; - await route.fulfill({ json, status: 201 }); - }); - await page.goto("http:localhost:3000/"); - await page.locator("span").filter({ hasText: "My Collection" }).isVisible(); + await page.goto("/"); + await page.locator('//*[@id="new-project-btn"]').click(); + + await page.getByTestId("blank-flow").click(); + await page.waitForTimeout(2000); + // Read your file into a buffer. const jsonContent = readFileSync( - "tests/onlyFront/assets/collection.json", + "tests/end-to-end/assets/flow_group_test.json", "utf-8" ); @@ -34,32 +30,32 @@ test.describe("save component tests", () => { const dataTransfer = await page.evaluateHandle((data) => { const dt = new DataTransfer(); // Convert the buffer to a hex array - const file = new File([data], "flowtest.json", { + const file = new File([data], "flow_group_test.json", { type: "application/json", }); dt.items.add(file); return dt; }, jsonContent); + page.waitForTimeout(2000); + // Now dispatch await page.dispatchEvent( - '//*[@id="root"]/div/div[1]/div[2]/div[3]/div/div', + "//*[@id='react-flow-id']/div[1]/div[1]/div", "drop", { dataTransfer, } ); - await page - .getByTestId("edit-flow-button-e9ac1bdc-429b-475d-ac03-d26f9a2a3210-0") - .click(); - await page.waitForTimeout(2000); - const genericNoda = page.getByTestId("div-generic-node"); const elementCount = await genericNoda.count(); if (elementCount > 0) { expect(true).toBeTruthy(); } + await page + .locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[3]') + .click(); await page.getByTestId("title-PythonFunctionTool").click({ modifiers: ["Control"], @@ -68,7 +64,7 @@ test.describe("save component tests", () => { modifiers: ["Control"], }); - await page.getByTestId("title-AgentInitializer").click({ + await page.getByTestId("title-Agent Initializer").click({ modifiers: ["Control"], }); @@ -87,9 +83,13 @@ test.describe("save component tests", () => { } await page.getByTestId("title-Group").click(); - await page.getByTestId("more-options-modal").click(); - await page.getByTestId("save-button-modal").click(); - await page.getByTestId("delete-button-modal").click(); + await page.getByTestId("icon-SaveAll").click(); + + const replaceButton = page.getByTestId("replace-button"); + + if (replaceButton) { + await replaceButton.click(); + } await page.getByPlaceholder("Search").click(); await page.getByPlaceholder("Search").fill("group"); diff --git a/src/frontend/tests/onlyFront/toggleComponent.spec.ts b/src/frontend/tests/end-to-end/toggleComponent.spec.ts similarity index 67% rename from src/frontend/tests/onlyFront/toggleComponent.spec.ts rename to src/frontend/tests/end-to-end/toggleComponent.spec.ts index cdf360c57..cb29b6627 100644 --- a/src/frontend/tests/onlyFront/toggleComponent.spec.ts +++ b/src/frontend/tests/end-to-end/toggleComponent.spec.ts @@ -1,22 +1,18 @@ import { expect, test } from "@playwright/test"; - +test.beforeEach(async ({ page }) => { + // await page.waitForTimeout(15000); + // test.setTimeout(120000); +}); test("ToggleComponent", async ({ page }) => { - await page.routeFromHAR("harFiles/langflow.har", { - url: "**/api/v1/**", - update: false, - }); - await page.route("**/api/v1/flows/", async (route) => { - const json = { - id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210", - }; - await route.fulfill({ json, status: 201 }); - }); - await page.goto("http://localhost:3000/"); + await page.goto("/"); await page.waitForTimeout(2000); await page.locator('//*[@id="new-project-btn"]').click(); await page.waitForTimeout(2000); + await page.getByTestId("blank-flow").click(); + await page.waitForTimeout(2000); + await page.getByPlaceholder("Search").click(); await page.getByPlaceholder("Search").fill("directoryLoader"); @@ -38,29 +34,27 @@ test("ToggleComponent", async ({ page }) => { await page.locator('//*[@id="saveChangesBtn"]').click(); - await page.locator('//*[@id="toggle-1"]').click(); - expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeFalsy(); + await page.getByTestId("toggle-load_hidden").click(); + expect(await page.getByTestId("toggle-load_hidden").isChecked()).toBeFalsy(); - await page.locator('//*[@id="toggle-1"]').click(); - expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeTruthy(); + await page.getByTestId("toggle-load_hidden").click(); + expect(await page.getByTestId("toggle-load_hidden").isChecked()).toBeTruthy(); - await page.locator('//*[@id="toggle-1"]').click(); - expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeFalsy(); + await page.getByTestId("toggle-load_hidden").click(); + expect(await page.getByTestId("toggle-load_hidden").isChecked()).toBeFalsy(); - await page.locator('//*[@id="toggle-1"]').click(); - expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeTruthy(); + await page.getByTestId("toggle-load_hidden").click(); + expect(await page.getByTestId("toggle-load_hidden").isChecked()).toBeTruthy(); - await page.locator('//*[@id="toggle-1"]').click(); - expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeFalsy(); + await page.getByTestId("toggle-load_hidden").click(); + expect(await page.getByTestId("toggle-load_hidden").isChecked()).toBeFalsy(); await page.getByTestId("div-generic-node").click(); await page.getByTestId("more-options-modal").click(); await page.getByTestId("edit-button-modal").click(); - expect( - await page.locator('//*[@id="toggle-edit-1"]').isChecked() - ).toBeFalsy(); + expect(await page.getByTestId("toggle-load_hidden").isChecked()).toBeFalsy(); await page.locator('//*[@id="showglob"]').click(); expect(await page.locator('//*[@id="showglob"]').isChecked()).toBeFalsy(); @@ -129,7 +123,7 @@ test("ToggleComponent", async ({ page }) => { await page.locator('//*[@id="saveChangesBtn"]').click(); - const plusButtonLocator = page.locator('//*[@id="toggle-1"]'); + const plusButtonLocator = page.getByTestId("toggle-load_hidden"); const elementCount = await plusButtonLocator.count(); if (elementCount === 0) { expect(true).toBeTruthy(); @@ -145,24 +139,34 @@ test("ToggleComponent", async ({ page }) => { ).toBeTruthy(); expect( - await page.locator('//*[@id="toggle-edit-1"]').isChecked() + await page.getByTestId("toggle-edit-load_hidden").isChecked() ).toBeFalsy(); await page.locator('//*[@id="saveChangesBtn"]').click(); - await page.locator('//*[@id="toggle-1"]').click(); - expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeTruthy(); + await page.getByTestId("toggle-load_hidden").click(); + expect( + await page.getByTestId("toggle-load_hidden").isChecked() + ).toBeTruthy(); - await page.locator('//*[@id="toggle-1"]').click(); - expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeFalsy(); + await page.getByTestId("toggle-load_hidden").click(); + expect( + await page.getByTestId("toggle-load_hidden").isChecked() + ).toBeFalsy(); - await page.locator('//*[@id="toggle-1"]').click(); - expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeTruthy(); + await page.getByTestId("toggle-load_hidden").click(); + expect( + await page.getByTestId("toggle-load_hidden").isChecked() + ).toBeTruthy(); - await page.locator('//*[@id="toggle-1"]').click(); - expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeFalsy(); + await page.getByTestId("toggle-load_hidden").click(); + expect( + await page.getByTestId("toggle-load_hidden").isChecked() + ).toBeFalsy(); - await page.locator('//*[@id="toggle-1"]').click(); - expect(await page.locator('//*[@id="toggle-1"]').isChecked()).toBeTruthy(); + await page.getByTestId("toggle-load_hidden").click(); + expect( + await page.getByTestId("toggle-load_hidden").isChecked() + ).toBeTruthy(); } }); diff --git a/src/frontend/tests/end-to-end/tweaks_test.spec.ts b/src/frontend/tests/end-to-end/tweaks_test.spec.ts new file mode 100644 index 000000000..acfe6f1cb --- /dev/null +++ b/src/frontend/tests/end-to-end/tweaks_test.spec.ts @@ -0,0 +1,38 @@ +import { expect, test } from "@playwright/test"; + +test("curl_api_generation", async ({ page, context }) => { + await page.goto("/"); + await page.locator('//*[@id="new-project-btn"]').click(); + await context.grantPermissions(["clipboard-read", "clipboard-write"]); + await page.getByRole("heading", { name: "Data Ingestion" }).click(); + await page.waitForTimeout(2000); + await page.getByText("API", { exact: true }).click(); + await page.getByRole("tab", { name: "cURL" }).click(); + await page.getByRole("button", { name: "Copy Code" }).click(); + const handle = await page.evaluateHandle(() => + navigator.clipboard.readText() + ); + const clipboardContent = await handle.jsonValue(); + const oldValue = clipboardContent; + expect(clipboardContent.length).toBeGreaterThan(0); + await page.getByRole("tab", { name: "Tweaks" }).click(); + await page + .getByRole("heading", { name: "URL" }) + .locator("div") + .first() + .click(); + await page.getByRole("textbox", { name: "Type something..." }).click(); + await page + .getByRole("textbox", { name: "Type something..." }) + .press("Control+a"); + await page.getByRole("textbox", { name: "Type something..." }).fill("teste"); + await page.getByRole("tab", { name: "cURL" }).click(); + await page.getByRole("button", { name: "Copy Code" }).click(); + const handle2 = await page.evaluateHandle(() => + navigator.clipboard.readText() + ); + const clipboardContent2 = await handle2.jsonValue(); + const newValue = clipboardContent2; + expect(oldValue).not.toBe(newValue); + expect(clipboardContent2.length).toBeGreaterThan(clipboardContent.length); +}); diff --git a/src/frontend/tests/globalTeardown.ts b/src/frontend/tests/globalTeardown.ts new file mode 100644 index 000000000..110978d42 --- /dev/null +++ b/src/frontend/tests/globalTeardown.ts @@ -0,0 +1,25 @@ +// tests/globalTeardown.ts + +import fs from "fs"; +import path from "path"; + +export default async () => { + try { + console.log("Removing the temp database"); + // Check if the file exists in the path + // this file is in src/frontend/tests/globalTeardown.ts + // temp is in src/frontend/temp + const tempDbPath = path.join(__dirname, "..", "temp"); + console.log("tempDbPath", tempDbPath); + // Remove the temp database + fs.rmSync(tempDbPath); + // Check if the file is removed + if (!fs.existsSync(tempDbPath)) { + console.log("Successfully removed the temp database"); + } else { + console.error("Error while removing the temp database"); + } + } catch (error) { + console.error("Error while removing the temp database:", error); + } +}; diff --git a/src/frontend/tests/onlyFront/dropdownComponent.spec.ts b/src/frontend/tests/onlyFront/dropdownComponent.spec.ts deleted file mode 100644 index ea397e68d..000000000 --- a/src/frontend/tests/onlyFront/dropdownComponent.spec.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { expect, test } from "@playwright/test"; - -test("dropDownComponent", async ({ page }) => { - await page.routeFromHAR("harFiles/backend_12112023.har", { - url: "**/api/v1/**", - update: false, - }); - await page.route("**/api/v1/flows/", async (route) => { - const json = { - id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210", - }; - await route.fulfill({ json, status: 201 }); - }); - - await page.goto("http://localhost:3000/"); - await page.waitForTimeout(2000); - - await page.locator('//*[@id="new-project-btn"]').click(); - await page.waitForTimeout(2000); - - await page.getByPlaceholder("Search").click(); - await page.getByPlaceholder("Search").fill("amazon"); - - await page.waitForTimeout(2000); - - await page - .getByTestId("llmsAmazon Bedrock") - .first() - .dragTo(page.locator('//*[@id="react-flow-id"]')); - await page.mouse.up(); - await page.mouse.down(); - - await page.getByTestId("dropdown-2-display").click(); - await page.getByTestId("ai21.j2-grande-instruct-0-option").click(); - - let value = await page.getByTestId("dropdown-2-display").innerText(); - if (value !== "ai21.j2-grande-instruct") { - expect(false).toBeTruthy(); - } - - await page.getByTestId("dropdown-2-display").click(); - await page.getByTestId("ai21.j2-jumbo-instruct-1-option").click(); - - value = await page.getByTestId("dropdown-2-display").innerText(); - if (value !== "ai21.j2-jumbo-instruct") { - expect(false).toBeTruthy(); - } - - await page.getByTestId("more-options-modal").click(); - await page.getByTestId("edit-button-modal").click(); - - value = await page.getByTestId("dropdown-edit-1-display").innerText(); - if (value !== "ai21.j2-jumbo-instruct") { - expect(false).toBeTruthy(); - } - - // showcode - await page.locator('//*[@id="showcode"]').click(); - expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeFalsy(); - - // showmodel_id - await page.locator('//*[@id="showmodel_id"]').click(); - expect(await page.locator('//*[@id="showmodel_id"]').isChecked()).toBeFalsy(); - - // showcode - await page.locator('//*[@id="showcode"]').click(); - expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeTruthy(); - - // showmodel_id - await page.locator('//*[@id="showmodel_id"]').click(); - expect( - await page.locator('//*[@id="showmodel_id"]').isChecked() - ).toBeTruthy(); - - // showcode - await page.locator('//*[@id="showcode"]').click(); - expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeFalsy(); - - // showmodel_id - await page.locator('//*[@id="showmodel_id"]').click(); - expect(await page.locator('//*[@id="showmodel_id"]').isChecked()).toBeFalsy(); - - // showcode - await page.locator('//*[@id="showcode"]').click(); - expect(await page.locator('//*[@id="showcode"]').isChecked()).toBeTruthy(); - - // showmodel_id - await page.locator('//*[@id="showmodel_id"]').click(); - expect( - await page.locator('//*[@id="showmodel_id"]').isChecked() - ).toBeTruthy(); - - await page.getByTestId("dropdown-edit-1-display").click(); - await page.getByTestId("ai21.j2-ultra-v1-5-option").click(); - - value = await page.getByTestId("dropdown-edit-1-display").innerText(); - if (value !== "ai21.j2-ultra-v1") { - expect(false).toBeTruthy(); - } - - await page.locator('//*[@id="saveChangesBtn"]').click(); - - value = await page.getByTestId("dropdown-2-display").innerText(); - if (value !== "ai21.j2-ultra-v1") { - expect(false).toBeTruthy(); - } -}); diff --git a/src/frontend/tests/onlyFront/group.spec.ts b/src/frontend/tests/onlyFront/group.spec.ts deleted file mode 100644 index dcd557279..000000000 --- a/src/frontend/tests/onlyFront/group.spec.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { expect, test } from "@playwright/test"; -import { readFileSync } from "fs"; - -test.describe("group node test", () => { - /// - test("group and ungroup updating values", async ({ page }) => { - await page.routeFromHAR("harFiles/langflow.har", { - url: "**/api/v1/**", - update: false, - }); - await page.route("**/api/v1/flows/", async (route) => { - const json = { - id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210", - }; - await route.fulfill({ json, status: 201 }); - }); - await page.goto("http:localhost:3000/"); - await page.locator("span").filter({ hasText: "My Collection" }).isVisible(); - // Read your file into a buffer. - const jsonContent = readFileSync( - "tests/onlyFront/assets/collection.json", - "utf-8" - ); - - // Create the DataTransfer and File - const dataTransfer = await page.evaluateHandle((data) => { - const dt = new DataTransfer(); - // Convert the buffer to a hex array - const file = new File([data], "flowtest.json", { - type: "application/json", - }); - dt.items.add(file); - return dt; - }, jsonContent); - - page.waitForTimeout(2000); - - await page.dispatchEvent( - '//*[@id="root"]/div/div[1]/div[2]/div[3]/div/div', - "drop", - { - dataTransfer, - } - ); - - await page - .getByTestId("edit-flow-button-e9ac1bdc-429b-475d-ac03-d26f9a2a3210-0") - .click(); - await page.waitForTimeout(2000); - - const genericNoda = page.getByTestId("div-generic-node"); - const elementCount = await genericNoda.count(); - if (elementCount > 0) { - expect(true).toBeTruthy(); - } - - await page.getByTestId("title-PythonFunctionTool").click({ - modifiers: ["Control"], - }); - await page.getByTestId("title-ChatOpenAI").click({ - modifiers: ["Control"], - }); - - await page.getByTestId("title-AgentInitializer").click({ - modifiers: ["Control"], - }); - - await page.getByRole("button", { name: "Group" }).click(); - - const textArea = page.getByTestId("div-textarea-description"); - const elementCountText = await textArea.count(); - if (elementCountText > 0) { - expect(true).toBeTruthy(); - } - - const groupNode = page.getByTestId("title-Group"); - const elementGroup = await groupNode.count(); - if (elementGroup > 0) { - expect(true).toBeTruthy(); - } - - // Now dispatch - }); -}); diff --git a/src/frontend/tests/onlyFront/intComponent.spec.ts b/src/frontend/tests/onlyFront/intComponent.spec.ts deleted file mode 100644 index be94d82e8..000000000 --- a/src/frontend/tests/onlyFront/intComponent.spec.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { expect, test } from "@playwright/test"; - -test("IntComponent", async ({ page }) => { - await page.routeFromHAR("harFiles/backend_12112023.har", { - url: "**/api/v1/**", - update: false, - }); - await page.route("**/api/v1/flows/", async (route) => { - const json = { - id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210", - }; - await route.fulfill({ json, status: 201 }); - }); - - await page.goto("http://localhost:3000/"); - await page.waitForTimeout(2000); - - await page.locator('//*[@id="new-project-btn"]').click(); - await page.waitForTimeout(2000); - - await page.getByPlaceholder("Search").click(); - await page.getByPlaceholder("Search").fill("getrequest"); - - await page.waitForTimeout(2000); - - await page - .getByTestId("utilitiesGET Request") - .first() - .dragTo(page.locator('//*[@id="react-flow-id"]')); - await page.mouse.up(); - await page.mouse.down(); - - await page.locator('//*[@id="int-input-2"]').click(); - await page - .locator('//*[@id="int-input-2"]') - .fill("123456789123456789123456789"); - - let value = await page.locator('//*[@id="int-input-2"]').inputValue(); - - if (value != "123456789123456789123456789") { - expect(false).toBeTruthy(); - } - - await page.locator('//*[@id="int-input-2"]').click(); - await page.locator('//*[@id="int-input-2"]').fill("0"); - - value = await page.locator('//*[@id="int-input-2"]').inputValue(); - - if (value != "0") { - expect(false).toBeTruthy(); - } - - await page.getByTestId("more-options-modal").click(); - await page.getByTestId("edit-button-modal").click(); - - value = await page.locator('//*[@id="edit-int-input-2"]').inputValue(); - - if (value != "0") { - expect(false).toBeTruthy(); - } - - await page.locator('//*[@id="edit-int-input-2"]').click(); - await page - .locator('//*[@id="edit-int-input-2"]') - .fill("123456789123456789123456789"); - - await page.locator('//*[@id="showheaders"]').click(); - expect(await page.locator('//*[@id="showheaders"]').isChecked()).toBeFalsy(); - - await page.locator('//*[@id="showtimeout"]').click(); - expect(await page.locator('//*[@id="showtimeout"]').isChecked()).toBeFalsy(); - - await page.locator('//*[@id="showurl"]').click(); - expect(await page.locator('//*[@id="showurl"]').isChecked()).toBeFalsy(); - - await page.locator('//*[@id="showheaders"]').click(); - expect(await page.locator('//*[@id="showheaders"]').isChecked()).toBeTruthy(); - - await page.locator('//*[@id="showurl"]').click(); - expect(await page.locator('//*[@id="showurl"]').isChecked()).toBeTruthy(); - - await page.locator('//*[@id="saveChangesBtn"]').click(); - - const plusButtonLocator = page.locator('//*[@id="int-input-2"]'); - const elementCount = await plusButtonLocator.count(); - if (elementCount === 0) { - expect(true).toBeTruthy(); - - await page.getByTestId("more-options-modal").click(); - await page.getByTestId("edit-button-modal").click(); - - await page.locator('//*[@id="showtimeout"]').click(); - expect( - await page.locator('//*[@id="showtimeout"]').isChecked() - ).toBeTruthy(); - - const valueEditNode = await page - .locator('//*[@id="edit-int-input-2"]') - .inputValue(); - - if (valueEditNode != "123456789123456789123456789") { - expect(false).toBeTruthy(); - } - - await page.locator('//*[@id="saveChangesBtn"]').click(); - await page.locator('//*[@id="int-input-2"]').click(); - await page.locator('//*[@id="int-input-2"]').fill("3"); - - let value = await page.locator('//*[@id="int-input-2"]').inputValue(); - - if (value != "3") { - expect(false).toBeTruthy(); - } - - await page.locator('//*[@id="int-input-2"]').click(); - await page.locator('//*[@id="int-input-2"]').fill("-3"); - - value = await page.locator('//*[@id="int-input-2"]').inputValue(); - - if (value != "0") { - expect(false).toBeTruthy(); - } - } -}); diff --git a/src/frontend/tests/onlyFront/login.spec.ts b/src/frontend/tests/onlyFront/login.spec.ts deleted file mode 100644 index 119d00a37..000000000 --- a/src/frontend/tests/onlyFront/login.spec.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { test } from "@playwright/test"; - -test.describe("Login Tests", () => { - test("Login_Success", async ({ page }) => { - // await page.route("**/api/v1/login", async (route) => { - // const json = { - // access_token: - // "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhMWNlM2FkOS1iZTE2LTRiNjgtOGRhYi1hYjA4YTVjMmZjZTkiLCJleHAiOjE2OTUyNTIwNTh9.MBYFwMhTcZnsW_L7p4qavUhSDylCllJQWUCJdU1wX8o", - // refresh_token: - // "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhMWNlM2FkOS1iZTE2LTRiNjgtOGRhYi1hYjA4YTVjMmZjZTkiLCJ0eXBlIjoicmYiLCJleHAiOjE2OTUyNTI2NTh9.a4wL9-XK_zyTyrXduBFgCsODFXrqiByVr5HOeiCbiQA", - // token_type: "bearer", - // }; - // await route.fulfill({ json }); - // }); - // await page.goto("http://localhost:3000/"); - // await page.waitForURL("http://localhost:3000/login"); - // await page.waitForURL("http://localhost:3000/login", { timeout: 100 }); - // await page.getByPlaceholder("Username").click(); - // await page.getByPlaceholder("Username").fill("test"); - // await page.getByPlaceholder("Password").click(); - // await page.getByPlaceholder("Password").fill("test"); - // await page.getByRole("button", { name: "Sign in" }).click(); - // await page.getByRole("button", { name: "Community Examples" }).click(); - // await page.waitForSelector(".community-pages-flows-panel"); - // expect( - // await page - // .locator(".community-pages-flows-panel") - // .evaluate((el) => el.children) - // ).toBeTruthy(); - // }); - // test("Login Error", async ({ page }) => { - // await page.route("**/api/v1/login", async (route) => { - // const json = { detail: "Incorrect username or password" }; - // await route.fulfill({ json, status: 401 }); - // }); - // await page.goto("http://localhost:3000/"); - // await page.waitForURL("http://localhost:3000/login"); - // await page.waitForURL("http://localhost:3000/login", { timeout: 100 }); - // await page.getByPlaceholder("Username").click(); - // await page.getByPlaceholder("Username").fill("test"); - // await page.getByPlaceholder("Password").click(); - // await page.getByPlaceholder("Password").fill("test5"); - // await page.getByRole("button", { name: "Sign in" }).click(); - // await page.getByRole("heading", { name: "Error signing in" }).click(); - // }); - // test("Login create account wrong form", async ({ page }) => { - // const fullfillForm = async (username, password, confirmPassword) => { - // await page.getByPlaceholder("Username").click(); - // await page.getByPlaceholder("Username").fill(username); - // await page.getByPlaceholder("Password", { exact: true }).click(); - // await page.getByPlaceholder("Password", { exact: true }).fill(password); - // await page.getByPlaceholder("Confirm your password").click(); - // await page - // .getByPlaceholder("Confirm your password") - // .fill(confirmPassword); - // }; - // await page.goto("http://localhost:3000/"); - // await page.waitForURL("http://localhost:3000/login"); - // await page.waitForURL("http://localhost:3000/login", { timeout: 100 }); - // await page - // .getByRole("button", { name: "Don't have an account? Sign Up" }) - // .click(); - // await page.getByText("Sign up to Langflow").click(); - // await page.goto("http://localhost:3000/signup"); - // await page.getByText("Sign up to Langflow").click(); - // await fullfillForm("name", "vazz", "vazz5"); - // expect( - // await page.getByRole("button", { name: "Sign up" }).isDisabled() - // ).toBeTruthy(); - // await fullfillForm("", "vazz", "vazz"); - // expect( - // await page.getByRole("button", { name: "Sign up" }).isDisabled() - // ).toBeTruthy(); - // await fullfillForm("name", "", ""); - // expect( - // await page.getByRole("button", { name: "Sign up" }).isDisabled() - // ).toBeTruthy(); - // await fullfillForm("", "", ""); - // expect( - // await page.getByRole("button", { name: "Sign up" }).isDisabled() - // ).toBeTruthy(); - // }); - // test("Login create account success", async ({ page }) => { - // await page.route("**/api/v1/users/", async (route) => { - // const json = { - // id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210", - // username: "teste", - // profile_image: null, - // is_active: false, - // is_superuser: false, - // create_at: "2023-09-21T01:45:51.873303", - // updated_at: "2023-09-21T01:45:51.873305", - // last_login_at: null, - // }; - // await route.fulfill({ json, status: 201 }); - // }); - // const submitForm = async (username, password, confirmPassword) => { - // await page.getByPlaceholder("Username").click(); - // await page.getByPlaceholder("Username").fill(username); - // await page.getByPlaceholder("Password", { exact: true }).click(); - // await page.getByPlaceholder("Password", { exact: true }).fill(password); - // await page.getByPlaceholder("Confirm your password").click(); - // await page - // .getByPlaceholder("Confirm your password") - // .fill(confirmPassword); - // }; - // await page.goto("http://localhost:3000/"); - // await page.waitForURL("http://localhost:3000/login"); - // await page.waitForURL("http://localhost:3000/login", { timeout: 100 }); - // await page - // .getByRole("button", { name: "Don't have an account? Sign Up" }) - // .click(); - // await page.getByText("Sign up to Langflow").click(); - // await page.goto("http://localhost:3000/signup"); - // await page.getByText("Sign up to Langflow").click(); - // await submitForm("teste", "pass", "pass"); - // await page.getByRole("button", { name: "Sign up" }).click(); - // await page.waitForURL("http://localhost:3000/login", { timeout: 1000 }); - // await page.getByText("Account created! Await admin activation.").click(); - }); -}); diff --git a/tests/conftest.py b/tests/conftest.py index af9bbe169..7f7252243 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -10,12 +10,14 @@ import orjson import pytest from fastapi.testclient import TestClient from httpx import AsyncClient -from sqlmodel import Session, SQLModel, create_engine +from sqlmodel import Session, SQLModel, create_engine, select from sqlmodel.pool import StaticPool from typer.testing import CliRunner from langflow.graph.graph.base import Graph +from langflow.initial_setup.setup import STARTER_FOLDER_NAME from langflow.services.auth.utils import get_password_hash +from langflow.services.database.models.api_key.model import ApiKey from langflow.services.database.models.flow.model import Flow, FlowCreate from langflow.services.database.models.user.model import User, UserCreate from langflow.services.database.utils import session_getter @@ -28,14 +30,17 @@ if TYPE_CHECKING: def pytest_configure(): pytest.BASIC_EXAMPLE_PATH = Path(__file__).parent.absolute() / "data" / "basic_example.json" pytest.COMPLEX_EXAMPLE_PATH = Path(__file__).parent.absolute() / "data" / "complex_example.json" + pytest.COMPLEX_DEPS_EXAMPLE_PATH = Path(__file__).parent.absolute() / "data" / "complex_deps_example.json" pytest.OPENAPI_EXAMPLE_PATH = Path(__file__).parent.absolute() / "data" / "Openapi.json" pytest.GROUPED_CHAT_EXAMPLE_PATH = Path(__file__).parent.absolute() / "data" / "grouped_chat.json" pytest.ONE_GROUPED_CHAT_EXAMPLE_PATH = Path(__file__).parent.absolute() / "data" / "one_group_chat.json" pytest.VECTOR_STORE_GROUPED_EXAMPLE_PATH = Path(__file__).parent.absolute() / "data" / "vector_store_grouped.json" pytest.BASIC_CHAT_WITH_PROMPT_AND_HISTORY = ( - Path(__file__).parent.absolute() / "data" / "BasicChatwithPromptandHistory.json" + Path(__file__).parent.absolute() / "data" / "BasicChatWithPromptAndHistory.json" ) + pytest.CHAT_INPUT = Path(__file__).parent.absolute() / "data" / "ChatInputTest.json" + pytest.TWO_OUTPUTS = Path(__file__).parent.absolute() / "data" / "TwoOutputsTest.json" pytest.VECTOR_STORE_PATH = Path(__file__).parent.absolute() / "data" / "Vector_store.json" pytest.CODE_WITH_SYNTAX_ERROR = """ def get_text(): @@ -43,6 +48,13 @@ def get_text(): """ +@pytest.fixture(autouse=True) +def check_openai_api_key_in_environment_variables(): + import os + + assert os.environ.get("OPENAI_API_KEY") is not None, "OPENAI_API_KEY is not set in environment variables" + + @pytest.fixture() async def async_client() -> AsyncGenerator: from langflow.main import create_app @@ -181,6 +193,16 @@ def json_vector_store(): return f.read() +@pytest.fixture +def complex_graph_with_groups(): + with open(pytest.COMPLEX_DEPS_EXAMPLE_PATH, "r") as f: + flow_graph = json.load(f) + data_graph = flow_graph["data"] + nodes = data_graph["nodes"] + edges = data_graph["edges"] + return Graph(nodes, edges) + + @pytest.fixture(name="client", autouse=True) def client_fixture(session: Session, monkeypatch): # Set the database url to a test database @@ -225,7 +247,7 @@ def test_user(client): username="testuser", password="testpassword", ) - response = client.post("/api/v1/users", json=user_data.model_dump()) + response = client.post("/api/v1/users", json=user_data.dict()) assert response.status_code == 201 return response.json() @@ -241,7 +263,7 @@ def active_user(client): is_superuser=False, ) # check if user exists - if active_user := session.query(User).filter(User.username == user.username).first(): + if active_user := session.exec(select(User).where(User.username == user.username)).first(): return active_user session.add(user) session.commit() @@ -264,13 +286,9 @@ def flow(client, json_flow: str, active_user): from langflow.services.database.models.flow.model import FlowCreate loaded_json = json.loads(json_flow) - flow_data = FlowCreate( - name="test_flow", - data=loaded_json.get("data"), - user_id=active_user.id, - description="description", - ) - flow = Flow.model_validate(flow_data.model_dump()) + flow_data = FlowCreate(name="test_flow", data=loaded_json.get("data"), user_id=active_user.id) + + flow = Flow.model_validate(flow_data) with session_getter(get_db_service()) as session: session.add(flow) session.commit() @@ -280,11 +298,47 @@ def flow(client, json_flow: str, active_user): @pytest.fixture -def added_flow(client, json_flow_with_prompt_and_history, logged_in_headers): +def json_chat_input(): + with open(pytest.CHAT_INPUT, "r") as f: + return f.read() + + +@pytest.fixture +def json_two_outputs(): + with open(pytest.TWO_OUTPUTS, "r") as f: + return f.read() + + +@pytest.fixture +def added_flow_with_prompt_and_history(client, json_flow_with_prompt_and_history, logged_in_headers): flow = orjson.loads(json_flow_with_prompt_and_history) data = flow["data"] flow = FlowCreate(name="Basic Chat", description="description", data=data) - response = client.post("api/v1/flows/", json=flow.model_dump(), headers=logged_in_headers) + response = client.post("api/v1/flows/", json=flow.dict(), headers=logged_in_headers) + assert response.status_code == 201 + assert response.json()["name"] == flow.name + assert response.json()["data"] == flow.data + return response.json() + + +@pytest.fixture +def added_flow_chat_input(client, json_chat_input, logged_in_headers): + flow = orjson.loads(json_chat_input) + data = flow["data"] + flow = FlowCreate(name="Chat Input", description="description", data=data) + response = client.post("api/v1/flows/", json=flow.dict(), headers=logged_in_headers) + assert response.status_code == 201 + assert response.json()["name"] == flow.name + assert response.json()["data"] == flow.data + return response.json() + + +@pytest.fixture +def added_flow_two_outputs(client, json_two_outputs, logged_in_headers): + flow = orjson.loads(json_two_outputs) + data = flow["data"] + flow = FlowCreate(name="Two Outputs", description="description", data=data) + response = client.post("api/v1/flows/", json=flow.dict(), headers=logged_in_headers) assert response.status_code == 201 assert response.json()["name"] == flow.name assert response.json()["data"] == flow.data @@ -296,7 +350,7 @@ def added_vector_store(client, json_vector_store, logged_in_headers): vector_store = orjson.loads(json_vector_store) data = vector_store["data"] vector_store = FlowCreate(name="Vector Store", description="description", data=data) - response = client.post("api/v1/flows/", json=vector_store.model_dump(), headers=logged_in_headers) + response = client.post("api/v1/flows/", json=vector_store.dict(), headers=logged_in_headers) assert response.status_code == 201 assert response.json()["name"] == vector_store.name assert response.json()["data"] == vector_store.data @@ -304,16 +358,43 @@ def added_vector_store(client, json_vector_store, logged_in_headers): @pytest.fixture -def test_component_code(): - path = Path(__file__).parent.absolute() / "data" / "component.py" - # load the content as a string - with open(path, "r") as f: - return f.read() +def created_api_key(active_user): + hashed = get_password_hash("random_key") + api_key = ApiKey( + name="test_api_key", + user_id=active_user.id, + api_key="random_key", + hashed_api_key=hashed, + ) + db_manager = get_db_service() + with session_getter(db_manager) as session: + if existing_api_key := session.exec(select(ApiKey).where(ApiKey.api_key == api_key.api_key)).first(): + return existing_api_key + session.add(api_key) + session.commit() + session.refresh(api_key) + return api_key -@pytest.fixture -def test_component_with_templatefield_code(): - path = Path(__file__).parent.absolute() / "data" / "component_with_templatefield.py" - # load the content as a string - with open(path, "r") as f: - return f.read() +@pytest.fixture(name="starter_project") +def get_starter_project(active_user): + # once the client is created, we can get the starter project + with session_getter(get_db_service()) as session: + flow = session.exec( + select(Flow).where(Flow.folder == STARTER_FOLDER_NAME).where(Flow.name == "Basic Prompting (Hello, world!)") + ).first() + if not flow: + raise ValueError("No starter project found") + + new_flow_create = FlowCreate( + name=flow.name, + description=flow.description, + data=flow.data, + user_id=active_user.id, + ) + new_flow = Flow.model_validate(new_flow_create, from_attributes=True) + session.add(new_flow) + session.commit() + session.refresh(new_flow) + new_flow_dict = new_flow.model_dump() + return new_flow_dict diff --git a/tests/data/ChatInputTest.json b/tests/data/ChatInputTest.json new file mode 100644 index 000000000..3c516067e --- /dev/null +++ b/tests/data/ChatInputTest.json @@ -0,0 +1,918 @@ +{ + "name": "ChatInputTest", + "description": "", + "data": { + "nodes": [ + { + "width": 384, + "height": 359, + "id": "PromptTemplate-IKKOx", + "type": "genericNode", + "position": { + "x": 880, + "y": 646.9375 + }, + "data": { + "type": "PromptTemplate", + "node": { + "template": { + "output_parser": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "output_parser", + "advanced": false, + "dynamic": false, + "info": "", + "type": "BaseOutputParser", + "list": false + }, + "input_variables": { + "required": true, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "input_variables", + "advanced": false, + "dynamic": false, + "info": "", + "type": "str", + "list": true, + "value": [ + "input" + ] + }, + "partial_variables": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "partial_variables", + "advanced": false, + "dynamic": false, + "info": "", + "type": "code", + "list": false + }, + "template": { + "required": true, + "placeholder": "", + "show": true, + "multiline": true, + "password": false, + "name": "template", + "advanced": false, + "dynamic": false, + "info": "", + "type": "prompt", + "list": false, + "value": "Input: {input}\nAI:" + }, + "template_format": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "value": "f-string", + "password": false, + "name": "template_format", + "advanced": false, + "dynamic": false, + "info": "", + "type": "str", + "list": false + }, + "validate_template": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "value": true, + "password": false, + "name": "validate_template", + "advanced": false, + "dynamic": false, + "info": "", + "type": "bool", + "list": false + }, + "_type": "PromptTemplate", + "input": { + "required": false, + "placeholder": "", + "show": true, + "multiline": true, + "value": "", + "password": false, + "name": "input", + "display_name": "input", + "advanced": false, + "input_types": [ + "Document", + "BaseOutputParser", + "str" + ], + "dynamic": false, + "info": "", + "type": "str", + "list": false + } + }, + "description": "A prompt template for a language model.", + "base_classes": [ + "BasePromptTemplate", + "PromptTemplate", + "StringPromptTemplate" + ], + "name": "", + "display_name": "PromptTemplate", + "documentation": "https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/", + "custom_fields": { + "": [ + "input" + ], + "template": [ + "input" + ] + }, + "output_types": [], + "field_formatters": { + "formatters": { + "openai_api_key": {} + }, + "base_formatters": { + "kwargs": {}, + "optional": {}, + "list": {}, + "dict": {}, + "union": {}, + "multiline": {}, + "show": {}, + "password": {}, + "default": {}, + "headers": {}, + "dict_code_file": {}, + "model_fields": { + "MODEL_DICT": { + "OpenAI": [ + "text-davinci-003", + "text-davinci-002", + "text-curie-001", + "text-babbage-001", + "text-ada-001" + ], + "ChatOpenAI": [ + "gpt-3.5-turbo-0613", + "gpt-3.5-turbo", + "gpt-3.5-turbo-16k-0613", + "gpt-3.5-turbo-16k", + "gpt-4-0613", + "gpt-4-32k-0613", + "gpt-4", + "gpt-4-32k" + ], + "Anthropic": [ + "claude-v1", + "claude-v1-100k", + "claude-instant-v1", + "claude-instant-v1-100k", + "claude-v1.3", + "claude-v1.3-100k", + "claude-v1.2", + "claude-v1.0", + "claude-instant-v1.1", + "claude-instant-v1.1-100k", + "claude-instant-v1.0" + ], + "ChatAnthropic": [ + "claude-v1", + "claude-v1-100k", + "claude-instant-v1", + "claude-instant-v1-100k", + "claude-v1.3", + "claude-v1.3-100k", + "claude-v1.2", + "claude-v1.0", + "claude-instant-v1.1", + "claude-instant-v1.1-100k", + "claude-instant-v1.0" + ] + } + } + } + }, + "beta": false, + "error": null + }, + "id": "PromptTemplate-IKKOx" + }, + "selected": false, + "positionAbsolute": { + "x": 880, + "y": 646.9375 + }, + "dragging": false + }, + { + "width": 384, + "height": 307, + "id": "LLMChain-e2dhN", + "type": "genericNode", + "position": { + "x": 1449.330344958542, + "y": 880.1760221487797 + }, + "data": { + "type": "LLMChain", + "node": { + "template": { + "callbacks": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "callbacks", + "advanced": false, + "dynamic": false, + "info": "", + "type": "langchain.callbacks.base.BaseCallbackHandler", + "list": true + }, + "llm": { + "required": true, + "placeholder": "", + "show": true, + "multiline": false, + "password": false, + "name": "llm", + "advanced": false, + "dynamic": false, + "info": "", + "type": "BaseLanguageModel", + "list": false + }, + "memory": { + "required": false, + "placeholder": "", + "show": true, + "multiline": false, + "password": false, + "name": "memory", + "advanced": false, + "dynamic": false, + "info": "", + "type": "BaseMemory", + "list": false + }, + "output_parser": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "output_parser", + "advanced": false, + "dynamic": false, + "info": "", + "type": "BaseLLMOutputParser", + "list": false + }, + "prompt": { + "required": true, + "placeholder": "", + "show": true, + "multiline": false, + "password": false, + "name": "prompt", + "advanced": false, + "dynamic": false, + "info": "", + "type": "BasePromptTemplate", + "list": false + }, + "llm_kwargs": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "llm_kwargs", + "advanced": false, + "dynamic": false, + "info": "", + "type": "code", + "list": false + }, + "metadata": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "metadata", + "advanced": false, + "dynamic": false, + "info": "", + "type": "code", + "list": false + }, + "output_key": { + "required": true, + "placeholder": "", + "show": true, + "multiline": false, + "value": "text", + "password": false, + "name": "output_key", + "advanced": true, + "dynamic": false, + "info": "", + "type": "str", + "list": false + }, + "return_final_only": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "value": true, + "password": false, + "name": "return_final_only", + "advanced": false, + "dynamic": false, + "info": "", + "type": "bool", + "list": false + }, + "tags": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "tags", + "advanced": false, + "dynamic": false, + "info": "", + "type": "str", + "list": true + }, + "verbose": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "value": false, + "password": false, + "name": "verbose", + "advanced": true, + "dynamic": false, + "info": "", + "type": "bool", + "list": false + }, + "_type": "LLMChain" + }, + "description": "Chain to run queries against LLMs.", + "base_classes": [ + "Chain", + "LLMChain", + "function", + "Text" + ], + "display_name": "LLMChain", + "custom_fields": {}, + "output_types": [], + "documentation": "https://python.langchain.com/docs/modules/chains/foundational/llm_chain", + "beta": false, + "error": null + }, + "id": "LLMChain-e2dhN" + }, + "positionAbsolute": { + "x": 1449.330344958542, + "y": 880.1760221487797 + } + }, + { + "width": 384, + "height": 621, + "id": "ChatOpenAI-2I57f", + "type": "genericNode", + "position": { + "x": 393.3551923753797, + "y": 1061.025177453298 + }, + "data": { + "type": "ChatOpenAI", + "node": { + "template": { + "callbacks": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "callbacks", + "advanced": false, + "dynamic": false, + "info": "", + "type": "langchain.callbacks.base.BaseCallbackHandler", + "list": true + }, + "cache": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "cache", + "advanced": false, + "dynamic": false, + "info": "", + "type": "bool", + "list": false + }, + "client": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "client", + "advanced": false, + "dynamic": false, + "info": "", + "type": "Any", + "list": false + }, + "max_retries": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "value": 6, + "password": false, + "name": "max_retries", + "advanced": false, + "dynamic": false, + "info": "", + "type": "int", + "list": false + }, + "max_tokens": { + "required": false, + "placeholder": "", + "show": true, + "multiline": false, + "password": true, + "name": "max_tokens", + "advanced": false, + "dynamic": false, + "info": "", + "type": "int", + "list": false, + "value": "" + }, + "metadata": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "metadata", + "advanced": false, + "dynamic": false, + "info": "", + "type": "code", + "list": false + }, + "model_kwargs": { + "required": false, + "placeholder": "", + "show": true, + "multiline": false, + "password": false, + "name": "model_kwargs", + "advanced": true, + "dynamic": false, + "info": "", + "type": "code", + "list": false + }, + "model_name": { + "required": false, + "placeholder": "", + "show": true, + "multiline": false, + "value": "gpt-3.5-turbo-0613", + "password": false, + "options": [ + "gpt-3.5-turbo-0613", + "gpt-3.5-turbo", + "gpt-3.5-turbo-16k-0613", + "gpt-3.5-turbo-16k", + "gpt-4-0613", + "gpt-4-32k-0613", + "gpt-4", + "gpt-4-32k" + ], + "name": "model_name", + "advanced": false, + "dynamic": false, + "info": "", + "type": "str", + "list": true + }, + "n": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "value": 1, + "password": false, + "name": "n", + "advanced": false, + "dynamic": false, + "info": "", + "type": "int", + "list": false + }, + "openai_api_base": { + "required": false, + "placeholder": "", + "show": true, + "multiline": false, + "password": false, + "name": "openai_api_base", + "display_name": "OpenAI API Base", + "advanced": false, + "dynamic": false, + "info": "\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\n", + "type": "str", + "list": false + }, + "openai_api_key": { + "required": false, + "placeholder": "", + "show": true, + "multiline": false, + "value": "", + "password": true, + "name": "openai_api_key", + "display_name": "OpenAI API Key", + "advanced": false, + "dynamic": false, + "info": "", + "type": "str", + "list": false + }, + "openai_organization": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "openai_organization", + "display_name": "OpenAI Organization", + "advanced": false, + "dynamic": false, + "info": "", + "type": "str", + "list": false + }, + "openai_proxy": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "openai_proxy", + "display_name": "OpenAI Proxy", + "advanced": false, + "dynamic": false, + "info": "", + "type": "str", + "list": false + }, + "request_timeout": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "request_timeout", + "advanced": false, + "dynamic": false, + "info": "", + "type": "float", + "list": false + }, + "streaming": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "value": false, + "password": false, + "name": "streaming", + "advanced": false, + "dynamic": false, + "info": "", + "type": "bool", + "list": false + }, + "tags": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "tags", + "advanced": false, + "dynamic": false, + "info": "", + "type": "str", + "list": true + }, + "temperature": { + "required": false, + "placeholder": "", + "show": true, + "multiline": false, + "value": 0.7, + "password": false, + "name": "temperature", + "advanced": false, + "dynamic": false, + "info": "", + "type": "float", + "list": false + }, + "tiktoken_model_name": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "tiktoken_model_name", + "advanced": false, + "dynamic": false, + "info": "", + "type": "str", + "list": false + }, + "verbose": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "value": false, + "password": false, + "name": "verbose", + "advanced": false, + "dynamic": false, + "info": "", + "type": "bool", + "list": false + }, + "_type": "ChatOpenAI" + }, + "description": "`OpenAI` Chat large language models API.", + "base_classes": [ + "BaseChatModel", + "ChatOpenAI", + "BaseLanguageModel", + "BaseLLM" + ], + "display_name": "ChatOpenAI", + "custom_fields": {}, + "output_types": [], + "documentation": "https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai", + "beta": false, + "error": null + }, + "id": "ChatOpenAI-2I57f" + }, + "selected": false, + "positionAbsolute": { + "x": 393.3551923753797, + "y": 1061.025177453298 + }, + "dragging": false + }, + { + "width": 384, + "height": 359, + "id": "ChatInput-207IY", + "type": "genericNode", + "position": { + "x": 415.1018926651509, + "y": 506.62736462360317 + }, + "data": { + "type": "ChatInput", + "node": { + "template": { + "code": { + "dynamic": true, + "required": true, + "placeholder": "", + "show": false, + "multiline": true, + "value": "from typing import Optional\nfrom langflow.custom import CustomComponent\n\n\nclass ChatInput(CustomComponent):\n display_name = \"Chat Input\"\n\n def build(self, message: Optional[str] = \"\") -> str:\n return message\n", + "password": false, + "name": "code", + "advanced": false, + "type": "code", + "list": false + }, + "_type": "CustomComponent", + "message": { + "required": false, + "placeholder": "", + "show": true, + "multiline": false, + "value": "", + "password": false, + "name": "message", + "display_name": "message", + "advanced": false, + "dynamic": false, + "info": "", + "type": "str", + "list": false + } + }, + "description": "Used to get user input from the chat.", + "base_classes": [ + "str" + ], + "display_name": "Chat Input", + "custom_fields": { + "message": null + }, + "output_types": [ + "ChatInput" + ], + "documentation": "", + "beta": true, + "error": null + }, + "id": "ChatInput-207IY" + }, + "positionAbsolute": { + "x": 415.1018926651509, + "y": 506.62736462360317 + } + }, + { + "width": 384, + "height": 389, + "id": "ChatOutput-1jlJy", + "type": "genericNode", + "position": { + "x": 2002.8008888732943, + "y": 926.1397178702218 + }, + "data": { + "type": "ChatOutput", + "node": { + "template": { + "code": { + "dynamic": true, + "required": true, + "placeholder": "", + "show": true, + "multiline": true, + "value": "from typing import Optional, Text\nfrom langflow.api.v1.schemas import ChatMessage\nfrom langflow.services.utils import get_chat_manager\nfrom langflow.custom import CustomComponent\nfrom anyio.from_thread import start_blocking_portal\nfrom loguru import logger\n\n\nclass ChatOutput(CustomComponent):\n display_name = \"Chat Output\"\n description = \"Used to send a message to the chat.\"\n\n field_config = {\n \"code\": {\n \"show\": False,\n }\n }\n\n def build_config(self):\n return {\"message\": {\"input_types\": [\"Text\"]}}\n\n def build(self, message: Optional[Text], is_ai: bool = False) -> Text:\n if not message:\n return \"\"\n try:\n chat_manager = get_chat_manager()\n chat_message = ChatMessage(message=message, is_bot=is_ai)\n # send_message is a coroutine\n # run in a thread safe manner\n with start_blocking_portal() as portal:\n portal.call(chat_manager.send_message, chat_message)\n chat_manager.chat_history.add_message(\n chat_manager.cache_manager.current_client_id, chat_message\n )\n except Exception as exc:\n logger.exception(exc)\n logger.debug(f\"Error sending message to chat: {exc}\")\n self.repr_value = message\n return message\n", + "password": false, + "name": "code", + "advanced": false, + "type": "code", + "list": false + }, + "_type": "CustomComponent", + "is_ai": { + "required": true, + "placeholder": "", + "show": true, + "multiline": false, + "value": true, + "password": false, + "name": "is_ai", + "display_name": "is_ai", + "advanced": false, + "dynamic": false, + "info": "", + "type": "bool", + "list": false + }, + "message": { + "required": false, + "placeholder": "", + "show": true, + "multiline": false, + "password": false, + "name": "message", + "display_name": "message", + "advanced": false, + "input_types": [ + "Text" + ], + "dynamic": false, + "info": "", + "type": "Text", + "list": false + } + }, + "description": "Used to send a message to the chat.", + "base_classes": [ + "str" + ], + "display_name": "Chat Output", + "custom_fields": { + "is_ai": null, + "message": null + }, + "output_types": [ + "ChatOutput" + ], + "documentation": "", + "beta": true, + "error": null + }, + "id": "ChatOutput-1jlJy" + }, + "selected": true, + "dragging": false, + "positionAbsolute": { + "x": 2002.8008888732943, + "y": 926.1397178702218 + } + } + ], + "edges": [ + { + "source": "PromptTemplate-IKKOx", + "sourceHandle": "PromptTemplate|PromptTemplate-IKKOx|BasePromptTemplate|PromptTemplate|StringPromptTemplate", + "target": "LLMChain-e2dhN", + "targetHandle": "BasePromptTemplate|prompt|LLMChain-e2dhN", + "style": { + "stroke": "#555" + }, + "className": "", + "animated": false, + "id": "reactflow__edge-PromptTemplate-IKKOxPromptTemplate|PromptTemplate-IKKOx|StringPromptTemplate|BasePromptTemplate|PromptTemplate-LLMChain-e2dhNBasePromptTemplate|prompt|LLMChain-e2dhN" + }, + { + "source": "ChatOpenAI-2I57f", + "sourceHandle": "ChatOpenAI|ChatOpenAI-2I57f|BaseChatModel|ChatOpenAI|BaseLanguageModel|BaseLLM", + "target": "LLMChain-e2dhN", + "targetHandle": "BaseLanguageModel|llm|LLMChain-e2dhN", + "style": { + "stroke": "#555" + }, + "className": "", + "animated": false, + "id": "reactflow__edge-ChatOpenAI-2I57fChatOpenAI|ChatOpenAI-2I57f|BaseChatModel|ChatOpenAI|BaseLanguageModel|BaseLLM-LLMChain-e2dhNBaseLanguageModel|llm|LLMChain-e2dhN" + }, + { + "source": "ChatInput-207IY", + "sourceHandle": "ChatInput|ChatInput-207IY|str", + "target": "PromptTemplate-IKKOx", + "targetHandle": "Document;BaseOutputParser;str|input|PromptTemplate-IKKOx", + "style": { + "stroke": "#555" + }, + "className": "", + "animated": false, + "id": "reactflow__edge-ChatInput-207IYChatInput|ChatInput-207IY|str-PromptTemplate-IKKOxDocument;BaseOutputParser;str|input|PromptTemplate-IKKOx" + }, + { + "source": "LLMChain-e2dhN", + "sourceHandle": "LLMChain|LLMChain-e2dhN|Chain|LLMChain|function|Text", + "target": "ChatOutput-1jlJy", + "targetHandle": "Text|message|ChatOutput-1jlJy", + "style": { + "stroke": "#555" + }, + "className": "stroke-foreground stroke-connection", + "animated": true, + "id": "reactflow__edge-LLMChain-e2dhNLLMChain|LLMChain-e2dhN|Chain|LLMChain|function|Text-ChatOutput-1jlJyText|message|ChatOutput-1jlJy" + } + ], + "viewport": { + "x": -141.98308184453367, + "y": -104.98637616656356, + "zoom": 0.4788209787464315 + } + }, + "id": "b3388ab9-b5dc-4447-b560-79caef40faa5", + "user_id": "c65bfea3-3eea-4e71-8fc4-106238eb0583" +} \ No newline at end of file diff --git a/tests/data/TwoOutputsTest.json b/tests/data/TwoOutputsTest.json new file mode 100644 index 000000000..4cd060249 --- /dev/null +++ b/tests/data/TwoOutputsTest.json @@ -0,0 +1,1024 @@ +{ + "name": "TwoOutputsTest", + "description": "", + "data": { + "nodes": [ + { + "width": 384, + "height": 359, + "id": "PromptTemplate-CweKz", + "type": "genericNode", + "position": { + "x": 969.6448076246203, + "y": 528.7788853763968 + }, + "data": { + "type": "PromptTemplate", + "node": { + "template": { + "output_parser": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "output_parser", + "advanced": false, + "dynamic": false, + "info": "", + "type": "BaseOutputParser", + "list": false + }, + "input_variables": { + "required": true, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "input_variables", + "advanced": false, + "dynamic": false, + "info": "", + "type": "str", + "list": true, + "value": [ + "input" + ] + }, + "partial_variables": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "partial_variables", + "advanced": false, + "dynamic": false, + "info": "", + "type": "code", + "list": false + }, + "template": { + "required": true, + "placeholder": "", + "show": true, + "multiline": true, + "password": false, + "name": "template", + "advanced": false, + "dynamic": false, + "info": "", + "type": "prompt", + "list": false, + "value": "Input: {input}\nAI:" + }, + "template_format": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "value": "f-string", + "password": false, + "name": "template_format", + "advanced": false, + "dynamic": false, + "info": "", + "type": "str", + "list": false + }, + "validate_template": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "value": true, + "password": false, + "name": "validate_template", + "advanced": false, + "dynamic": false, + "info": "", + "type": "bool", + "list": false + }, + "_type": "PromptTemplate", + "input": { + "required": false, + "placeholder": "", + "show": true, + "multiline": true, + "value": "", + "password": false, + "name": "input", + "display_name": "input", + "advanced": false, + "input_types": [ + "Document", + "BaseOutputParser", + "str" + ], + "dynamic": false, + "info": "", + "type": "str", + "list": false + } + }, + "description": "A prompt template for a language model.", + "base_classes": [ + "BasePromptTemplate", + "StringPromptTemplate", + "PromptTemplate" + ], + "name": "", + "display_name": "PromptTemplate", + "documentation": "https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/", + "custom_fields": { + "": [ + "input" + ], + "template": [ + "input" + ] + }, + "output_types": [], + "field_formatters": { + "formatters": { + "openai_api_key": {} + }, + "base_formatters": { + "kwargs": {}, + "optional": {}, + "list": {}, + "dict": {}, + "union": {}, + "multiline": {}, + "show": {}, + "password": {}, + "default": {}, + "headers": {}, + "dict_code_file": {}, + "model_fields": { + "MODEL_DICT": { + "OpenAI": [ + "text-davinci-003", + "text-davinci-002", + "text-curie-001", + "text-babbage-001", + "text-ada-001" + ], + "ChatOpenAI": [ + "gpt-3.5-turbo-0613", + "gpt-3.5-turbo", + "gpt-3.5-turbo-16k-0613", + "gpt-3.5-turbo-16k", + "gpt-4-0613", + "gpt-4-32k-0613", + "gpt-4", + "gpt-4-32k" + ], + "Anthropic": [ + "claude-v1", + "claude-v1-100k", + "claude-instant-v1", + "claude-instant-v1-100k", + "claude-v1.3", + "claude-v1.3-100k", + "claude-v1.2", + "claude-v1.0", + "claude-instant-v1.1", + "claude-instant-v1.1-100k", + "claude-instant-v1.0" + ], + "ChatAnthropic": [ + "claude-v1", + "claude-v1-100k", + "claude-instant-v1", + "claude-instant-v1-100k", + "claude-v1.3", + "claude-v1.3-100k", + "claude-v1.2", + "claude-v1.0", + "claude-instant-v1.1", + "claude-instant-v1.1-100k", + "claude-instant-v1.0" + ] + } + } + } + }, + "beta": false, + "error": null + }, + "id": "PromptTemplate-CweKz" + }, + "selected": false, + "positionAbsolute": { + "x": 969.6448076246203, + "y": 528.7788853763968 + } + }, + { + "width": 384, + "height": 307, + "id": "LLMChain-HUM6g", + "type": "genericNode", + "position": { + "x": 1515.3241458756393, + "y": 732.4536491407735 + }, + "data": { + "type": "LLMChain", + "node": { + "template": { + "callbacks": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "callbacks", + "advanced": false, + "dynamic": false, + "info": "", + "type": "langchain.callbacks.base.BaseCallbackHandler", + "list": true + }, + "llm": { + "required": true, + "placeholder": "", + "show": true, + "multiline": false, + "password": false, + "name": "llm", + "advanced": false, + "dynamic": false, + "info": "", + "type": "BaseLanguageModel", + "list": false + }, + "memory": { + "required": false, + "placeholder": "", + "show": true, + "multiline": false, + "password": false, + "name": "memory", + "advanced": false, + "dynamic": false, + "info": "", + "type": "BaseMemory", + "list": false + }, + "output_parser": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "output_parser", + "advanced": false, + "dynamic": false, + "info": "", + "type": "BaseLLMOutputParser", + "list": false + }, + "prompt": { + "required": true, + "placeholder": "", + "show": true, + "multiline": false, + "password": false, + "name": "prompt", + "advanced": false, + "dynamic": false, + "info": "", + "type": "BasePromptTemplate", + "list": false + }, + "llm_kwargs": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "llm_kwargs", + "advanced": false, + "dynamic": false, + "info": "", + "type": "code", + "list": false + }, + "metadata": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "metadata", + "advanced": false, + "dynamic": false, + "info": "", + "type": "code", + "list": false + }, + "output_key": { + "required": true, + "placeholder": "", + "show": true, + "multiline": false, + "value": "text", + "password": false, + "name": "output_key", + "advanced": true, + "dynamic": false, + "info": "", + "type": "str", + "list": false + }, + "return_final_only": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "value": true, + "password": false, + "name": "return_final_only", + "advanced": false, + "dynamic": false, + "info": "", + "type": "bool", + "list": false + }, + "tags": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "tags", + "advanced": false, + "dynamic": false, + "info": "", + "type": "str", + "list": true + }, + "verbose": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "value": false, + "password": false, + "name": "verbose", + "advanced": true, + "dynamic": false, + "info": "", + "type": "bool", + "list": false + }, + "_type": "LLMChain" + }, + "description": "Chain to run queries against LLMs.", + "base_classes": [ + "LLMChain", + "Chain", + "function", + "Text" + ], + "display_name": "LLMChain", + "custom_fields": {}, + "output_types": [], + "documentation": "https://python.langchain.com/docs/modules/chains/foundational/llm_chain", + "beta": false, + "error": null + }, + "id": "LLMChain-HUM6g" + }, + "selected": false, + "positionAbsolute": { + "x": 1515.3241458756393, + "y": 732.4536491407735 + }, + "dragging": false + }, + { + "width": 384, + "height": 621, + "id": "ChatOpenAI-02kOF", + "type": "genericNode", + "position": { + "x": 483, + "y": 942.8665628296949 + }, + "data": { + "type": "ChatOpenAI", + "node": { + "template": { + "callbacks": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "callbacks", + "advanced": false, + "dynamic": false, + "info": "", + "type": "langchain.callbacks.base.BaseCallbackHandler", + "list": true + }, + "cache": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "cache", + "advanced": false, + "dynamic": false, + "info": "", + "type": "bool", + "list": false + }, + "client": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "client", + "advanced": false, + "dynamic": false, + "info": "", + "type": "Any", + "list": false + }, + "max_retries": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "value": 6, + "password": false, + "name": "max_retries", + "advanced": false, + "dynamic": false, + "info": "", + "type": "int", + "list": false + }, + "max_tokens": { + "required": false, + "placeholder": "", + "show": true, + "multiline": false, + "password": true, + "name": "max_tokens", + "advanced": false, + "dynamic": false, + "info": "", + "type": "int", + "list": false, + "value": "" + }, + "metadata": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "metadata", + "advanced": false, + "dynamic": false, + "info": "", + "type": "code", + "list": false + }, + "model_kwargs": { + "required": false, + "placeholder": "", + "show": true, + "multiline": false, + "password": false, + "name": "model_kwargs", + "advanced": true, + "dynamic": false, + "info": "", + "type": "code", + "list": false + }, + "model_name": { + "required": false, + "placeholder": "", + "show": true, + "multiline": false, + "value": "gpt-3.5-turbo-0613", + "password": false, + "options": [ + "gpt-3.5-turbo-0613", + "gpt-3.5-turbo", + "gpt-3.5-turbo-16k-0613", + "gpt-3.5-turbo-16k", + "gpt-4-0613", + "gpt-4-32k-0613", + "gpt-4", + "gpt-4-32k" + ], + "name": "model_name", + "advanced": false, + "dynamic": false, + "info": "", + "type": "str", + "list": true + }, + "n": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "value": 1, + "password": false, + "name": "n", + "advanced": false, + "dynamic": false, + "info": "", + "type": "int", + "list": false + }, + "openai_api_base": { + "required": false, + "placeholder": "", + "show": true, + "multiline": false, + "password": false, + "name": "openai_api_base", + "display_name": "OpenAI API Base", + "advanced": false, + "dynamic": false, + "info": "\nThe base URL of the OpenAI API. Defaults to https://api.openai.com/v1.\n\nYou can change this to use other APIs like JinaChat, LocalAI and Prem.\n", + "type": "str", + "list": false + }, + "openai_api_key": { + "required": false, + "placeholder": "", + "show": true, + "multiline": false, + "value": "", + "password": true, + "name": "openai_api_key", + "display_name": "OpenAI API Key", + "advanced": false, + "dynamic": false, + "info": "", + "type": "str", + "list": false + }, + "openai_organization": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "openai_organization", + "display_name": "OpenAI Organization", + "advanced": false, + "dynamic": false, + "info": "", + "type": "str", + "list": false + }, + "openai_proxy": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "openai_proxy", + "display_name": "OpenAI Proxy", + "advanced": false, + "dynamic": false, + "info": "", + "type": "str", + "list": false + }, + "request_timeout": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "request_timeout", + "advanced": false, + "dynamic": false, + "info": "", + "type": "float", + "list": false + }, + "streaming": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "value": false, + "password": false, + "name": "streaming", + "advanced": false, + "dynamic": false, + "info": "", + "type": "bool", + "list": false + }, + "tags": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "tags", + "advanced": false, + "dynamic": false, + "info": "", + "type": "str", + "list": true + }, + "temperature": { + "required": false, + "placeholder": "", + "show": true, + "multiline": false, + "value": 0.7, + "password": false, + "name": "temperature", + "advanced": false, + "dynamic": false, + "info": "", + "type": "float", + "list": false + }, + "tiktoken_model_name": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "tiktoken_model_name", + "advanced": false, + "dynamic": false, + "info": "", + "type": "str", + "list": false + }, + "verbose": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "value": false, + "password": false, + "name": "verbose", + "advanced": false, + "dynamic": false, + "info": "", + "type": "bool", + "list": false + }, + "_type": "ChatOpenAI" + }, + "description": "`OpenAI` Chat large language models API.", + "base_classes": [ + "ChatOpenAI", + "BaseLanguageModel", + "BaseChatModel", + "BaseLLM" + ], + "display_name": "ChatOpenAI", + "custom_fields": {}, + "output_types": [], + "documentation": "https://python.langchain.com/docs/modules/model_io/models/chat/integrations/openai", + "beta": false, + "error": null + }, + "id": "ChatOpenAI-02kOF" + }, + "selected": false, + "positionAbsolute": { + "x": 483, + "y": 942.8665628296949 + } + }, + { + "width": 384, + "height": 389, + "id": "ChatOutput-8SWFf", + "type": "genericNode", + "position": { + "x": 2035.5749798606498, + "y": 651.0174452514373 + }, + "data": { + "type": "ChatOutput", + "node": { + "template": { + "code": { + "dynamic": true, + "required": true, + "placeholder": "", + "show": true, + "multiline": true, + "value": "from typing import Optional\nfrom langflow.api.v1.schemas import ChatMessage\nfrom langflow.services.utils import get_chat_manager\nfrom langflow.custom import CustomComponent\nfrom anyio.from_thread import start_blocking_portal\nfrom loguru import logger\nfrom langflow.field_typing import Text\n\n\nclass ChatOutput(CustomComponent):\n display_name = \"Chat Output\"\n\n def build_config(self):\n return {\"message\": {\"input_types\": [\"str\"]}}\n\n def build(self, message: Optional[Text], is_ai: bool = False) -> Text:\n if not message:\n return \"\"\n try:\n chat_manager = get_chat_manager()\n chat_message = ChatMessage(message=message, is_bot=is_ai)\n # send_message is a coroutine\n # run in a thread safe manner\n with start_blocking_portal() as portal:\n portal.call(chat_manager.send_message, chat_message)\n chat_manager.chat_history.add_message(\n chat_manager.cache_manager.current_client_id, chat_message\n )\n except Exception as exc:\n logger.exception(exc)\n logger.debug(f\"Error sending message to chat: {exc}\")\n\n return message\n", + "password": false, + "name": "code", + "advanced": false, + "type": "code", + "list": false + }, + "_type": "CustomComponent", + "is_ai": { + "required": true, + "placeholder": "", + "show": true, + "multiline": false, + "value": false, + "password": false, + "name": "is_ai", + "display_name": "is_ai", + "advanced": false, + "dynamic": false, + "info": "", + "type": "bool", + "list": false + }, + "message": { + "required": false, + "placeholder": "", + "show": true, + "multiline": false, + "password": false, + "name": "message", + "display_name": "message", + "advanced": false, + "input_types": [ + "Text" + ], + "dynamic": false, + "info": "", + "type": "Text", + "list": false + } + }, + "description": "Used to send a message to the chat.", + "base_classes": [ + "str" + ], + "display_name": "Chat Output", + "custom_fields": { + "is_ai": null, + "message": null + }, + "output_types": [ + "ChatOutput" + ], + "documentation": "", + "beta": true, + "error": null + }, + "id": "ChatOutput-8SWFf" + }, + "selected": false, + "positionAbsolute": { + "x": 2035.5749798606498, + "y": 651.0174452514373 + } + }, + { + "width": 384, + "height": 273, + "id": "ChatInput-PqtHe", + "type": "genericNode", + "position": { + "x": 504.7467002897712, + "y": 388.46875 + }, + "data": { + "type": "ChatInput", + "node": { + "template": { + "code": { + "dynamic": true, + "required": true, + "placeholder": "", + "show": false, + "multiline": true, + "value": "from typing import Optional\nfrom langflow.custom import CustomComponent\n\n\nclass ChatInput(CustomComponent):\n display_name = \"Chat Input\"\n\n def build(self, message: Optional[str] = \"\") -> str:\n return message\n", + "password": false, + "name": "code", + "advanced": false, + "type": "code", + "list": false + }, + "_type": "CustomComponent", + "message": { + "required": false, + "placeholder": "", + "show": true, + "multiline": false, + "value": "", + "password": false, + "name": "message", + "display_name": "message", + "advanced": false, + "dynamic": false, + "info": "", + "type": "str", + "list": false + } + }, + "description": "Used to get user input from the chat.", + "base_classes": [ + "str" + ], + "display_name": "Chat Input", + "custom_fields": { + "message": null + }, + "output_types": [ + "ChatInput" + ], + "documentation": "", + "beta": true, + "error": null + }, + "id": "ChatInput-PqtHe" + }, + "selected": false, + "positionAbsolute": { + "x": 504.7467002897712, + "y": 388.46875 + } + }, + { + "width": 384, + "height": 475, + "id": "Tool-jyI4N", + "type": "genericNode", + "position": { + "x": 2044.485030617051, + "y": 1131.4250055845532 + }, + "data": { + "type": "Tool", + "node": { + "template": { + "func": { + "required": true, + "placeholder": "", + "show": true, + "multiline": true, + "password": false, + "name": "func", + "advanced": false, + "dynamic": false, + "info": "", + "type": "function", + "list": false + }, + "description": { + "required": true, + "placeholder": "", + "show": true, + "multiline": true, + "value": "Test tool", + "password": false, + "name": "description", + "advanced": false, + "dynamic": false, + "info": "", + "type": "str", + "list": false + }, + "name": { + "required": true, + "placeholder": "", + "show": true, + "multiline": true, + "value": "Tool", + "password": false, + "name": "name", + "advanced": false, + "dynamic": false, + "info": "", + "type": "str", + "list": false + }, + "return_direct": { + "required": true, + "placeholder": "", + "show": true, + "multiline": false, + "value": false, + "password": false, + "name": "return_direct", + "advanced": false, + "dynamic": false, + "info": "", + "type": "bool", + "list": false + }, + "_type": "Tool" + }, + "description": "Converts a chain, agent or function into a tool.", + "base_classes": [ + "Tool", + "BaseTool" + ], + "display_name": "Tool", + "custom_fields": {}, + "output_types": [], + "documentation": "", + "beta": false, + "error": null + }, + "id": "Tool-jyI4N" + }, + "selected": true, + "positionAbsolute": { + "x": 2044.485030617051, + "y": 1131.4250055845532 + }, + "dragging": false + } + ], + "edges": [ + { + "source": "PromptTemplate-CweKz", + "target": "LLMChain-HUM6g", + "sourceHandle": "PromptTemplate|PromptTemplate-CweKz|BasePromptTemplate|StringPromptTemplate|PromptTemplate", + "targetHandle": "BasePromptTemplate|prompt|LLMChain-HUM6g", + "id": "reactflow__edge-PromptTemplate-CweKzPromptTemplate|PromptTemplate-CweKz|BasePromptTemplate|StringPromptTemplate|PromptTemplate-LLMChain-HUM6gBasePromptTemplate|prompt|LLMChain-HUM6g", + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 ", + "animated": false, + "selected": false + }, + { + "source": "ChatOpenAI-02kOF", + "target": "LLMChain-HUM6g", + "sourceHandle": "ChatOpenAI|ChatOpenAI-02kOF|ChatOpenAI|BaseLanguageModel|BaseChatModel|BaseLLM", + "targetHandle": "BaseLanguageModel|llm|LLMChain-HUM6g", + "id": "reactflow__edge-ChatOpenAI-02kOFChatOpenAI|ChatOpenAI-02kOF|ChatOpenAI|BaseLanguageModel|BaseChatModel|BaseLLM-LLMChain-HUM6gBaseLanguageModel|llm|LLMChain-HUM6g", + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 ", + "animated": false, + "selected": false + }, + { + "source": "ChatInput-PqtHe", + "target": "PromptTemplate-CweKz", + "sourceHandle": "ChatInput|ChatInput-PqtHe|str", + "targetHandle": "Document;BaseOutputParser;str|input|PromptTemplate-CweKz", + "id": "reactflow__edge-ChatInput-PqtHeChatInput|ChatInput-PqtHe|str-PromptTemplate-CweKzDocument;BaseOutputParser;str|input|PromptTemplate-CweKz", + "style": { + "stroke": "#555" + }, + "className": "stroke-gray-900 ", + "animated": false, + "selected": false + }, + { + "source": "LLMChain-HUM6g", + "sourceHandle": "LLMChain|LLMChain-HUM6g|LLMChain|Chain|function|Text", + "target": "ChatOutput-8SWFf", + "targetHandle": "Text|message|ChatOutput-8SWFf", + "style": { + "stroke": "#555" + }, + "className": "stroke-foreground stroke-connection", + "animated": true, + "id": "reactflow__edge-LLMChain-HUM6gLLMChain|LLMChain-HUM6g|LLMChain|Chain|function|Text-ChatOutput-8SWFfText|message|ChatOutput-8SWFf" + }, + { + "source": "LLMChain-HUM6g", + "sourceHandle": "LLMChain|LLMChain-HUM6g|LLMChain|Chain|function|Text", + "target": "Tool-jyI4N", + "targetHandle": "function|func|Tool-jyI4N", + "style": { + "stroke": "#555" + }, + "className": "stroke-foreground stroke-connection", + "animated": false, + "id": "reactflow__edge-LLMChain-HUM6gLLMChain|LLMChain-HUM6g|LLMChain|Chain|function|Text-Tool-jyI4Nfunction|func|Tool-jyI4N" + } + ], + "viewport": { + "x": -401.32668426335044, + "y": -129.59138346130635, + "zoom": 0.5073779796520557 + } + }, + "id": "cf923ccb-e14c-4754-96eb-a8a3b5bbe082", + "user_id": "c65bfea3-3eea-4e71-8fc4-106238eb0583" +} \ No newline at end of file diff --git a/tests/data/component.py b/tests/data/component.py index e801d2feb..5de63fcd5 100644 --- a/tests/data/component.py +++ b/tests/data/component.py @@ -1,6 +1,6 @@ import random -from langflow import CustomComponent +from langflow.custom import CustomComponent class TestComponent(CustomComponent): diff --git a/tests/data/component_with_templatefield.py b/tests/data/component_with_templatefield.py index 6b2ce011b..26d7e834b 100644 --- a/tests/data/component_with_templatefield.py +++ b/tests/data/component_with_templatefield.py @@ -1,6 +1,6 @@ import random -from langflow import CustomComponent +from langflow.custom import CustomComponent from langflow.field_typing import TemplateField diff --git a/tests/test_api_key.py b/tests/test_api_key.py index 7988793d4..31f484d60 100644 --- a/tests/test_api_key.py +++ b/tests/test_api_key.py @@ -1,4 +1,5 @@ import pytest + from langflow.services.database.models.api_key import ApiKeyCreate @@ -21,7 +22,6 @@ def test_get_api_keys(client, logged_in_headers, api_key): assert any("test-api-key" in api_key["name"] for api_key in data["api_keys"]) # assert all api keys in data["api_keys"] are masked assert all("**" in api_key["api_key"] for api_key in data["api_keys"]) - # Add more assertions as needed based on the expected data structure and content def test_create_api_key(client, logged_in_headers): diff --git a/tests/test_cache.py b/tests/test_cache.py index 8cfebe230..6d4911efd 100644 --- a/tests/test_cache.py +++ b/tests/test_cache.py @@ -39,7 +39,8 @@ def langchain_objects_are_equal(obj1, obj2): # Test build_graph -def test_build_graph(client, basic_data_graph): +@pytest.mark.asyncio +async def test_build_graph(client, basic_data_graph): graph = Graph.from_payload(basic_data_graph) assert graph is not None assert len(graph.vertices) == len(basic_data_graph["nodes"]) diff --git a/tests/test_cli.py b/tests/test_cli.py index ee95a271c..60595f48a 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -17,6 +17,7 @@ def default_settings(): def test_components_path(runner, client, default_settings): # Create a foldr in the tmp directory + temp_dir = Path(tempdir) # create a "components" folder temp_dir = temp_dir / "components" @@ -34,5 +35,4 @@ def test_components_path(runner, client, default_settings): def test_superuser(runner, client, session): result = runner.invoke(app, ["superuser"], input="admin\nadmin\n") assert result.exit_code == 0, result.stdout - assert "Superuser creation failed." not in result.output, result.output - assert "Superuser created successfully." in result.output, result.output + assert "Superuser created successfully." in result.stdout diff --git a/tests/test_custom_component.py b/tests/test_custom_component.py index 1b85c9198..725d35564 100644 --- a/tests/test_custom_component.py +++ b/tests/test_custom_component.py @@ -3,14 +3,21 @@ import types from uuid import uuid4 import pytest +from langchain_core.documents import Document + from langflow.interface.custom.base import CustomComponent -from langflow.interface.custom.code_parser.code_parser import CodeParser, CodeSyntaxError -from langflow.interface.custom.custom_component.component import Component, ComponentCodeNullError -from langflow.interface.custom.utils import build_custom_component_template +from langflow.interface.custom.code_parser.code_parser import ( + CodeParser, + CodeSyntaxError, +) +from langflow.interface.custom.custom_component.component import ( + Component, + ComponentCodeNullError, +) from langflow.services.database.models.flow import Flow, FlowCreate code_default = """ -from langflow import Prompt +from langflow.field_typing import Prompt from langflow.interface.custom.custom_component import CustomComponent from langchain.llms.base import BaseLLM @@ -67,16 +74,16 @@ def test_component_init(): """ Test the initialization of the Component class. """ - component = Component(code=code_default, _function_entrypoint_name="build") + component = Component(code=code_default, function_entrypoint_name="build") assert component.code == code_default - assert component._function_entrypoint_name == "build" + assert component.function_entrypoint_name == "build" def test_component_get_code_tree(): """ Test the get_code_tree method of the Component class. """ - component = Component(code=code_default, _function_entrypoint_name="build") + component = Component(code=code_default, function_entrypoint_name="build") tree = component.get_code_tree(component.code) assert "imports" in tree @@ -86,22 +93,11 @@ def test_component_code_null_error(): Test the get_function method raises the ComponentCodeNullError when the code is empty. """ - component = Component(code="", _function_entrypoint_name="") + component = Component(code="", function_entrypoint_name="") with pytest.raises(ComponentCodeNullError): component.get_function() -# TODO: Validate if we should remove this -# def test_component_function_entrypoint_name_null_error(): -# """ -# Test the get_function method raises the ComponentFunctionEntrypointNameNullError -# when the function_entrypoint_name is empty. -# """ -# component = Component(code=code_default, _function_entrypoint_name="") -# with pytest.raises(ComponentFunctionEntrypointNameNullError): -# component.get_function() - - def test_custom_component_init(): """ Test the initialization of the CustomComponent class. @@ -118,7 +114,7 @@ def test_custom_component_build_template_config(): Test the build_template_config property of the CustomComponent class. """ custom_component = CustomComponent(code=code_default, function_entrypoint_name="build") - config = custom_component.template_config + config = custom_component.build_template_config() assert isinstance(config, dict) @@ -127,7 +123,7 @@ def test_custom_component_get_function(): Test the get_function property of the CustomComponent class. """ custom_component = CustomComponent(code="def build(): pass", function_entrypoint_name="build") - my_function = custom_component.get_function + my_function = custom_component.get_function() assert isinstance(my_function, types.FunctionType) @@ -201,7 +197,7 @@ def test_component_get_function_valid(): Test the get_function method of the Component class with valid code and function_entrypoint_name. """ - component = Component(code="def build(): pass", _function_entrypoint_name="build") + component = Component(code="def build(): pass", function_entrypoint_name="build") my_function = component.get_function() assert callable(my_function) @@ -224,7 +220,6 @@ def test_custom_component_get_function_entrypoint_return_type(): Test the get_function_entrypoint_return_type property of the CustomComponent class. """ - from langchain_core.documents import Document custom_component = CustomComponent(code=code_default, function_entrypoint_name="build") return_type = custom_component.get_function_entrypoint_return_type @@ -309,7 +304,7 @@ def test_code_parser_parse_ann_assign(): stmt = ast.AnnAssign( target=ast.Name(id="x", ctx=ast.Store()), annotation=ast.Name(id="int", ctx=ast.Load()), - value=ast.Constant(n=1), + value=ast.Num(n=1), simple=1, ) result = parser.parse_ann_assign(stmt) @@ -359,11 +354,21 @@ def test_component_get_code_tree_syntax_error(): Test the get_code_tree method of the Component class raises the CodeSyntaxError when given incorrect syntax. """ - component = Component(code="import os as", _function_entrypoint_name="build") + component = Component(code="import os as", function_entrypoint_name="build") with pytest.raises(CodeSyntaxError): component.get_code_tree(component.code) +def test_custom_component_class_template_validation_no_code(): + """ + Test the _class_template_validation method of the CustomComponent class + raises the HTTPException when the code is None. + """ + custom_component = CustomComponent(code=None, function_entrypoint_name="build") + with pytest.raises(TypeError): + custom_component.get_function() + + def test_custom_component_get_code_tree_syntax_error(): """ Test the get_code_tree method of the CustomComponent class @@ -518,36 +523,3 @@ def test_build_config_field_value_keys(component): config = component.build_config() field_values = config["fields"].values() assert all("type" in value for value in field_values) - - -def test_create_and_validate_component_valid_code(test_component_code): - component = CustomComponent(code=test_component_code) - assert isinstance(component, CustomComponent) - - -def test_build_langchain_template_custom_component_valid_code(test_component_code): - component = CustomComponent(code=test_component_code) - frontend_node = build_custom_component_template(component) - assert isinstance(frontend_node, dict) - template = frontend_node["template"] - assert isinstance(template, dict) - assert "param" in template - param_options = template["param"]["options"] - # Now run it again with an update field - frontend_node = build_custom_component_template(component, update_field="param") - new_param_options = frontend_node["template"]["param"]["options"] - assert param_options != new_param_options - - -def test_build_langchain_template_custom_component_templatefield(test_component_with_templatefield_code): - component = CustomComponent(code=test_component_with_templatefield_code) - frontend_node = build_custom_component_template(component) - assert isinstance(frontend_node, dict) - template = frontend_node["template"] - assert isinstance(template, dict) - assert "param" in template - param_options = template["param"]["options"] - # Now run it again with an update field - frontend_node = build_custom_component_template(component, update_field="param") - new_param_options = frontend_node["template"]["param"]["options"] - assert param_options != new_param_options diff --git a/tests/test_custom_types.py b/tests/test_custom_types.py index ba54b7023..33c854ba3 100644 --- a/tests/test_custom_types.py +++ b/tests/test_custom_types.py @@ -1,7 +1,7 @@ # Test this: -from langflow.interface.importing.utils import get_function import pytest -from langflow.interface.tools.custom import PythonFunctionTool, PythonFunction +from langflow.interface.custom.utils import get_function +from langflow.interface.tools.custom import PythonFunction, PythonFunctionTool from langflow.utils import constants diff --git a/tests/test_data_components.py b/tests/test_data_components.py new file mode 100644 index 000000000..ca92ee190 --- /dev/null +++ b/tests/test_data_components.py @@ -0,0 +1,166 @@ +import os +from pathlib import Path +from unittest.mock import Mock, patch + +import httpx +import pytest +import respx +from httpx import Response + +from langflow.components import ( + data, +) # Adjust the import according to your project structure + + +@pytest.fixture +def api_request(): + # This fixture provides an instance of APIRequest for each test case + return data.APIRequest() + + +@pytest.mark.asyncio +@respx.mock +async def test_successful_get_request(api_request): + # Mocking a successful GET request + url = "https://example.com/api/test" + method = "GET" + mock_response = {"success": True} + respx.get(url).mock(return_value=Response(200, json=mock_response)) + + # Making the request + result = await api_request.make_request(client=httpx.AsyncClient(), method=method, url=url) + + # Assertions + assert result.data["status_code"] == 200 + assert result.data["result"] == mock_response + + +@pytest.mark.asyncio +@respx.mock +async def test_failed_request(api_request): + # Mocking a failed GET request + url = "https://example.com/api/test" + method = "GET" + respx.get(url).mock(return_value=Response(404)) + + # Making the request + result = await api_request.make_request(client=httpx.AsyncClient(), method=method, url=url) + + # Assertions + assert result.data["status_code"] == 404 + + +@pytest.mark.asyncio +@respx.mock +async def test_timeout(api_request): + # Mocking a timeout + url = "https://example.com/api/timeout" + method = "GET" + respx.get(url).mock(side_effect=httpx.TimeoutException(message="Timeout", request=None)) + + # Making the request + result = await api_request.make_request(client=httpx.AsyncClient(), method=method, url=url, timeout=1) + + # Assertions + assert result.data["status_code"] == 408 + assert result.data["error"] == "Request timed out" + + +@pytest.mark.asyncio +@respx.mock +async def test_build_with_multiple_urls(api_request): + # This test depends on having a working internet connection and accessible URLs + # It's better to mock these requests using respx or a similar library + + # Setup for multiple URLs + method = "GET" + urls = ["https://example.com/api/one", "https://example.com/api/two"] + # You would mock these requests similarly to the single request tests + for url in urls: + respx.get(url).mock(return_value=Response(200, json={"success": True})) + + # Do I have to mock the async client? + # + + # Execute the build method + results = await api_request.build(method=method, urls=urls) + + # Assertions + assert len(results) == len(urls) + + +@patch("langflow.components.data.Directory.parallel_load_records") +@patch("langflow.components.data.Directory.retrieve_file_paths") +@patch("langflow.components.data.DirectoryComponent.resolve_path") +def test_directory_component_build_with_multithreading( + mock_resolve_path, mock_retrieve_file_paths, mock_parallel_load_records +): + # Arrange + directory_component = data.DirectoryComponent() + path = os.path.dirname(os.path.abspath(__file__)) + depth = 1 + max_concurrency = 2 + load_hidden = False + recursive = True + silent_errors = False + use_multithreading = True + + mock_resolve_path.return_value = path + mock_retrieve_file_paths.return_value = [ + os.path.join(path, file) for file in os.listdir(path) if file.endswith(".py") + ] + mock_parallel_load_records.return_value = [Mock()] + + # Act + directory_component.build( + path, + depth, + max_concurrency, + load_hidden, + recursive, + silent_errors, + use_multithreading, + ) + + # Assert + mock_resolve_path.assert_called_once_with(path) + mock_retrieve_file_paths.assert_called_once_with(path, load_hidden, recursive, depth) + mock_parallel_load_records.assert_called_once_with( + mock_retrieve_file_paths.return_value, silent_errors, max_concurrency + ) + + +def test_directory_without_mocks(): + directory_component = data.DirectoryComponent() + from langflow.initial_setup import setup + from langflow.initial_setup.setup import load_starter_projects + + projects = load_starter_projects() + # the setup module has a folder where the projects are stored + # the contents of that folder are in the projects variable + # the directory component can be used to load the projects + # and we can validate if the contents are the same as the projects variable + setup_path = Path(setup.__file__).parent / "starter_projects" + results = directory_component.build(str(setup_path), use_multithreading=False) + assert len(results) == len(projects) + # each result is a Record that contains the content attribute + # each are dict that are exactly the same as one of the projects + for result in results: + assert result.text in projects + + # in ../docs/docs/components there are many mdx files + # check if the directory component can load them + # just check if the number of results is the same as the number of files + docs_path = Path(__file__).parent.parent / "docs" / "docs" / "components" + results = directory_component.build(str(docs_path), use_multithreading=False) + docs_files = list(docs_path.glob("*.mdx")) + assert len(results) == len(docs_files) + + +def test_url_component(): + url_component = data.URLComponent() + # the url component can be used to load the contents of a website + records = url_component.build(["https://langflow.org"]) + assert all(record.data for record in records) + assert all(record.text for record in records) + assert all(record.source for record in records) diff --git a/tests/test_database.py b/tests/test_database.py index f52252856..554a1fc4f 100644 --- a/tests/test_database.py +++ b/tests/test_database.py @@ -3,12 +3,14 @@ from uuid import UUID, uuid4 import orjson import pytest from fastapi.testclient import TestClient +from sqlmodel import Session + from langflow.api.v1.schemas import FlowListCreate +from langflow.initial_setup.setup import load_starter_projects from langflow.services.database.models.base import orjson_dumps from langflow.services.database.models.flow import Flow, FlowCreate, FlowUpdate from langflow.services.database.utils import session_getter from langflow.services.deps import get_db_service -from sqlmodel import Session @pytest.fixture(scope="module") @@ -29,13 +31,13 @@ def test_create_flow(client: TestClient, json_flow: str, active_user, logged_in_ flow = orjson.loads(json_flow) data = flow["data"] flow = FlowCreate(name="Test Flow", description="description", data=data) - response = client.post("api/v1/flows/", json=flow.model_dump(), headers=logged_in_headers) + response = client.post("api/v1/flows/", json=flow.dict(), headers=logged_in_headers) assert response.status_code == 201 assert response.json()["name"] == flow.name assert response.json()["data"] == flow.data # flow is optional so we can create a flow without a flow - flow = FlowCreate(name="Test Flow", description="description") - response = client.post("api/v1/flows/", json=flow.model_dump(exclude_unset=True), headers=logged_in_headers) + flow = FlowCreate(name="Test Flow") + response = client.post("api/v1/flows/", json=flow.dict(exclude_unset=True), headers=logged_in_headers) assert response.status_code == 201 assert response.json()["name"] == flow.name assert response.json()["data"] == flow.data @@ -45,13 +47,13 @@ def test_read_flows(client: TestClient, json_flow: str, active_user, logged_in_h flow_data = orjson.loads(json_flow) data = flow_data["data"] flow = FlowCreate(name="Test Flow", description="description", data=data) - response = client.post("api/v1/flows/", json=flow.model_dump(), headers=logged_in_headers) + response = client.post("api/v1/flows/", json=flow.dict(), headers=logged_in_headers) assert response.status_code == 201 assert response.json()["name"] == flow.name assert response.json()["data"] == flow.data flow = FlowCreate(name="Test Flow", description="description", data=data) - response = client.post("api/v1/flows/", json=flow.model_dump(), headers=logged_in_headers) + response = client.post("api/v1/flows/", json=flow.dict(), headers=logged_in_headers) assert response.status_code == 201 assert response.json()["name"] == flow.name assert response.json()["data"] == flow.data @@ -65,7 +67,7 @@ def test_read_flow(client: TestClient, json_flow: str, active_user, logged_in_he flow = orjson.loads(json_flow) data = flow["data"] flow = FlowCreate(name="Test Flow", description="description", data=data) - response = client.post("api/v1/flows/", json=flow.model_dump(), headers=logged_in_headers) + response = client.post("api/v1/flows/", json=flow.dict(), headers=logged_in_headers) flow_id = response.json()["id"] # flow_id should be a UUID but is a string # turn it into a UUID flow_id = UUID(flow_id) @@ -81,7 +83,7 @@ def test_update_flow(client: TestClient, json_flow: str, active_user, logged_in_ data = flow["data"] flow = FlowCreate(name="Test Flow", description="description", data=data) - response = client.post("api/v1/flows/", json=flow.model_dump(), headers=logged_in_headers) + response = client.post("api/v1/flows/", json=flow.dict(), headers=logged_in_headers) flow_id = response.json()["id"] updated_flow = FlowUpdate( @@ -89,7 +91,7 @@ def test_update_flow(client: TestClient, json_flow: str, active_user, logged_in_ description="updated description", data=data, ) - response = client.patch(f"api/v1/flows/{flow_id}", json=updated_flow.model_dump(), headers=logged_in_headers) + response = client.patch(f"api/v1/flows/{flow_id}", json=updated_flow.dict(), headers=logged_in_headers) assert response.status_code == 200 assert response.json()["name"] == updated_flow.name @@ -101,7 +103,7 @@ def test_delete_flow(client: TestClient, json_flow: str, active_user, logged_in_ flow = orjson.loads(json_flow) data = flow["data"] flow = FlowCreate(name="Test Flow", description="description", data=data) - response = client.post("api/v1/flows/", json=flow.model_dump(), headers=logged_in_headers) + response = client.post("api/v1/flows/", json=flow.dict(), headers=logged_in_headers) flow_id = response.json()["id"] response = client.delete(f"api/v1/flows/{flow_id}", headers=logged_in_headers) assert response.status_code == 200 @@ -119,7 +121,7 @@ def test_create_flows(client: TestClient, session: Session, json_flow: str, logg ] ) # Make request to endpoint - response = client.post("api/v1/flows/batch/", json=flow_list.model_dump(), headers=logged_in_headers) + response = client.post("api/v1/flows/batch/", json=flow_list.dict(), headers=logged_in_headers) # Check response status code assert response.status_code == 201 # Check response data @@ -143,7 +145,7 @@ def test_upload_file(client: TestClient, session: Session, json_flow: str, logge FlowCreate(name="Flow 2", description="description", data=data), ] ) - file_contents = orjson_dumps(flow_list.model_dump()) + file_contents = orjson_dumps(flow_list.dict()) response = client.post( "api/v1/flows/upload/", files={"file": ("examples.json", file_contents, "application/json")}, @@ -191,7 +193,9 @@ def test_download_file( assert response.status_code == 200, response.json() # Check response data response_data = response.json()["flows"] - assert len(response_data) == 2, response_data + starter_projects = load_starter_projects() + number_of_projects = len(starter_projects) + len(flow_list.flows) + assert len(response_data) == number_of_projects, response_data assert response_data[0]["name"] == "Flow 1" assert response_data[0]["description"] == "description" assert response_data[0]["data"] == data @@ -216,11 +220,11 @@ def test_update_flow_idempotency(client: TestClient, json_flow: str, active_user flow_data = orjson.loads(json_flow) data = flow_data["data"] flow_data = FlowCreate(name="Test Flow", description="description", data=data) - response = client.post("api/v1/flows/", json=flow_data.model_dump(), headers=logged_in_headers) + response = client.post("api/v1/flows/", json=flow_data.dict(), headers=logged_in_headers) flow_id = response.json()["id"] updated_flow = FlowCreate(name="Updated Flow", description="description", data=data) - response1 = client.put(f"api/v1/flows/{flow_id}", json=updated_flow.model_dump(), headers=logged_in_headers) - response2 = client.put(f"api/v1/flows/{flow_id}", json=updated_flow.model_dump(), headers=logged_in_headers) + response1 = client.put(f"api/v1/flows/{flow_id}", json=updated_flow.dict(), headers=logged_in_headers) + response2 = client.put(f"api/v1/flows/{flow_id}", json=updated_flow.dict(), headers=logged_in_headers) assert response1.json() == response2.json() @@ -233,7 +237,7 @@ def test_update_nonexistent_flow(client: TestClient, json_flow: str, active_user description="description", data=data, ) - response = client.patch(f"api/v1/flows/{uuid}", json=updated_flow.model_dump(), headers=logged_in_headers) + response = client.patch(f"api/v1/flows/{uuid}", json=updated_flow.dict(), headers=logged_in_headers) assert response.status_code == 404 @@ -243,7 +247,8 @@ def test_delete_nonexistent_flow(client: TestClient, active_user, logged_in_head assert response.status_code == 404 -def test_read_empty_flows(client: TestClient, active_user, logged_in_headers): +def test_read_only_starter_projects(client: TestClient, active_user, logged_in_headers): response = client.get("api/v1/flows/", headers=logged_in_headers) + starter_projects = load_starter_projects() assert response.status_code == 200 - assert len(response.json()) == 0 + assert len(response.json()) == len(starter_projects) diff --git a/tests/test_embeddings_template.py b/tests/test_embeddings_template.py deleted file mode 100644 index 7334c2abd..000000000 --- a/tests/test_embeddings_template.py +++ /dev/null @@ -1,59 +0,0 @@ -from langflow.template.field.base import TemplateField -from langflow.template.frontend_node.embeddings import EmbeddingFrontendNode - - -def test_format_jina_fields(): - field = TemplateField(name="jina") - EmbeddingFrontendNode.format_jina_fields(field) - assert field.show is True - assert field.advanced is False - - field = TemplateField(name="auth") - EmbeddingFrontendNode.format_jina_fields(field) - assert field.password is True - assert field.show is True - assert field.advanced is False - - field = TemplateField(name="jina_api_url") - EmbeddingFrontendNode.format_jina_fields(field) - assert field.show is True - assert field.advanced is True - assert field.display_name == "Jina API URL" - assert field.password is False - - -def test_format_openai_fields(): - field = TemplateField(name="openai") - EmbeddingFrontendNode.format_openai_fields(field) - assert field.show is True - assert field.advanced is True - assert field.display_name == "OpenAI" - - field = TemplateField(name="openai_api_key") - EmbeddingFrontendNode.format_openai_fields(field) - assert field.password is True - assert field.show is True - assert field.advanced is False - - -def test_format_field(): - field = TemplateField(name="headers") - EmbeddingFrontendNode.format_field(field) - assert field.show is False - - field = TemplateField(name="jina") - EmbeddingFrontendNode.format_field(field) - assert field.advanced is False - assert field.show is True - - field = TemplateField(name="openai") - EmbeddingFrontendNode.format_field(field) - assert field.advanced is True - assert field.show is True - assert field.display_name == "OpenAI" - - field = TemplateField(name="test_field", required=True) - EmbeddingFrontendNode.format_field(field) - assert field.advanced is False - assert field.show is True - assert field.required is True diff --git a/tests/test_endpoints.py b/tests/test_endpoints.py index 2d8f41597..1430682ae 100644 --- a/tests/test_endpoints.py +++ b/tests/test_endpoints.py @@ -1,16 +1,11 @@ import time -import uuid -from collections import namedtuple +from uuid import uuid4 import pytest +from fastapi import status from fastapi.testclient import TestClient - -from langflow.interface.tools.constants import CUSTOM_TOOLS -from langflow.processing.process import Result -from langflow.services.auth.utils import get_password_hash -from langflow.services.database.models.api_key.model import ApiKey -from langflow.services.database.utils import session_getter -from langflow.services.deps import get_db_service, get_settings_service +from langflow.interface.custom.directory_reader.directory_reader import DirectoryReader +from langflow.services.deps import get_settings_service from langflow.template.frontend_node.chains import TimeTravelGuideChainNode @@ -25,7 +20,7 @@ def run_post(client, flow_id, headers, post_data): # Helper function to poll task status -def poll_task_status(client, headers, href, max_attempts=20, sleep_time=2): +def poll_task_status(client, headers, href, max_attempts=20, sleep_time=1): for _ in range(max_attempts): task_status_response = client.get( href, @@ -114,184 +109,171 @@ PROMPT_REQUEST = { } -@pytest.fixture -def created_api_key(active_user): - hashed = get_password_hash("random_key") - api_key = ApiKey( - name="test_api_key", - user_id=active_user.id, - api_key="random_key", - hashed_api_key=hashed, - ) - db_manager = get_db_service() - with session_getter(db_manager) as session: - if existing_api_key := session.query(ApiKey).filter(ApiKey.api_key == api_key.api_key).first(): - return existing_api_key - session.add(api_key) - session.commit() - session.refresh(api_key) - return api_key +# def test_process_flow_invalid_api_key(client, flow, monkeypatch): +# # Mock de process_graph_cached +# from langflow.api.v1 import endpoints +# from langflow.services.database.models.api_key import crud + +# settings_service = get_settings_service() +# settings_service.auth_settings.AUTO_LOGIN = False + +# async def mock_process_graph_cached(*args, **kwargs): +# return Result(result={}, session_id="session_id_mock") + +# def mock_update_total_uses(*args, **kwargs): +# return created_api_key + +# monkeypatch.setattr(endpoints, "process_graph_cached", mock_process_graph_cached) +# monkeypatch.setattr(crud, "update_total_uses", mock_update_total_uses) + +# headers = {"x-api-key": "invalid_api_key"} + +# post_data = { +# "inputs": {"key": "value"}, +# "tweaks": None, +# "clear_cache": False, +# "session_id": None, +# } + +# response = client.post(f"api/v1/process/{flow.id}", headers=headers, json=post_data) + +# assert response.status_code == 403 +# assert response.json() == {"detail": "Invalid or missing API key"} -def test_process_flow_invalid_api_key(client, flow, monkeypatch): - # Mock de process_graph_cached - from langflow.api.v1 import endpoints - from langflow.services.database.models.api_key import crud +# def test_process_flow_invalid_id(client, monkeypatch, created_api_key): +# async def mock_process_graph_cached(*args, **kwargs): +# return Result(result={}, session_id="session_id_mock") - settings_service = get_settings_service() - settings_service.auth_settings.AUTO_LOGIN = False +# from langflow.api.v1 import endpoints - async def mock_process_graph_cached(*args, **kwargs): - return Result(result={}, session_id="session_id_mock") +# monkeypatch.setattr(endpoints, "process_graph_cached", mock_process_graph_cached) - def mock_update_total_uses(*args, **kwargs): - return created_api_key +# api_key = created_api_key.api_key +# headers = {"x-api-key": api_key} - monkeypatch.setattr(endpoints, "process_graph_cached", mock_process_graph_cached) - monkeypatch.setattr(crud, "update_total_uses", mock_update_total_uses) +# post_data = { +# "inputs": {"key": "value"}, +# "tweaks": None, +# "clear_cache": False, +# "session_id": None, +# } - headers = {"x-api-key": "invalid_api_key"} +# invalid_id = uuid.uuid4() +# response = client.post(f"api/v1/process/{invalid_id}", headers=headers, json=post_data) - post_data = { - "inputs": {"key": "value"}, - "tweaks": None, - "clear_cache": False, - "session_id": None, - } - - response = client.post(f"api/v1/process/{flow.id}", headers=headers, json=post_data) - - assert response.status_code == 403 - assert response.json() == {"detail": "Invalid or missing API key"} +# assert response.status_code == 404 +# assert f"Flow {invalid_id} not found" in response.json()["detail"] -def test_process_flow_invalid_id(client, monkeypatch, created_api_key): - async def mock_process_graph_cached(*args, **kwargs): - return Result(result={}, session_id="session_id_mock") +# def test_process_flow_without_autologin(client, flow, monkeypatch, created_api_key): +# # Mock de process_graph_cached +# from langflow.api.v1 import endpoints +# from langflow.services.database.models.api_key import crud - from langflow.api.v1 import endpoints +# settings_service = get_settings_service() +# settings_service.auth_settings.AUTO_LOGIN = False - monkeypatch.setattr(endpoints, "process_graph_cached", mock_process_graph_cached) +# async def mock_process_graph_cached(*args, **kwargs): +# return Result(result={}, session_id="session_id_mock") - api_key = created_api_key.api_key - headers = {"x-api-key": api_key} +# def mock_process_graph_cached_task(*args, **kwargs): +# return Result(result={}, session_id="session_id_mock") - post_data = { - "inputs": {"key": "value"}, - "tweaks": None, - "clear_cache": False, - "session_id": None, - } +# # The task function is ran like this: +# # if not self.use_celery: +# # return None, await task_func(*args, **kwargs) +# # if not hasattr(task_func, "apply"): +# # raise ValueError(f"Task function {task_func} does not have an apply method") +# # task = task_func.apply(args=args, kwargs=kwargs) +# # result = task.get() +# # return task.id, result +# # So we need to mock the task function to return a task object +# # and then mock the task object to return a result +# # maybe a named tuple would be better here +# task = namedtuple("task", ["id", "get"]) +# mock_process_graph_cached_task.apply = lambda *args, **kwargs: task( +# id="task_id_mock", get=lambda: Result(result={}, session_id="session_id_mock") +# ) - invalid_id = uuid.uuid4() - response = client.post(f"api/v1/process/{invalid_id}", headers=headers, json=post_data) +# def mock_update_total_uses(*args, **kwargs): +# return created_api_key - assert response.status_code == 404 - assert f"Flow {invalid_id} not found" in response.json()["detail"] +# monkeypatch.setattr(endpoints, "process_graph_cached", mock_process_graph_cached) +# monkeypatch.setattr(crud, "update_total_uses", mock_update_total_uses) +# monkeypatch.setattr(endpoints, "process_graph_cached_task", mock_process_graph_cached_task) + +# api_key = created_api_key.api_key +# headers = {"x-api-key": api_key} + +# # Dummy POST data +# post_data = { +# "inputs": {"input": "value"}, +# "tweaks": None, +# "clear_cache": False, +# "session_id": None, +# } + +# # Make the request to the FastAPI TestClient + +# response = client.post(f"api/v1/process/{flow.id}", headers=headers, json=post_data) + +# # Check the response +# assert response.status_code == 200, response.json() +# assert response.json()["result"] == {}, response.json() +# assert response.json()["session_id"] == "session_id_mock", response.json() -def test_process_flow_without_autologin(client, flow, monkeypatch, created_api_key): - # Mock de process_graph_cached - from langflow.api.v1 import endpoints - from langflow.services.database.models.api_key import crud +# def test_process_flow_fails_autologin_off(client, flow, monkeypatch): +# # Mock de process_graph_cached +# from langflow.api.v1 import endpoints +# from langflow.services.database.models.api_key import crud - settings_service = get_settings_service() - settings_service.auth_settings.AUTO_LOGIN = False +# settings_service = get_settings_service() +# settings_service.auth_settings.AUTO_LOGIN = False - async def mock_process_graph_cached(*args, **kwargs): - return Result(result={}, session_id="session_id_mock") +# async def mock_process_graph_cached(*args, **kwargs): +# return Result(result={}, session_id="session_id_mock") - def mock_process_graph_cached_task(*args, **kwargs): - return Result(result={}, session_id="session_id_mock") +# async def mock_update_total_uses(*args, **kwargs): +# return created_api_key - # The task function is ran like this: - # if not self.use_celery: - # return None, await task_func(*args, **kwargs) - # if not hasattr(task_func, "apply"): - # raise ValueError(f"Task function {task_func} does not have an apply method") - # task = task_func.apply(args=args, kwargs=kwargs) - # result = task.get() - # return task.id, result - # So we need to mock the task function to return a task object - # and then mock the task object to return a result - # maybe a named tuple would be better here - task = namedtuple("task", ["id", "get"]) - mock_process_graph_cached_task.apply = lambda *args, **kwargs: task( - id="task_id_mock", get=lambda: Result(result={}, session_id="session_id_mock") - ) +# monkeypatch.setattr(endpoints, "process_graph_cached", mock_process_graph_cached) +# monkeypatch.setattr(crud, "update_total_uses", mock_update_total_uses) - def mock_update_total_uses(*args, **kwargs): - return created_api_key +# headers = {"x-api-key": "api_key"} - monkeypatch.setattr(endpoints, "process_graph_cached", mock_process_graph_cached) - monkeypatch.setattr(crud, "update_total_uses", mock_update_total_uses) - monkeypatch.setattr(endpoints, "process_graph_cached_task", mock_process_graph_cached_task) +# # Dummy POST data +# post_data = { +# "inputs": {"key": "value"}, +# "tweaks": None, +# "clear_cache": False, +# "session_id": None, +# } - api_key = created_api_key.api_key - headers = {"x-api-key": api_key} +# # Make the request to the FastAPI TestClient - # Dummy POST data - post_data = { - "inputs": {"input": "value"}, - "tweaks": None, - "clear_cache": False, - "session_id": None, - } +# response = client.post(f"api/v1/process/{flow.id}", headers=headers, json=post_data) - # Make the request to the FastAPI TestClient - - response = client.post(f"api/v1/process/{flow.id}", headers=headers, json=post_data) - - # Check the response - assert response.status_code == 200, response.json() - assert response.json()["result"] == {}, response.json() - assert response.json()["session_id"] == "session_id_mock", response.json() - - -def test_process_flow_fails_autologin_off(client, flow, monkeypatch): - # Mock de process_graph_cached - from langflow.api.v1 import endpoints - from langflow.services.database.models.api_key import crud - - settings_service = get_settings_service() - settings_service.auth_settings.AUTO_LOGIN = False - - async def mock_process_graph_cached(*args, **kwargs): - return Result(result={}, session_id="session_id_mock") - - async def mock_update_total_uses(*args, **kwargs): - return created_api_key - - monkeypatch.setattr(endpoints, "process_graph_cached", mock_process_graph_cached) - monkeypatch.setattr(crud, "update_total_uses", mock_update_total_uses) - - headers = {"x-api-key": "api_key"} - - # Dummy POST data - post_data = { - "inputs": {"key": "value"}, - "tweaks": None, - "clear_cache": False, - "session_id": None, - } - - # Make the request to the FastAPI TestClient - - response = client.post(f"api/v1/process/{flow.id}", headers=headers, json=post_data) - - # Check the response - assert response.status_code == 403, response.json() - assert response.json() == {"detail": "Invalid or missing API key"} +# # Check the response +# assert response.status_code == 403, response.json() +# assert response.json() == {"detail": "Invalid or missing API key"} def test_get_all(client: TestClient, logged_in_headers): response = client.get("api/v1/all", headers=logged_in_headers) assert response.status_code == 200 + settings = get_settings_service().settings + dir_reader = DirectoryReader(settings.COMPONENTS_PATH[0]) + files = dir_reader.get_files() + # json_response is a dict of dicts + all_names = [component_name for _, components in response.json().items() for component_name in components] json_response = response.json() # We need to test the custom nodes - assert "PromptTemplate" in json_response["prompts"] - # All CUSTOM_TOOLS(dict) should be in the response - assert all(tool in json_response["tools"] for tool in CUSTOM_TOOLS.keys()) + assert len(all_names) > len(files) + assert "ChatInput" in json_response["inputs"] + assert "Prompt" in json_response["inputs"] + assert "ChatOutput" in json_response["outputs"] def test_post_validate_code(client: TestClient): @@ -409,173 +391,345 @@ def test_various_prompts(client, prompt, expected_input_variables): assert response.json()["input_variables"] == expected_input_variables -def test_basic_chat_in_process(client, added_flow, created_api_key): - # Run the /api/v1/process/{flow_id} endpoint +def test_get_vertices_flow_not_found(client, logged_in_headers): + response = client.get("/api/v1/build/nonexistent_id/vertices", headers=logged_in_headers) + assert response.status_code == 500 # Or whatever status code you've set for invalid ID + + +def test_get_vertices(client, added_flow_with_prompt_and_history, logged_in_headers): + flow_id = added_flow_with_prompt_and_history["id"] + response = client.get(f"/api/v1/build/{flow_id}/vertices", headers=logged_in_headers) + assert response.status_code == 200 + assert "ids" in response.json() + # The response should contain the list in this order + # ['ConversationBufferMemory-Lu2Nb', 'PromptTemplate-5Q0W8', 'ChatOpenAI-vy7fV', 'LLMChain-UjBh1'] + # The important part is before the - (ConversationBufferMemory, PromptTemplate, ChatOpenAI, LLMChain) + ids = [_id.split("-")[0] for _id in response.json()["ids"]] + assert ids == [ + "ChatOpenAI", + "PromptTemplate", + "ConversationBufferMemory", + ] + + +def test_build_vertex_invalid_flow_id(client, logged_in_headers): + response = client.post("/api/v1/build/nonexistent_id/vertices/vertex_id", headers=logged_in_headers) + assert response.status_code == 500 + + +def test_build_vertex_invalid_vertex_id(client, added_flow_with_prompt_and_history, logged_in_headers): + flow_id = added_flow_with_prompt_and_history["id"] + response = client.post(f"/api/v1/build/{flow_id}/vertices/invalid_vertex_id", headers=logged_in_headers) + assert response.status_code == 500 + + +def test_successful_run_no_payload(client, starter_project, created_api_key): headers = {"x-api-key": created_api_key.api_key} - post_data = {"inputs": {"text": "Hi, My name is Gabriel"}} - response = client.post( - f"api/v1/process/{added_flow.get('id')}", - headers=headers, - json=post_data, - ) - assert response.status_code == 200, response.json() - # Check the response - assert "Gabriel" in response.json()["result"]["text"] - # session_id should be returned - assert "session_id" in response.json() - assert response.json()["session_id"] is not None - # New request with the same session_id - # asking "What is my name?" should return "Gabriel" - post_data = { - "inputs": {"text": "What is my name?"}, - "session_id": response.json()["session_id"], + flow_id = starter_project["id"] + response = client.post(f"/api/v1/run/{flow_id}", headers=headers) + assert response.status_code == status.HTTP_200_OK, response.text + # Add more assertions here to validate the response content + json_response = response.json() + assert "session_id" in json_response + assert "outputs" in json_response + outer_outputs = json_response["outputs"] + assert len(outer_outputs) == 1 + outputs_dict = outer_outputs[0] + assert len(outputs_dict) == 2 + assert "inputs" in outputs_dict + assert "outputs" in outputs_dict + assert outputs_dict.get("inputs") == {"input_value": ""} + assert isinstance(outputs_dict.get("outputs"), list) + assert len(outputs_dict.get("outputs")) == 1 + ids = [output.get("component_id") for output in outputs_dict.get("outputs")] + assert all(["ChatOutput" in _id for _id in ids]) + display_names = [output.get("component_display_name") for output in outputs_dict.get("outputs")] + assert all([name in display_names for name in ["Chat Output"]]) + inner_results = [output.get("results").get("result") for output in outputs_dict.get("outputs")] + + assert all([len(result) > 0 for result in inner_results]), inner_results + + +def test_successful_run_with_output_type_text(client, starter_project, created_api_key): + headers = {"x-api-key": created_api_key.api_key} + flow_id = starter_project["id"] + payload = { + "output_type": "text", } - response = client.post( - f"api/v1/process/{added_flow.get('id')}", - headers=headers, - json=post_data, - ) - assert response.status_code == 200, response.json() - assert "Gabriel" in response.json()["result"]["text"] + response = client.post(f"/api/v1/run/{flow_id}", headers=headers, json=payload) + assert response.status_code == status.HTTP_200_OK, response.text + # Add more assertions here to validate the response content + json_response = response.json() + assert "session_id" in json_response + assert "outputs" in json_response + outer_outputs = json_response["outputs"] + assert len(outer_outputs) == 1 + outputs_dict = outer_outputs[0] + assert len(outputs_dict) == 2 + assert "inputs" in outputs_dict + assert "outputs" in outputs_dict + assert outputs_dict.get("inputs") == {"input_value": ""} + assert isinstance(outputs_dict.get("outputs"), list) + assert len(outputs_dict.get("outputs")) == 1 + ids = [output.get("component_id") for output in outputs_dict.get("outputs")] + assert all(["TextOutput" in _id for _id in ids]), ids + display_names = [output.get("component_display_name") for output in outputs_dict.get("outputs")] + assert all([name in display_names for name in ["Prompt Output"]]), display_names + inner_results = [output.get("results").get("result") for output in outputs_dict.get("outputs")] + expected_result = "Langflow" + assert all([expected_result in result for result in inner_results]), inner_results -def test_basic_chat_different_session_ids(client, added_flow, created_api_key): - # Run the /api/v1/process/{flow_id} endpoint +def test_successful_run_with_output_type_any(client, starter_project, created_api_key): + # This one should have both the ChatOutput and TextOutput components headers = {"x-api-key": created_api_key.api_key} - post_data = {"inputs": {"text": "Hi, My name is Gabriel"}} - response = client.post( - f"api/v1/process/{added_flow.get('id')}", - headers=headers, - json=post_data, - ) - assert response.status_code == 200, response.json() - # Check the response - assert "Gabriel" in response.json()["result"]["text"] - # session_id should be returned - assert "session_id" in response.json() - assert response.json()["session_id"] is not None - session_id1 = response.json()["session_id"] - # New request with a different session_id - # asking "What is my name?" should return "Gabriel" - post_data = { - "inputs": {"text": "What is my name?"}, + flow_id = starter_project["id"] + payload = { + "output_type": "any", } - response = client.post( - f"api/v1/process/{added_flow.get('id')}", - headers=headers, - json=post_data, - ) - assert response.status_code == 200, response.json() - assert "Gabriel" not in response.json()["result"]["text"] - assert session_id1 != response.json()["session_id"] + response = client.post(f"/api/v1/run/{flow_id}", headers=headers, json=payload) + assert response.status_code == status.HTTP_200_OK, response.text + # Add more assertions here to validate the response content + json_response = response.json() + assert "session_id" in json_response + assert "outputs" in json_response + outer_outputs = json_response["outputs"] + assert len(outer_outputs) == 1 + outputs_dict = outer_outputs[0] + assert len(outputs_dict) == 2 + assert "inputs" in outputs_dict + assert "outputs" in outputs_dict + assert outputs_dict.get("inputs") == {"input_value": ""} + assert isinstance(outputs_dict.get("outputs"), list) + assert len(outputs_dict.get("outputs")) == 2 + ids = [output.get("component_id") for output in outputs_dict.get("outputs")] + assert all(["ChatOutput" in _id or "TextOutput" in _id for _id in ids]), ids + display_names = [output.get("component_display_name") for output in outputs_dict.get("outputs")] + assert all([name in display_names for name in ["Chat Output", "Prompt Output"]]), display_names + inner_results = [output.get("results").get("result") for output in outputs_dict.get("outputs")] + expected_result = "Langflow" + assert all([expected_result in result for result in inner_results]), inner_results -def test_basic_chat_with_two_session_ids_and_names(client, added_flow, created_api_key): +def test_successful_run_with_output_type_debug(client, starter_project, created_api_key): + # This one should return outputs for all components + # Let's just check the amount of outputs(there hsould be 7) headers = {"x-api-key": created_api_key.api_key} - flow_id = added_flow.get("id") - names = ["Gabriel", "John"] - session_ids = [] - - for name in names: - post_data = {"inputs": {"text": f"Hi, My name is {name}"}} - response_json = run_post(client, flow_id, headers, post_data) - - assert name in response_json["result"]["text"] - assert "session_id" in response_json - assert response_json["session_id"] is not None - - session_ids.append(response_json["session_id"]) - - for i, name in enumerate(names): - post_data = { - "inputs": {"text": "What is my name?"}, - "session_id": session_ids[i], - } - response_json = run_post(client, flow_id, headers, post_data) - - assert name in response_json["result"]["text"] + flow_id = starter_project["id"] + payload = { + "output_type": "debug", + } + response = client.post(f"/api/v1/run/{flow_id}", headers=headers, json=payload) + assert response.status_code == status.HTTP_200_OK, response.text + # Add more assertions here to validate the response content + json_response = response.json() + assert "session_id" in json_response + assert "outputs" in json_response + outer_outputs = json_response["outputs"] + assert len(outer_outputs) == 1 + outputs_dict = outer_outputs[0] + assert len(outputs_dict) == 2 + assert "inputs" in outputs_dict + assert "outputs" in outputs_dict + assert outputs_dict.get("inputs") == {"input_value": ""} + assert isinstance(outputs_dict.get("outputs"), list) + assert len(outputs_dict.get("outputs")) == 7 -@pytest.mark.async_test -def test_vector_store_in_process(distributed_client, added_vector_store, created_api_key): - # Run the /api/v1/process/{flow_id} endpoint +# To test input_type wel'l just set it with output_type debug and check if the value is correct +def test_successful_run_with_input_type_text(client, starter_project, created_api_key): headers = {"x-api-key": created_api_key.api_key} - post_data = {"inputs": {"input": "What is Langflow?"}} - response = distributed_client.post( - f"api/v1/process/{added_vector_store.get('id')}", - headers=headers, - json=post_data, - ) - assert response.status_code == 200, response.json() - # Check the response - assert "Langflow" in response.json()["result"]["output"] - # session_id should be returned - assert "session_id" in response.json() - assert response.json()["session_id"] is not None + flow_id = starter_project["id"] + payload = { + "input_type": "text", + "output_type": "debug", + "input_value": "value1", + } + response = client.post(f"/api/v1/run/{flow_id}", headers=headers, json=payload) + assert response.status_code == status.HTTP_200_OK, response.text + # Add more assertions here to validate the response content + json_response = response.json() + assert "session_id" in json_response + assert "outputs" in json_response + outer_outputs = json_response["outputs"] + assert len(outer_outputs) == 1 + outputs_dict = outer_outputs[0] + assert len(outputs_dict) == 2 + assert "inputs" in outputs_dict + assert "outputs" in outputs_dict + assert outputs_dict.get("inputs") == {"input_value": "value1"} + assert isinstance(outputs_dict.get("outputs"), list) + assert len(outputs_dict.get("outputs")) == 7 + # Now we get all components that contain TextInput in the component_id + text_input_outputs = [output for output in outputs_dict.get("outputs") if "TextInput" in output.get("component_id")] + assert len(text_input_outputs) == 2 + # Now we check if the input_value is correct + assert all([output.get("results").get("result") == "value1" for output in text_input_outputs]), text_input_outputs -# Test function without loop -@pytest.mark.async_test -def test_async_task_processing(distributed_client, added_flow, created_api_key): +# Now do the same for "chat" input type +def test_successful_run_with_input_type_chat(client, starter_project, created_api_key): headers = {"x-api-key": created_api_key.api_key} - post_data = {"inputs": {"text": "Hi, My name is Gabriel"}} - - # Run the /api/v1/process/{flow_id} endpoint with sync=False - response = distributed_client.post( - f"api/v1/process/{added_flow.get('id')}", - headers=headers, - json={**post_data, "sync": False}, - ) - assert response.status_code == 200, response.json() - - # Extract the task ID from the response - task = response.json().get("task") - task_id = task.get("id") - task_href = task.get("href") - assert task_id is not None - assert task_href is not None - assert task_href == f"api/v1/task/{task_id}" - - # Polling the task status using the helper function - task_status_json = poll_task_status(distributed_client, headers, task_href) - assert task_status_json is not None, "Task did not complete in time" - - # Validate that the task completed successfully and the result is as expected - assert "result" in task_status_json, task_status_json - assert "text" in task_status_json["result"], task_status_json["result"] - assert "Gabriel" in task_status_json["result"]["text"], task_status_json["result"] + flow_id = starter_project["id"] + payload = { + "input_type": "chat", + "output_type": "debug", + "input_value": "value1", + } + response = client.post(f"/api/v1/run/{flow_id}", headers=headers, json=payload) + assert response.status_code == status.HTTP_200_OK, response.text + # Add more assertions here to validate the response content + json_response = response.json() + assert "session_id" in json_response + assert "outputs" in json_response + outer_outputs = json_response["outputs"] + assert len(outer_outputs) == 1 + outputs_dict = outer_outputs[0] + assert len(outputs_dict) == 2 + assert "inputs" in outputs_dict + assert "outputs" in outputs_dict + assert outputs_dict.get("inputs") == {"input_value": "value1"} + assert isinstance(outputs_dict.get("outputs"), list) + assert len(outputs_dict.get("outputs")) == 7 + # Now we get all components that contain TextInput in the component_id + chat_input_outputs = [output for output in outputs_dict.get("outputs") if "ChatInput" in output.get("component_id")] + assert len(chat_input_outputs) == 1 + # Now we check if the input_value is correct + assert all([output.get("results").get("result") == "value1" for output in chat_input_outputs]), chat_input_outputs -# ! Deactivating this until updating the test -# Test function without loop -# @pytest.mark.async_test -# def test_async_task_processing_vector_store(client, added_vector_store, created_api_key): -# headers = {"x-api-key": created_api_key.api_key} -# post_data = {"inputs": {"input": "How do I upload examples?"}} +def test_successful_run_with_input_type_any(client, starter_project, created_api_key): + headers = {"x-api-key": created_api_key.api_key} + flow_id = starter_project["id"] + payload = { + "input_type": "any", + "output_type": "debug", + "input_value": "value1", + } + response = client.post(f"/api/v1/run/{flow_id}", headers=headers, json=payload) + assert response.status_code == status.HTTP_200_OK, response.text + # Add more assertions here to validate the response content + json_response = response.json() + assert "session_id" in json_response + assert "outputs" in json_response + outer_outputs = json_response["outputs"] + assert len(outer_outputs) == 1 + outputs_dict = outer_outputs[0] + assert len(outputs_dict) == 2 + assert "inputs" in outputs_dict + assert "outputs" in outputs_dict + assert outputs_dict.get("inputs") == {"input_value": "value1"} + assert isinstance(outputs_dict.get("outputs"), list) + assert len(outputs_dict.get("outputs")) == 7 + # Now we get all components that contain TextInput or ChatInput in the component_id + any_input_outputs = [ + output + for output in outputs_dict.get("outputs") + if "TextInput" in output.get("component_id") or "ChatInput" in output.get("component_id") + ] + assert len(any_input_outputs) == 3 + # Now we check if the input_value is correct + assert all([output.get("results").get("result") == "value1" for output in any_input_outputs]), any_input_outputs -# # Run the /api/v1/process/{flow_id} endpoint with sync=False -# response = client.post( -# f"api/v1/process/{added_vector_store.get('id')}", -# headers=headers, -# json={**post_data, "sync": False}, -# ) -# assert response.status_code == 200, response.json() -# assert "result" in response.json() -# assert "FAILURE" not in response.json()["result"] -# # Extract the task ID from the response -# task = response.json().get("task") -# task_id = task.get("id") -# task_href = task.get("href") -# assert task_id is not None -# assert task_href is not None -# assert task_href == f"api/v1/task/{task_id}" +def test_run_with_inputs_and_outputs(client, starter_project, created_api_key): + headers = {"x-api-key": created_api_key.api_key} + flow_id = starter_project["id"] + payload = { + "input_value": "value1", + "input_type": "text", + "output_type": "text", + "tweaks": {"parameter_name": "value"}, + "stream": False, + } + response = client.post(f"/api/v1/run/{flow_id}", json=payload, headers=headers) + assert response.status_code == status.HTTP_200_OK, response.text + # Validate the response structure and content -# # Polling the task status using the helper function -# task_status_json = poll_task_status(client, headers, task_href) -# assert task_status_json is not None, "Task did not complete in time" -# # Validate that the task completed successfully and the result is as expected -# assert "result" in task_status_json, task_status_json -# assert "output" in task_status_json["result"], task_status_json["result"] -# assert "Langflow" in task_status_json["result"]["output"], task_status_json["result"] +def test_invalid_flow_id(client, created_api_key): + headers = {"x-api-key": created_api_key.api_key} + flow_id = "invalid-flow-id" + response = client.post(f"/api/v1/run/{flow_id}", headers=headers) + assert response.status_code == status.HTTP_404_NOT_FOUND + # Check if the error detail is as expected + + +def test_run_flow_with_caching_success(client: TestClient, starter_project, created_api_key): + flow_id = starter_project["id"] + headers = {"x-api-key": created_api_key.api_key} + payload = { + "input_value": "value1", + "input_type": "text", + "output_type": "text", + "tweaks": {"parameter_name": "value"}, + "stream": False, + } + response = client.post(f"/api/v1/run/{flow_id}", json=payload, headers=headers) + assert response.status_code == status.HTTP_200_OK + data = response.json() + assert "outputs" in data + assert "session_id" in data + + +def test_run_flow_with_caching_invalid_flow_id(client: TestClient, created_api_key): + invalid_flow_id = uuid4() + headers = {"x-api-key": created_api_key.api_key} + payload = {"input_value": "", "input_type": "text", "output_type": "text", "tweaks": {}, "stream": False} + response = client.post(f"/api/v1/run/{invalid_flow_id}", json=payload, headers=headers) + assert response.status_code == status.HTTP_404_NOT_FOUND + data = response.json() + assert "detail" in data + assert f"Flow {invalid_flow_id} not found" in data["detail"] + + +def test_run_flow_with_caching_invalid_input_format(client: TestClient, starter_project, created_api_key): + flow_id = starter_project["id"] + headers = {"x-api-key": created_api_key.api_key} + payload = {"input_value": {"key": "value"}, "input_type": "text", "output_type": "text", "tweaks": {}} + response = client.post(f"/api/v1/run/{flow_id}", json=payload, headers=headers) + assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY + + +def test_run_flow_with_session_id(client, starter_project, created_api_key): + headers = {"x-api-key": created_api_key.api_key} + flow_id = starter_project["id"] + payload = { + "input_value": "value1", + "input_type": "text", + "output_type": "text", + "session_id": "test-session-id", + } + response = client.post(f"/api/v1/run/{flow_id}", json=payload, headers=headers) + assert response.status_code == status.HTTP_404_NOT_FOUND + data = response.json() + assert {"detail": "Session test-session-id not found"} == data + + +def test_run_flow_with_invalid_session_id(client, starter_project, created_api_key): + headers = {"x-api-key": created_api_key.api_key} + flow_id = starter_project["id"] + payload = { + "input_value": "value1", + "input_type": "text", + "output_type": "text", + "session_id": "invalid-session-id", + } + response = client.post(f"/api/v1/run/{flow_id}", json=payload, headers=headers) + assert response.status_code == status.HTTP_404_NOT_FOUND + data = response.json() + assert "detail" in data + assert f"Session {payload['session_id']} not found" in data["detail"] + + +def test_run_flow_with_invalid_tweaks(client, starter_project, created_api_key): + headers = {"x-api-key": created_api_key.api_key} + flow_id = starter_project["id"] + payload = { + "input_value": "value1", + "input_type": "text", + "output_type": "text", + "tweaks": {"invalid_tweak": "value"}, + } + response = client.post(f"/api/v1/run/{flow_id}", json=payload, headers=headers) + assert response.status_code == status.HTTP_200_OK diff --git a/tests/test_files.py b/tests/test_files.py new file mode 100644 index 000000000..b3a85cf03 --- /dev/null +++ b/tests/test_files.py @@ -0,0 +1,104 @@ +from unittest.mock import MagicMock + +import pytest + +from langflow.services.deps import get_storage_service +from langflow.services.storage.service import StorageService + + +@pytest.fixture +def mock_storage_service(): + # Create a mock instance of StorageService + service = MagicMock(spec=StorageService) + # Setup mock behaviors for the service methods as needed + service.save_file.return_value = None + service.get_file.return_value = b"file content" # Binary content for files + service.list_files.return_value = ["file1.txt", "file2.jpg"] + service.delete_file.return_value = None + return service + + +def test_upload_file(client, mock_storage_service, created_api_key, flow): + headers = {"x-api-key": created_api_key.api_key} + # Replace the actual storage service with the mock + client.app.dependency_overrides[get_storage_service] = lambda: mock_storage_service + + response = client.post( + f"api/v1/files/upload/{flow.id}", + files={"file": ("test.txt", b"test content")}, + headers=headers, + ) + assert response.status_code == 201 + assert response.json() == { + "flowId": str(flow.id), + "file_path": f"{flow.id}/test.txt", + } + + +def test_download_file(client, mock_storage_service, created_api_key, flow): + headers = {"x-api-key": created_api_key.api_key} + client.app.dependency_overrides[get_storage_service] = lambda: mock_storage_service + + response = client.get(f"api/v1/files/download/{flow.id}/test.txt", headers=headers) + assert response.status_code == 200 + assert response.content == b"file content" + + +def test_list_files(client, mock_storage_service, created_api_key, flow): + headers = {"x-api-key": created_api_key.api_key} + client.app.dependency_overrides[get_storage_service] = lambda: mock_storage_service + + response = client.get(f"api/v1/files/list/{flow.id}", headers=headers) + assert response.status_code == 200 + assert response.json() == {"files": ["file1.txt", "file2.jpg"]} + + +def test_delete_file(client, mock_storage_service, created_api_key, flow): + headers = {"x-api-key": created_api_key.api_key} + client.app.dependency_overrides[get_storage_service] = lambda: mock_storage_service + + response = client.delete(f"api/v1/files/delete/{flow.id}/test.txt", headers=headers) + assert response.status_code == 200 + assert response.json() == {"message": "File test.txt deleted successfully"} + + +def test_file_operations(client, created_api_key, flow): + headers = {"x-api-key": created_api_key.api_key} + flow_id = flow.id + file_name = "test.txt" + file_content = b"Hello, world!" + + # Step 1: Upload the file + response = client.post( + f"api/v1/files/upload/{flow_id}", + files={"file": (file_name, file_content)}, + headers=headers, + ) + assert response.status_code == 201 + assert response.json() == { + "flowId": str(flow_id), + "file_path": f"{flow_id}/{file_name}", + } + + # Step 2: List files in the folder + response = client.get(f"api/v1/files/list/{flow_id}", headers=headers) + assert response.status_code == 200 + assert file_name in response.json()["files"] + + # Step 3: Download the file and verify its content + + response = client.get(f"api/v1/files/download/{flow_id}/{file_name}", headers=headers) + assert response.status_code == 200 + assert response.content == file_content + # the headers are application/octet-stream + assert response.headers["content-type"] == "application/octet-stream" + # mime_type is inside media_type + + # Step 4: Delete the file + response = client.delete(f"api/v1/files/delete/{flow_id}/{file_name}", headers=headers) + assert response.status_code == 200 + assert response.json() == {"message": f"File {file_name} deleted successfully"} + + # Verify that the file is indeed deleted + response = client.get(f"api/v1/files/list/{flow_id}", headers=headers) + assert file_name not in response.json()["files"] diff --git a/tests/test_graph.py b/tests/test_graph.py index cca6d4f49..8395c304f 100644 --- a/tests/test_graph.py +++ b/tests/test_graph.py @@ -1,14 +1,9 @@ import copy import json -import os import pickle -from pathlib import Path from typing import Type, Union import pytest -from langchain.agents import AgentExecutor -from langchain.chains.base import Chain -from langchain.llms.fake import FakeListLLM from langflow.graph import Graph from langflow.graph.edge.base import Edge @@ -21,10 +16,8 @@ from langflow.graph.graph.utils import ( update_target_handle, update_template, ) -from langflow.graph.utils import UnbuiltObject from langflow.graph.vertex.base import Vertex -from langflow.graph.vertex.types import FileToolVertex, LLMVertex, ToolkitVertex -from langflow.processing.process import get_result_and_thought +from langflow.initial_setup.setup import load_starter_projects from langflow.utils.payload import get_root_vertex # Test cases for the graph module @@ -82,8 +75,10 @@ def test_graph_structure(basic_graph): assert isinstance(node, Vertex) for edge in basic_graph.edges: assert isinstance(edge, Edge) - assert edge.source_id in basic_graph.vertex_map.keys() - assert edge.target_id in basic_graph.vertex_map.keys() + source_vertex = basic_graph.get_vertex(edge.source_id) + target_vertex = basic_graph.get_vertex(edge.target_id) + assert source_vertex in basic_graph.vertices + assert target_vertex in basic_graph.vertices def test_circular_dependencies(basic_graph): @@ -152,55 +147,6 @@ def test_get_node_neighbors_basic(basic_graph): assert any("OpenAI" in neighbor.data["type"] for neighbor, val in neighbors.items() if val) -# def test_get_node_neighbors_complex(complex_graph): -# """Test getting node neighbors""" -# assert isinstance(complex_graph, Graph) -# # Get root node -# root = get_root_node(complex_graph) -# assert root is not None -# neighbors = complex_graph.get_nodes_with_target(root) -# assert neighbors is not None -# # Neighbors should be a list of nodes -# assert isinstance(neighbors, list) -# # Root Node is an Agent, it requires an LLMChain and tools -# # We need to check if there is a Chain in the one of the neighbors' -# assert any("Chain" in neighbor.data["type"] for neighbor in neighbors) -# # assert Tool is in the neighbors -# assert any("Tool" in neighbor.data["type"] for neighbor in neighbors) -# # Now on to the Chain's neighbors -# chain = next(neighbor for neighbor in neighbors if "Chain" in neighbor.data["type"]) -# chain_neighbors = complex_graph.get_nodes_with_target(chain) -# assert chain_neighbors is not None -# # Check if there is a LLM in the chain's neighbors -# assert any("OpenAI" in neighbor.data["type"] for neighbor in chain_neighbors) -# # Chain should have a Prompt as a neighbor -# assert any("Prompt" in neighbor.data["type"] for neighbor in chain_neighbors) -# # Now on to the Tool's neighbors -# tool = next(neighbor for neighbor in neighbors if "Tool" in neighbor.data["type"]) -# tool_neighbors = complex_graph.get_nodes_with_target(tool) -# assert tool_neighbors is not None -# # Check if there is an Agent in the tool's neighbors -# assert any("Agent" in neighbor.data["type"] for neighbor in tool_neighbors) -# # This Agent has a Tool that has a PythonFunction as func -# agent = next( -# neighbor for neighbor in tool_neighbors if "Agent" in neighbor.data["type"] -# ) -# agent_neighbors = complex_graph.get_nodes_with_target(agent) -# assert agent_neighbors is not None -# # Check if there is a Tool in the agent's neighbors -# assert any("Tool" in neighbor.data["type"] for neighbor in agent_neighbors) -# # This Tool has a PythonFunction as func -# tool = next( -# neighbor for neighbor in agent_neighbors if "Tool" in neighbor.data["type"] -# ) -# tool_neighbors = complex_graph.get_nodes_with_target(tool) -# assert tool_neighbors is not None -# # Check if there is a PythonFunction in the tool's neighbors -# assert any( -# "PythonFunctionTool" in neighbor.data["type"] for neighbor in tool_neighbors -# ) - - def test_get_node(basic_graph): """Test getting a single node""" node_id = basic_graph.vertices[0].id @@ -222,7 +168,6 @@ def test_build_edges(basic_graph): assert len(basic_graph.edges) == len(basic_graph._edges) for edge in basic_graph.edges: assert isinstance(edge, Edge) - assert isinstance(edge.source_id, str) assert isinstance(edge.target_id, str) @@ -281,83 +226,11 @@ def test_build_params(basic_graph): assert "memory" in root.params -@pytest.mark.asyncio -async def test_build(basic_graph): - """Test Node's build method""" - await assert_agent_was_built(basic_graph) - - -async def assert_agent_was_built(graph): - """Assert that the agent was built""" - assert isinstance(graph, Graph) - # Now we test the build method - # Build the Agent - result = await graph.build() - # The agent should be a AgentExecutor - assert isinstance(result, Chain) - - -@pytest.mark.asyncio -async def test_llm_node_build(basic_graph): - llm_node = get_node_by_type(basic_graph, LLMVertex) - assert llm_node is not None - built_object = await llm_node.build() - assert built_object is not UnbuiltObject() - - -@pytest.mark.asyncio -async def test_toolkit_node_build(client, openapi_graph): - # Write a file to the disk - file_path = "api-with-examples.yaml" - with open(file_path, "w") as f: - f.write("openapi: 3.0.0") - - toolkit_node = get_node_by_type(openapi_graph, ToolkitVertex) - assert toolkit_node is not None - built_object = await toolkit_node.build() - assert built_object is not UnbuiltObject - # Remove the file - os.remove(file_path) - assert not Path(file_path).exists() - - -@pytest.mark.asyncio -async def test_file_tool_node_build(client, openapi_graph): - file_path = "api-with-examples.yaml" - with open(file_path, "w") as f: - f.write("openapi: 3.0.0") - - assert Path(file_path).exists() - file_tool_node = get_node_by_type(openapi_graph, FileToolVertex) - assert file_tool_node is not UnbuiltObject and file_tool_node is not None - built_object = await file_tool_node.build() - assert built_object is not UnbuiltObject - # Remove the file - os.remove(file_path) - assert not Path(file_path).exists() - - -@pytest.mark.asyncio -async def test_get_result_and_thought(basic_graph): - """Test the get_result_and_thought method""" - responses = [ - "Final Answer: I am a response", - ] - message = {"input": "Hello"} - # Find the node that is an LLMNode and change the - # _built_object to a FakeListLLM - llm_node = get_node_by_type(basic_graph, LLMVertex) - assert llm_node is not None - llm_node._built_object = FakeListLLM(responses=responses) - llm_node._built = True - langchain_object = await basic_graph.build() - # assert all nodes are built - assert all(node._built for node in basic_graph.vertices) - # now build again and check if FakeListLLM was used - - # Get the result and thought - result = get_result_and_thought(langchain_object, message) - assert isinstance(result, dict) +# def test_wrapper_node_build(openapi_graph): +# wrapper_node = get_node_by_type(openapi_graph, WrapperVertex) +# assert wrapper_node is not None +# built_object = wrapper_node.build() +# assert built_object is not None def test_find_last_node(grouped_chat_json_flow): @@ -471,12 +344,10 @@ def test_update_template(sample_template, sample_nodes): node2_updated = next((n for n in nodes_copy if n["id"] == "node2"), None) node3_updated = next((n for n in nodes_copy if n["id"] == "node3"), None) - assert node1_updated is not None assert node1_updated["data"]["node"]["template"]["some_field"]["show"] is True assert node1_updated["data"]["node"]["template"]["some_field"]["advanced"] is False assert node1_updated["data"]["node"]["template"]["some_field"]["display_name"] == "Name1" - assert node2_updated is not None assert node2_updated["data"]["node"]["template"]["other_field"]["show"] is False assert node2_updated["data"]["node"]["template"]["other_field"]["advanced"] is True assert node2_updated["data"]["node"]["template"]["other_field"]["display_name"] == "DisplayName2" @@ -537,27 +408,37 @@ def test_update_source_handle(): @pytest.mark.asyncio async def test_pickle_graph(json_vector_store): - loaded_json = json.loads(json_vector_store) - graph = Graph.from_payload(loaded_json) + starter_projects = load_starter_projects() + data = starter_projects[0]["data"] + graph = Graph.from_payload(data) assert isinstance(graph, Graph) - first_result = await graph.build() - assert isinstance(first_result, AgentExecutor) pickled = pickle.dumps(graph) - assert pickled is not UnbuiltObject + assert pickled is not None unpickled = pickle.loads(pickled) - assert unpickled is not UnbuiltObject - result = await unpickled.build() - assert isinstance(result, AgentExecutor) + assert unpickled is not None @pytest.mark.asyncio async def test_pickle_each_vertex(json_vector_store): - loaded_json = json.loads(json_vector_store) - graph = Graph.from_payload(loaded_json) + starter_projects = load_starter_projects() + data = starter_projects[0]["data"] + graph = Graph.from_payload(data) assert isinstance(graph, Graph) for vertex in graph.vertices: await vertex.build() pickled = pickle.dumps(vertex) - assert pickled is not UnbuiltObject + assert pickled is not None unpickled = pickle.loads(pickled) - assert unpickled is not UnbuiltObject + assert unpickled is not None + + +@pytest.mark.asyncio +async def test_build_ordering(complex_graph_with_groups): + sorted_vertices = complex_graph_with_groups.sort_vertices(stop_component_id="ChatInput-Ay8QQ") + assert sorted_vertices == [ + "ChatInput-Ay8QQ", + "RecordsAsText-vkx2A", + "FileLoader-Vo1Cq", + ] + + sorted_vertices = complex_graph_with_groups.sort_vertices() diff --git a/tests/test_helper_components.py b/tests/test_helper_components.py new file mode 100644 index 000000000..8414cdac5 --- /dev/null +++ b/tests/test_helper_components.py @@ -0,0 +1,80 @@ +from langchain_core.documents import Document +from langflow.components import helpers +from langflow.interface.custom.utils import build_custom_component_template +from langflow.schema import Record + + +def test_update_record_component(): + # Arrange + update_record_component = helpers.UpdateRecordComponent() + + # Act + new_data = {"new_key": "new_value"} + existing_record = Record(data={"existing_key": "existing_value"}) + result = update_record_component.build(existing_record, new_data) + assert result.data == {"existing_key": "existing_value", "new_key": "new_value"} + assert result.existing_key == "existing_value" + assert result.new_key == "new_value" + + +def test_document_to_record_component(): + # Arrange + document_to_record_component = helpers.DocumentToRecordComponent() + + # Act + # Replace with your actual test data + document = Document(page_content="key: value", metadata={"url": "https://example.com"}) + result = document_to_record_component.build(document) + + # Assert + # Replace with your actual expected result + assert result == [Record(data={"text": "key: value", "url": "https://example.com"})] + + +def test_uuid_generator_component(): + # Arrange + uuid_generator_component = helpers.UUIDGeneratorComponent() + uuid_generator_component.code = open(helpers.IDGenerator.__file__, "r").read() + + frontend_node, _ = build_custom_component_template(uuid_generator_component) + + # Act + build_config = frontend_node.get("template") + field_name = "unique_id" + build_config = uuid_generator_component.update_build_config(build_config, None, field_name) + unique_id = build_config["unique_id"]["value"] + result = uuid_generator_component.build(unique_id) + + # Assert + # UUID should be a string of length 36 + assert isinstance(result, str) + assert len(result) == 36 + + +def test_records_as_text_component(): + # Arrange + records_as_text_component = helpers.RecordsToTextComponent() + + # Act + # Replace with your actual test data + records = [Record(data={"key": "value", "bacon": "eggs"})] + template = "Data:{data} -- Bacon:{bacon}" + result = records_as_text_component.build(records, template=template) + + # Assert + # Replace with your actual expected result + assert result == "Data:{'key': 'value', 'bacon': 'eggs'} -- Bacon:eggs" + + +def test_text_to_record_component(): + # Arrange + text_to_record_component = helpers.CreateRecordComponent() + + # Act + # Replace with your actual test data + dict_with_text = {"field_1": {"key": "value"}} + result = text_to_record_component.build(number_of_fields=1, **dict_with_text) + + # Assert + # Replace with your actual expected result + assert result == Record(data={"key": "value"}) diff --git a/tests/test_initial_setup.py b/tests/test_initial_setup.py new file mode 100644 index 000000000..33aaf8df3 --- /dev/null +++ b/tests/test_initial_setup.py @@ -0,0 +1,92 @@ +from datetime import datetime + +import pytest +from langflow.graph.graph.base import Graph +from langflow.graph.schema import RunOutputs +from langflow.initial_setup.setup import ( + STARTER_FOLDER_NAME, + create_or_update_starter_projects, + get_project_data, + load_starter_projects, +) +from langflow.memory import delete_messages +from langflow.services.database.models.flow.model import Flow +from langflow.services.deps import session_scope +from sqlalchemy import func +from sqlmodel import select + + +def test_load_starter_projects(): + projects = load_starter_projects() + assert isinstance(projects, list) + assert all(isinstance(project, dict) for project in projects) + + +def test_get_project_data(): + projects = load_starter_projects() + for _, project in projects: + ( + project_name, + project_description, + project_is_component, + updated_at_datetime, + project_data, + project_icon, + project_icon_bg_color, + ) = get_project_data(project) + assert isinstance(project_name, str) + assert isinstance(project_description, str) + assert isinstance(project_is_component, bool) + assert isinstance(updated_at_datetime, datetime) + assert isinstance(project_data, dict) + assert isinstance(project_icon, str) or project_icon is None + assert isinstance(project_icon_bg_color, str) or project_icon_bg_color is None + + +def test_create_or_update_starter_projects(client): + with session_scope() as session: + # Run the function to create or update projects + create_or_update_starter_projects() + + # Get the number of projects returned by load_starter_projects + num_projects = len(load_starter_projects()) + + # Get the number of projects in the database + num_db_projects = session.exec(select(func.count(Flow.id)).where(Flow.folder == STARTER_FOLDER_NAME)).one() + + # Check that the number of projects in the database is the same as the number of projects returned by load_starter_projects + assert num_db_projects == num_projects + + +@pytest.mark.asyncio +async def test_starter_project_can_run_successfully(client): + with session_scope() as session: + # Run the function to create or update projects + create_or_update_starter_projects() + + # Get the number of projects returned by load_starter_projects + num_projects = len(load_starter_projects()) + + # Get the number of projects in the database + num_db_projects = session.exec(select(func.count(Flow.id)).where(Flow.folder == STARTER_FOLDER_NAME)).one() + + # Check that the number of projects in the database is the same as the number of projects returned by load_starter_projects + assert num_db_projects == num_projects + + # Get all the starter projects + projects = session.exec(select(Flow).where(Flow.folder == STARTER_FOLDER_NAME)).all() + + graphs: list[tuple[str, Graph]] = [ + (project.name, Graph.from_payload(project.data, flow_id=project.id)) + for project in projects + if "Document" not in project.name or "RAG" not in project.name + ] + assert len(graphs) == len(projects) + for name, graph in graphs: + outputs = await graph.arun( + inputs={}, + outputs=[], + session_id="test", + ) + assert all(isinstance(output, RunOutputs) for output in outputs), f"Project {name} error: {outputs}" + delete_messages(session_id="test") diff --git a/tests/test_loading.py b/tests/test_loading.py index eb3987e93..b95791139 100644 --- a/tests/test_loading.py +++ b/tests/test_loading.py @@ -1,37 +1,19 @@ -import json - import pytest -from langchain.chains.base import Chain + from langflow.graph import Graph from langflow.processing.load import load_flow_from_json -from langflow.utils.payload import get_root_vertex def test_load_flow_from_json(): """Test loading a flow from a json file""" loaded = load_flow_from_json(pytest.BASIC_EXAMPLE_PATH) assert loaded is not None - assert isinstance(loaded, Chain) + assert isinstance(loaded, Graph) def test_load_flow_from_json_with_tweaks(): """Test loading a flow from a json file and applying tweaks""" - tweaks = {"dndnode_82": {"model_name": "test model"}} + tweaks = {"dndnode_82": {"model_name": "gpt-3.5-turbo-16k-0613"}} loaded = load_flow_from_json(pytest.BASIC_EXAMPLE_PATH, tweaks=tweaks) assert loaded is not None - assert isinstance(loaded, Chain) - assert loaded.llm.model_name == "test model" - - -def test_get_root_vertex(): - with open(pytest.BASIC_EXAMPLE_PATH, "r") as f: - flow_graph = json.load(f) - data_graph = flow_graph["data"] - nodes = data_graph["nodes"] - edges = data_graph["edges"] - graph = Graph(nodes, edges) - root = get_root_vertex(graph) - assert root is not None - assert hasattr(root, "id") - assert hasattr(root, "data") - assert hasattr(root, "data") + assert isinstance(loaded, Graph) diff --git a/tests/test_login.py b/tests/test_login.py index 399c7b761..29a8a852e 100644 --- a/tests/test_login.py +++ b/tests/test_login.py @@ -1,8 +1,8 @@ +import pytest +from langflow.services.auth.utils import get_password_hash +from langflow.services.database.models.user import User from langflow.services.database.utils import session_getter from langflow.services.deps import get_db_service -import pytest -from langflow.services.database.models.user import User -from langflow.services.auth.utils import get_password_hash @pytest.fixture diff --git a/tests/test_process.py b/tests/test_process.py index c8e4ec9cc..2548e9215 100644 --- a/tests/test_process.py +++ b/tests/test_process.py @@ -1,4 +1,5 @@ import pytest + from langflow.processing.process import process_tweaks from langflow.services.deps import get_session_service @@ -164,6 +165,70 @@ def test_multiple_tweaks(): assert result == expected_result +# Test twekas that just pass the param and value but no node id. +# This is a new feature that was added to the process_tweaks function +def test_tweak_no_node_id(): + graph_data = { + "data": { + "nodes": [ + { + "id": "node1", + "data": { + "node": { + "template": { + "param1": {"value": 1}, + "param2": {"value": 2}, + } + } + }, + }, + { + "id": "node2", + "data": { + "node": { + "template": { + "param1": {"value": 3}, + "param2": {"value": 4}, + } + } + }, + }, + ] + } + } + tweaks = {"param1": 5} + expected_result = { + "data": { + "nodes": [ + { + "id": "node1", + "data": { + "node": { + "template": { + "param1": {"value": 5}, + "param2": {"value": 2}, + } + } + }, + }, + { + "id": "node2", + "data": { + "node": { + "template": { + "param1": {"value": 5}, + "param2": {"value": 4}, + } + } + }, + }, + ] + } + } + result = process_tweaks(graph_data, tweaks) + assert result == expected_result + + def test_tweak_not_in_template(): graph_data = { "data": { @@ -217,11 +282,11 @@ async def test_load_langchain_object_with_no_cached_session(client, basic_graph_ session_service = get_session_service() session_id1 = "non-existent-session-id" session_id = session_service.build_key(session_id1, basic_graph_data) - graph1, artifacts1 = await session_service.load_session(session_id, basic_graph_data) + graph1, artifacts1 = await session_service.load_session(session_id, data_graph=basic_graph_data, flow_id="flow_id") # Clear the cache session_service.clear_session(session_id) # Use the new session_id to get the langchain_object again - graph2, artifacts2 = await session_service.load_session(session_id, basic_graph_data) + graph2, artifacts2 = await session_service.load_session(session_id, data_graph=basic_graph_data, flow_id="flow_id") assert id(graph1) != id(graph2) # Since the cache was cleared, objects should be different @@ -232,8 +297,8 @@ async def test_load_langchain_object_without_session_id(client, basic_graph_data # Provide a non-existent session_id session_service = get_session_service() session_id1 = None - graph1, artifacts1 = await session_service.load_session(session_id1, basic_graph_data) + graph1, artifacts1 = await session_service.load_session(session_id1, data_graph=basic_graph_data, flow_id="flow_id") # Use the new session_id to get the langchain_object again - graph2, artifacts2 = await session_service.load_session(session_id1, basic_graph_data) + graph2, artifacts2 = await session_service.load_session(session_id1, data_graph=basic_graph_data, flow_id="flow_id") assert graph1 == graph2 diff --git a/tests/test_prompts_template.py b/tests/test_prompts_template.py deleted file mode 100644 index 505b9db2f..000000000 --- a/tests/test_prompts_template.py +++ /dev/null @@ -1,11 +0,0 @@ -from fastapi.testclient import TestClient -from langflow.services.deps import get_settings_service - - -def test_prompts_settings(client: TestClient, logged_in_headers): - settings_service = get_settings_service() - response = client.get("api/v1/all", headers=logged_in_headers) - assert response.status_code == 200 - json_response = response.json() - prompts = json_response["prompts"] - assert set(prompts.keys()) == set(settings_service.settings.PROMPTS) diff --git a/tests/test_record.py b/tests/test_record.py new file mode 100644 index 000000000..45afaa5af --- /dev/null +++ b/tests/test_record.py @@ -0,0 +1,139 @@ +from langchain_core.documents import Document + +from langflow.schema import Record + + +def test_record_initialization(): + record = Record(text_key="msg", data={"msg": "Hello, World!", "extra": "value"}) + assert record.msg == "Hello, World!" + assert record.extra == "value" + + +def test_validate_data_with_extra_keys(): + record = Record(dummy_key="dummy", data={"key": "value"}) + assert record.data["dummy_key"] == "dummy" + assert "dummy_key" in record.data + assert record.key == "value" + + +def test_conversion_to_document(): + record = Record(data={"text": "Sample text", "meta": "data"}) + document = record.to_lc_document() + assert document.page_content == "Sample text" + assert document.metadata == {"meta": "data"} + + +def test_conversion_from_document(): + document = Document(page_content="Doc content", metadata={"meta": "info"}) + record = Record.from_document(document) + assert record.text == "Doc content" + assert record.meta == "info" + + +def test_add_method_for_strings(): + record1 = Record(data={"text": "Hello"}) + record2 = Record(data={"text": " World"}) + combined = record1 + record2 + assert combined.text == "Hello World" + + +def test_add_method_for_integers(): + record1 = Record(data={"number": 5}) + record2 = Record(data={"number": 10}) + combined = record1 + record2 + assert combined.number == 15 + + +def test_add_method_with_non_overlapping_keys(): + record1 = Record(data={"text": "Hello"}) + record2 = Record(data={"number": 10}) + combined = record1 + record2 + assert combined.text == "Hello" + assert combined.number == 10 + + +def test_custom_attribute_get_set_del(): + record = Record() + record.custom_attr = "custom_value" + assert record.custom_attr == "custom_value" + del record.custom_attr + assert record.custom_attr == record.default_value + + +def test_deep_copy(): + import copy + + record1 = Record(data={"text": "Hello", "number": 10}) + record2 = copy.deepcopy(record1) + assert record2.text == "Hello" + assert record2.number == 10 + record2.text = "World" + assert record1.text == "Hello" # Ensure original is unchanged + + +def test_custom_attribute_setting_and_getting(): + record = Record() + record.dynamic_attribute = "Dynamic Value" + assert record.dynamic_attribute == "Dynamic Value" + + +def test_str_and_dir_methods(): + record = Record(text_key="text", data={"text": "Test Text", "key": "value"}) + assert "Test Text" in str(record) + assert "key" in dir(record) + assert "data" in dir(record) + + +def test_dir_includes_data_keys(): + record = Record(data={"text": "Hello", "new_attr": "value"}) + dir_output = dir(record) + + # Check for standard attributes + assert "data" in dir_output + assert "text_key" in dir_output + assert "__add__" in dir_output # Checking for a method + + # Check for dynamic attributes from data + assert "text" in dir_output + assert "new_attr" in dir_output + + # Optionally, verify that dynamically added attributes are listed + record.dynamic_attr = "dynamic" + assert "dynamic_attr" in dir_output or "dynamic_attr" in dir(record) # To account for the change + + +def test_dir_reflects_attribute_deletion(): + record = Record(data={"removable": "I can be removed"}) + assert "removable" in dir(record) + + # Delete the attribute and check again + del record.removable + assert "removable" not in dir(record) + + +def test_get_text_with_text_key(): + data = {"text": "Hello, World!"} + schema = Record(data=data, text_key="text", default_value="default") + result = schema.get_text() + assert result == "Hello, World!" + + +def test_get_text_without_text_key(): + data = {"other_key": "Hello, World!"} + schema = Record(data=data, text_key="text", default_value="default") + result = schema.get_text() + assert result == "default" + + +def test_get_text_with_empty_data(): + data = {} + schema = Record(data=data, text_key="text", default_value="default") + result = schema.get_text() + assert result == "default" + + +def test_get_text_with_none_data(): + data = None + schema = Record(data=data, text_key="text", default_value="default") + result = schema.get_text() + assert result == "default" diff --git a/tests/test_setup_superuser.py b/tests/test_setup_superuser.py index 03d3882fb..c2172429b 100644 --- a/tests/test_setup_superuser.py +++ b/tests/test_setup_superuser.py @@ -1,6 +1,9 @@ from unittest.mock import MagicMock, patch -from langflow.services.settings.constants import DEFAULT_SUPERUSER, DEFAULT_SUPERUSER_PASSWORD +from langflow.services.settings.constants import ( + DEFAULT_SUPERUSER, + DEFAULT_SUPERUSER_PASSWORD, +) from langflow.services.utils import teardown_superuser # @patch("langflow.services.deps.get_session") @@ -119,11 +122,11 @@ def test_teardown_superuser_no_default_superuser(mock_get_session, mock_get_sett mock_session = MagicMock() mock_user = MagicMock() mock_user.is_superuser = False - mock_session.exec.return_value.filter.return_value.first.return_value = mock_user + mock_session.query.return_value.filter.return_value.first.return_value = mock_user mock_get_session.return_value = [mock_session] teardown_superuser(mock_settings_service, mock_session) - mock_session.exec.assert_called_once() + mock_session.query.assert_not_called() mock_session.delete.assert_not_called() mock_session.commit.assert_not_called() diff --git a/tests/test_user.py b/tests/test_user.py index d7e814845..5f894e801 100644 --- a/tests/test_user.py +++ b/tests/test_user.py @@ -1,7 +1,6 @@ from datetime import datetime import pytest - from langflow.services.auth.utils import create_super_user, get_password_hash from langflow.services.database.models.user import UserUpdate from langflow.services.database.models.user.model import User @@ -90,7 +89,7 @@ def test_data_consistency_after_update(client, active_user, logged_in_headers, s user_id = active_user.id update_data = UserUpdate(is_active=False) - response = client.patch(f"/api/v1/users/{user_id}", json=update_data.model_dump(), headers=super_user_headers) + response = client.patch(f"/api/v1/users/{user_id}", json=update_data.dict(), headers=super_user_headers) assert response.status_code == 200, response.json() # Fetch the updated user from the database @@ -117,7 +116,7 @@ def test_inactive_user(client): username="inactiveuser", password=get_password_hash("testpassword"), is_active=False, - last_login_at=datetime.now(), + last_login_at=datetime(2023, 1, 1, 0, 0, 0), ) session.add(user) session.commit() @@ -164,13 +163,13 @@ def test_patch_user(client, active_user, logged_in_headers): username="newname", ) - response = client.patch(f"/api/v1/users/{user_id}", json=update_data.model_dump(), headers=logged_in_headers) + response = client.patch(f"/api/v1/users/{user_id}", json=update_data.dict(), headers=logged_in_headers) assert response.status_code == 200, response.json() update_data = UserUpdate( profile_image="new_image", ) - response = client.patch(f"/api/v1/users/{user_id}", json=update_data.model_dump(), headers=logged_in_headers) + response = client.patch(f"/api/v1/users/{user_id}", json=update_data.dict(), headers=logged_in_headers) assert response.status_code == 200, response.json() @@ -182,7 +181,7 @@ def test_patch_reset_password(client, active_user, logged_in_headers): response = client.patch( f"/api/v1/users/{user_id}/reset-password", - json=update_data.model_dump(), + json=update_data.dict(), headers=logged_in_headers, ) assert response.status_code == 200, response.json() @@ -198,13 +197,13 @@ def test_patch_user_wrong_id(client, active_user, logged_in_headers): username="newname", ) - response = client.patch(f"/api/v1/users/{user_id}", json=update_data.model_dump(), headers=logged_in_headers) + response = client.patch(f"/api/v1/users/{user_id}", json=update_data.dict(), headers=logged_in_headers) assert response.status_code == 422, response.json() json_response = response.json() detail = json_response["detail"] - assert detail[0]["type"] == "uuid_parsing" - assert detail[0]["loc"] == ["path", "user_id"] - assert detail[0]["input"] == "wrong_id" + error = detail[0] + assert error["loc"] == ["path", "user_id"] + assert error["type"] == "uuid_parsing" def test_delete_user(client, test_user, super_user_headers): @@ -220,9 +219,9 @@ def test_delete_user_wrong_id(client, test_user, super_user_headers): assert response.status_code == 422 json_response = response.json() detail = json_response["detail"] - assert detail[0]["type"] == "uuid_parsing" - assert detail[0]["loc"] == ["path", "user_id"] - assert detail[0]["input"] == "wrong_id" + error = detail[0] + assert error["loc"] == ["path", "user_id"] + assert error["type"] == "uuid_parsing" def test_normal_user_cant_delete_user(client, test_user, logged_in_headers): diff --git a/tests/test_websocket.py b/tests/test_websocket.py deleted file mode 100644 index c4c9ee322..000000000 --- a/tests/test_websocket.py +++ /dev/null @@ -1,50 +0,0 @@ -from fastapi import WebSocketDisconnect -from fastapi.testclient import TestClient - -# from langflow.services.chat.manager import ChatService - -import pytest - - -def test_init_build(client, active_user, logged_in_headers): - response = client.post( - "api/v1/build/init/test", - json={"id": "test", "data": {"key": "value"}}, - headers=logged_in_headers, - ) - assert response.status_code == 201 - assert response.json() == {"flowId": "test"} - - -# def test_stream_build(client): -# client.post( -# "api/v1/build/init", json={"id": "stream_test", "data": {"key": "value"}} -# ) - -# # Test the stream -# response = client.get("api/v1/build/stream/stream_test") -# assert response.status_code == 200 -# assert response.headers["content-type"] == "text/event-stream; charset=utf-8" - - -def test_websocket_endpoint(client: TestClient, active_user, logged_in_headers): - # Assuming your websocket_endpoint uses chat_service which caches data from stream_build - access_token = logged_in_headers["Authorization"].split(" ")[1] - with pytest.raises(WebSocketDisconnect): - with client.websocket_connect(f"api/v1/chat/non_existing_client_id?token={access_token}") as websocket: - websocket.send_json({"type": "test"}) - data = websocket.receive_json() - assert "Please, build the flow before sending messages" in data["message"] - - -def test_websocket_endpoint_after_build(client, basic_graph_data): - # Assuming your websocket_endpoint uses chat_service which caches data from stream_build - client.post("api/v1/build/init", json=basic_graph_data) - client.get("api/v1/build/stream/websocket_test") - - # There should be more to test here, but it depends on the inner workings of your websocket handler - # and how your chat_service and other classes behave. The following is just an example structure. - with pytest.raises(WebSocketDisconnect): - with client.websocket_connect("api/v1/chat/websocket_test") as websocket: - websocket.send_json({"input": "test"}) - websocket.receive_json() diff --git a/tests/text_experimental_components.py b/tests/text_experimental_components.py new file mode 100644 index 000000000..a4ee47729 --- /dev/null +++ b/tests/text_experimental_components.py @@ -0,0 +1,15 @@ +from langflow.components import experimental + + +def test_python_function_component(): + # Arrange + python_function_component = experimental.PythonFunctionComponent() + + # Act + # function must be a string representation + function = "def function():\n return 'Hello, World!'" + # result is the callable function + result = python_function_component.build(function) + + # Assert + assert result() == "Hello, World!"