{
  "data": {
    "edges": [
      {
        "animated": false,
        "className": "",
        "data": {
          "sourceHandle": {
            "dataType": "StructuredOutput",
            "id": "StructuredOutput-rwiX4",
            "name": "structured_output",
            "output_types": [
              "Data"
            ]
          },
          "targetHandle": {
            "fieldName": "input_data",
            "id": "parser-tptWK",
            "inputTypes": [
              "DataFrame",
              "Data"
            ],
            "type": "other"
          }
        },
        "id": "reactflow__edge-StructuredOutput-rwiX4{œdataTypeœ:œStructuredOutputœ,œidœ:œStructuredOutput-rwiX4œ,œnameœ:œstructured_outputœ,œoutput_typesœ:[œDataœ]}-parser-tptWK{œfieldNameœ:œinput_dataœ,œidœ:œparser-tptWKœ,œinputTypesœ:[œDataFrameœ,œDataœ],œtypeœ:œotherœ}",
        "selected": false,
        "source": "StructuredOutput-rwiX4",
        "sourceHandle": "{œdataTypeœ: œStructuredOutputœ, œidœ: œStructuredOutput-rwiX4œ, œnameœ: œstructured_outputœ, œoutput_typesœ: [œDataœ]}",
        "target": "parser-tptWK",
        "targetHandle": "{œfieldNameœ: œinput_dataœ, œidœ: œparser-tptWKœ, œinputTypesœ: [œDataFrameœ, œDataœ], œtypeœ: œotherœ}"
      },
      {
        "animated": false,
        "className": "",
        "data": {
          "sourceHandle": {
            "dataType": "File",
            "id": "File-dfMwA",
            "name": "message",
            "output_types": [
              "Message"
            ]
          },
          "targetHandle": {
            "fieldName": "input_value",
            "id": "StructuredOutput-rwiX4",
            "inputTypes": [
              "Message"
            ],
            "type": "str"
          }
        },
        "id": "reactflow__edge-File-dfMwA{œdataTypeœ:œFileœ,œidœ:œFile-dfMwAœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-StructuredOutput-rwiX4{œfieldNameœ:œinput_valueœ,œidœ:œStructuredOutput-rwiX4œ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}",
        "selected": false,
        "source": "File-dfMwA",
        "sourceHandle": "{œdataTypeœ: œFileœ, œidœ: œFile-dfMwAœ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}",
        "target": "StructuredOutput-rwiX4",
        "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œStructuredOutput-rwiX4œ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}"
      },
      {
        "animated": false,
        "data": {
          "sourceHandle": {
            "dataType": "LanguageModelComponent",
            "id": "LanguageModelComponent-HrqxT",
            "name": "model_output",
            "output_types": [
              "LanguageModel"
            ]
          },
          "targetHandle": {
            "fieldName": "llm",
            "id": "StructuredOutput-rwiX4",
            "inputTypes": [
              "LanguageModel"
            ],
            "type": "other"
          }
        },
        "id": "xy-edge__LanguageModelComponent-HrqxT{œdataTypeœ:œLanguageModelComponentœ,œidœ:œLanguageModelComponent-HrqxTœ,œnameœ:œmodel_outputœ,œoutput_typesœ:[œLanguageModelœ]}-StructuredOutput-rwiX4{œfieldNameœ:œllmœ,œidœ:œStructuredOutput-rwiX4œ,œinputTypesœ:[œLanguageModelœ],œtypeœ:œotherœ}",
        "selected": false,
        "source": "LanguageModelComponent-HrqxT",
        "sourceHandle": "{œdataTypeœ: œLanguageModelComponentœ, œidœ: œLanguageModelComponent-HrqxTœ, œnameœ: œmodel_outputœ, œoutput_typesœ: [œLanguageModelœ]}",
        "target": "StructuredOutput-rwiX4",
        "targetHandle": "{œfieldNameœ: œllmœ, œidœ: œStructuredOutput-rwiX4œ, œinputTypesœ: [œLanguageModelœ], œtypeœ: œotherœ}"
      },
      {
        "animated": false,
        "data": {
          "sourceHandle": {
            "dataType": "parser",
            "id": "parser-tptWK",
            "name": "parsed_text",
            "output_types": [
              "Message"
            ]
          },
          "targetHandle": {
            "fieldName": "input_value",
            "id": "LanguageModelComponent-QdlJs",
            "inputTypes": [
              "Message"
            ],
            "type": "str"
          }
        },
        "id": "xy-edge__parser-tptWK{œdataTypeœ:œparserœ,œidœ:œparser-tptWKœ,œnameœ:œparsed_textœ,œoutput_typesœ:[œMessageœ]}-LanguageModelComponent-QdlJs{œfieldNameœ:œinput_valueœ,œidœ:œLanguageModelComponent-QdlJsœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}",
        "selected": false,
        "source": "parser-tptWK",
        "sourceHandle": "{œdataTypeœ: œparserœ, œidœ: œparser-tptWKœ, œnameœ: œparsed_textœ, œoutput_typesœ: [œMessageœ]}",
        "target": "LanguageModelComponent-QdlJs",
        "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œLanguageModelComponent-QdlJsœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}"
      },
      {
        "animated": false,
        "data": {
          "sourceHandle": {
            "dataType": "TextInput",
            "id": "TextInput-zN7nF",
            "name": "text",
            "output_types": [
              "Message"
            ]
          },
          "targetHandle": {
            "fieldName": "system_message",
            "id": "LanguageModelComponent-QdlJs",
            "inputTypes": [
              "Message"
            ],
            "type": "str"
          }
        },
        "id": "xy-edge__TextInput-zN7nF{œdataTypeœ:œTextInputœ,œidœ:œTextInput-zN7nFœ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-LanguageModelComponent-QdlJs{œfieldNameœ:œsystem_messageœ,œidœ:œLanguageModelComponent-QdlJsœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}",
        "selected": false,
        "source": "TextInput-zN7nF",
        "sourceHandle": "{œdataTypeœ: œTextInputœ, œidœ: œTextInput-zN7nFœ, œnameœ: œtextœ, œoutput_typesœ: [œMessageœ]}",
        "target": "LanguageModelComponent-QdlJs",
        "targetHandle": "{œfieldNameœ: œsystem_messageœ, œidœ: œLanguageModelComponent-QdlJsœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}"
      },
      {
        "data": {
          "sourceHandle": {
            "dataType": "LanguageModelComponent",
            "id": "LanguageModelComponent-QdlJs",
            "name": "text_output",
            "output_types": [
              "Message"
            ]
          },
          "targetHandle": {
            "fieldName": "input_value",
            "id": "ChatOutput-X6ReB",
            "inputTypes": [
              "Data",
              "DataFrame",
              "Message"
            ],
            "type": "str"
          }
        },
        "id": "xy-edge__LanguageModelComponent-QdlJs{œdataTypeœ:œLanguageModelComponentœ,œidœ:œLanguageModelComponent-QdlJsœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-X6ReB{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-X6ReBœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œstrœ}",
        "source": "LanguageModelComponent-QdlJs",
        "sourceHandle": "{œdataTypeœ: œLanguageModelComponentœ, œidœ: œLanguageModelComponent-QdlJsœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œMessageœ]}",
        "target": "ChatOutput-X6ReB",
        "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-X6ReBœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}"
      }
    ],
    "nodes": [
      {
        "data": {
          "id": "TextInput-zN7nF",
          "node": {
            "base_classes": [
              "Message"
            ],
            "beta": false,
            "category": "inputs",
            "conditional_paths": [],
            "custom_fields": {},
            "description": "Get user text inputs.",
            "display_name": "Text Input",
            "documentation": "",
            "edited": false,
            "field_order": [
              "input_value"
            ],
            "frozen": false,
            "icon": "type",
            "key": "TextInput",
            "legacy": false,
            "lf_version": "1.2.0",
            "metadata": {},
            "minimized": false,
            "output_types": [],
            "outputs": [
              {
                "allows_loop": false,
                "cache": true,
                "display_name": "Output Text",
                "group_outputs": false,
                "method": "text_response",
                "name": "text",
                "selected": "Message",
                "tool_mode": true,
                "types": [
                  "Message"
                ],
                "value": "__UNDEFINED__"
              }
            ],
            "pinned": false,
            "score": 0.0020353564437605998,
            "template": {
              "_type": "Component",
              "code": {
                "advanced": true,
                "dynamic": true,
                "fileTypes": [],
                "file_path": "",
                "info": "",
                "list": false,
                "load_from_db": false,
                "multiline": true,
                "name": "code",
                "password": false,
                "placeholder": "",
                "required": true,
                "show": true,
                "title_case": false,
                "type": "code",
                "value": "from langflow.base.io.text import TextComponent\nfrom langflow.io import MultilineInput, Output\nfrom langflow.schema.message import Message\n\n\nclass TextInputComponent(TextComponent):\n    display_name = \"Text Input\"\n    description = \"Get user text inputs.\"\n    documentation: str = \"https://docs.langflow.org/components-io#text-input\"\n    icon = \"type\"\n    name = \"TextInput\"\n\n    inputs = [\n        MultilineInput(\n            name=\"input_value\",\n            display_name=\"Text\",\n            info=\"Text to be passed as input.\",\n        ),\n    ]\n    outputs = [\n        Output(display_name=\"Output Text\", name=\"text\", method=\"text_response\"),\n    ]\n\n    def text_response(self) -> Message:\n        return Message(\n            text=self.input_value,\n        )\n"
              },
              "input_value": {
                "_input_type": "MultilineInput",
                "advanced": false,
                "display_name": "Text",
                "dynamic": false,
                "info": "Text to be passed as input.",
                "input_types": [
                  "Message"
                ],
                "list": false,
                "list_add_label": "Add More",
                "load_from_db": false,
                "multiline": true,
                "name": "input_value",
                "placeholder": "",
                "required": false,
                "show": true,
                "title_case": false,
                "tool_mode": false,
                "trace_as_input": true,
                "trace_as_metadata": true,
                "type": "str",
                "value": "Generate a single-page portfolio website using HTML and CSS that takes a resume in JSON format as input and dynamically renders the following sections with a well-structured and aesthetic layout:\n\n📌 Sections & Content Requirements:\n\t1.\tHeader:\n\t•\tDisplay the person’s name, job title, and a professional tagline prominently.\n\t•\tEnsure the name is bold and eye-catching, with subtle emphasis on the job title.\n\t2.\tAbout Me:\n\t•\tExtract and enhance the personal summary from the resume, making it engaging, concise, and readable.\n\t•\tUse short, well-structured sentences to improve clarity.\n\t3.\tExperience:\n\t•\tList past job roles with company names, durations, and a refined description of responsibilities.\n\t•\tEnsure descriptions are professionally formatted, with key contributions highlighted.\n\t4.\tProjects:\n\t•\tDisplay projects as a neatly styled list.\n\t•\tEach project includes a title, refined description, technologies used, and rounded buttons linking to GitHub or live demo (if available).\n\t5.\tSkills:\n\t•\tDisplay skills as aesthetic pill-style badges below the Skills section title. Display all skills mentioned\n\t•\tArrange in a well-balanced, ensuring readability and consistent spacing.\n\t6.\tEducation:\n\t•\tList degrees, institutions, and years attended in a clean and professional format.\n\t•\tMaintain uniformity in typography and spacing.\n\t7.\tAwards & Publications  (if any):\n\t•\tIf the resume contains awards or publications, display them in a separate section.\n\t•\tEach entry includes the title, organization, and year, ensuring clean alignment.\n\t8.\tContact:\n\t•\tDisplay email, social media links, and an optional contact button.\n\t•\tEnsure social media links are clearly visible, with modern and accessible icon buttons.\n\n🎨 Styling & Aesthetic Requirements:\n\n✅ Minimalist & Elegant:\n\t•\tClean layout with ample whitespace for breathing room.\n\t•\tConsistent spacing across all sections.\n\n✅ Fast & Lightweight:\n\t•\tUse only HTML & CSS (no JavaScript required).\n\t•\tEnsure a smooth, fast-loading experience.\n\n✅ Beautiful Typography:\n\t•\tUse a modern, professional Google Font that complements the design.\n\t•\tEnsure text readability with proper size, weight, and contrast.\n\n✅ Visually Harmonious Colors & Themes:\n\t•\tFollow a cohesive color palette that ensures a modern, professional feel.\n\t•\tEnsure background colors, text colors, and section dividers are consistent and complementary.\n\t•\tAvoid hard-to-read combinations (e.g., light text on a light background).\n\n✅ Responsive & Readable Design:\n\t•\tMobile-first approach, adapting to desktop, tablet, and mobile views.\n\t•\tMaintain consistency in padding, margins, and alignment.\n\n✅ Dark Mode Support:\n\t•\tAuto-detect system settings and adjust the theme accordingly.\n\t•\tEnsure clear contrasts and readability in both light and dark modes.\n\n✅ Embedded CSS:\n\t•\tEnsure CSS is written directly in the HTML file within <style> tags for easy integration.\n\n🚀 Key Enhancements for a Superior First Impression:\n\t•\tEnsure the color scheme is visually cohesive and all text is legible against the background.\n\t•\tMaintain uniform padding and spacing for a professional, structured appearance.\n\t•\tImprove text formatting, ensuring sections are balanced and visually engaging.\n\t•\tFollow aesthetically pleasing, simple yet modern design principles.\n\n🌟 End Goal:\n\nThe final output should be a well-balanced, visually stunning, and highly readable portfolio website that immediately impresses viewers. The design must be polished, with an intuitive layout, ensuring consistency, clarity, and elegance.\nEnsuring all details in resume are well displayed in portfolio website.\nInclude all experiences, projects and education details from resume in the html code generated.\n"
              }
            },
            "tool_mode": false
          },
          "selected_output": "text",
          "showNode": true,
          "type": "TextInput"
        },
        "dragging": false,
        "id": "TextInput-zN7nF",
        "measured": {
          "height": 204,
          "width": 320
        },
        "position": {
          "x": 1750.5165749650018,
          "y": 1018.4979290286542
        },
        "selected": false,
        "type": "genericNode"
      },
      {
        "data": {
          "id": "ChatOutput-X6ReB",
          "node": {
            "base_classes": [
              "Message"
            ],
            "beta": false,
            "category": "outputs",
            "conditional_paths": [],
            "custom_fields": {},
            "description": "Display a chat message in the Playground.",
            "display_name": "Chat Output",
            "documentation": "",
            "edited": false,
            "field_order": [
              "input_value",
              "should_store_message",
              "sender",
              "sender_name",
              "session_id",
              "data_template",
              "background_color",
              "chat_icon",
              "text_color"
            ],
            "frozen": false,
            "icon": "MessagesSquare",
            "key": "ChatOutput",
            "legacy": false,
            "lf_version": "1.2.0",
            "metadata": {},
            "minimized": true,
            "output_types": [],
            "outputs": [
              {
                "allows_loop": false,
                "cache": true,
                "display_name": "Output Message",
                "group_outputs": false,
                "method": "message_response",
                "name": "message",
                "selected": "Message",
                "tool_mode": true,
                "types": [
                  "Message"
                ],
                "value": "__UNDEFINED__"
              }
            ],
            "pinned": false,
            "score": 0.003169567463043492,
            "template": {
              "_type": "Component",
              "code": {
                "advanced": true,
                "dynamic": true,
                "fileTypes": [],
                "file_path": "",
                "info": "",
                "list": false,
                "load_from_db": false,
                "multiline": true,
                "name": "code",
                "password": false,
                "placeholder": "",
                "required": true,
                "show": true,
                "title_case": false,
                "type": "code",
                "value": "from collections.abc import Generator\nfrom typing import Any\n\nimport orjson\nfrom fastapi.encoders import jsonable_encoder\n\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.helpers.data import safe_convert\nfrom langflow.inputs.inputs import BoolInput, DropdownInput, HandleInput, MessageTextInput\nfrom langflow.schema.data import Data\nfrom langflow.schema.dataframe import DataFrame\nfrom langflow.schema.message import Message\nfrom langflow.schema.properties import Source\nfrom langflow.template.field.base import Output\nfrom langflow.utils.constants import (\n    MESSAGE_SENDER_AI,\n    MESSAGE_SENDER_NAME_AI,\n    MESSAGE_SENDER_USER,\n)\n\n\nclass ChatOutput(ChatComponent):\n    display_name = \"Chat Output\"\n    description = \"Display a chat message in the Playground.\"\n    documentation: str = \"https://docs.langflow.org/components-io#chat-output\"\n    icon = \"MessagesSquare\"\n    name = \"ChatOutput\"\n    minimized = True\n\n    inputs = [\n        HandleInput(\n            name=\"input_value\",\n            display_name=\"Inputs\",\n            info=\"Message to be passed as output.\",\n            input_types=[\"Data\", \"DataFrame\", \"Message\"],\n            required=True,\n        ),\n        BoolInput(\n            name=\"should_store_message\",\n            display_name=\"Store Messages\",\n            info=\"Store the message in the history.\",\n            value=True,\n            advanced=True,\n        ),\n        DropdownInput(\n            name=\"sender\",\n            display_name=\"Sender Type\",\n            options=[MESSAGE_SENDER_AI, MESSAGE_SENDER_USER],\n            value=MESSAGE_SENDER_AI,\n            advanced=True,\n            info=\"Type of sender.\",\n        ),\n        MessageTextInput(\n            name=\"sender_name\",\n            display_name=\"Sender Name\",\n            info=\"Name of the sender.\",\n            value=MESSAGE_SENDER_NAME_AI,\n            advanced=True,\n        ),\n        MessageTextInput(\n            name=\"session_id\",\n            display_name=\"Session ID\",\n            info=\"The session ID of the chat. If empty, the current session ID parameter will be used.\",\n            advanced=True,\n        ),\n        MessageTextInput(\n            name=\"data_template\",\n            display_name=\"Data Template\",\n            value=\"{text}\",\n            advanced=True,\n            info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n        ),\n    ]\n    outputs = [\n        Output(\n            display_name=\"Output Message\",\n            name=\"message\",\n            method=\"message_response\",\n        ),\n    ]\n\n    def _build_source(self, id_: str | None, display_name: str | None, source: str | None) -> Source:\n        source_dict = {}\n        if id_:\n            source_dict[\"id\"] = id_\n        if display_name:\n            source_dict[\"display_name\"] = display_name\n        if source:\n            # Handle case where source is a ChatOpenAI object\n            if hasattr(source, \"model_name\"):\n                source_dict[\"source\"] = source.model_name\n            elif hasattr(source, \"model\"):\n                source_dict[\"source\"] = str(source.model)\n            else:\n                source_dict[\"source\"] = str(source)\n        return Source(**source_dict)\n\n    async def message_response(self) -> Message:\n        # First convert the input to string if needed\n        text = self.convert_to_string()\n\n        # Get source properties\n        source, icon, display_name, source_id = self.get_properties_from_source_component()\n\n        # Create or use existing Message object\n        if isinstance(self.input_value, Message):\n            message = self.input_value\n            # Update message properties\n            message.text = text\n        else:\n            message = Message(text=text)\n\n        # Set message properties\n        message.sender = self.sender\n        message.sender_name = self.sender_name\n        message.session_id = self.session_id\n        message.flow_id = self.graph.flow_id if hasattr(self, \"graph\") else None\n        message.properties.source = self._build_source(source_id, display_name, source)\n\n        # Store message if needed\n        if self.session_id and self.should_store_message:\n            stored_message = await self.send_message(message)\n            self.message.value = stored_message\n            message = stored_message\n\n        self.status = message\n        return message\n\n    def _serialize_data(self, data: Data) -> str:\n        \"\"\"Serialize Data object to JSON string.\"\"\"\n        # Convert data.data to JSON-serializable format\n        serializable_data = jsonable_encoder(data.data)\n        # Serialize with orjson, enabling pretty printing with indentation\n        json_bytes = orjson.dumps(serializable_data, option=orjson.OPT_INDENT_2)\n        # Convert bytes to string and wrap in Markdown code blocks\n        return \"```json\\n\" + json_bytes.decode(\"utf-8\") + \"\\n```\"\n\n    def _validate_input(self) -> None:\n        \"\"\"Validate the input data and raise ValueError if invalid.\"\"\"\n        if self.input_value is None:\n            msg = \"Input data cannot be None\"\n            raise ValueError(msg)\n        if isinstance(self.input_value, list) and not all(\n            isinstance(item, Message | Data | DataFrame | str) for item in self.input_value\n        ):\n            invalid_types = [\n                type(item).__name__\n                for item in self.input_value\n                if not isinstance(item, Message | Data | DataFrame | str)\n            ]\n            msg = f\"Expected Data or DataFrame or Message or str, got {invalid_types}\"\n            raise TypeError(msg)\n        if not isinstance(\n            self.input_value,\n            Message | Data | DataFrame | str | list | Generator | type(None),\n        ):\n            type_name = type(self.input_value).__name__\n            msg = f\"Expected Data or DataFrame or Message or str, Generator or None, got {type_name}\"\n            raise TypeError(msg)\n\n    def convert_to_string(self) -> str | Generator[Any, None, None]:\n        \"\"\"Convert input data to string with proper error handling.\"\"\"\n        self._validate_input()\n        if isinstance(self.input_value, list):\n            clean_data: bool = getattr(self, \"clean_data\", False)\n            return \"\\n\".join([safe_convert(item, clean_data=clean_data) for item in self.input_value])\n        if isinstance(self.input_value, Generator):\n            return self.input_value\n        return safe_convert(self.input_value)\n"
              },
              "data_template": {
                "_input_type": "MessageTextInput",
                "advanced": true,
                "display_name": "Data Template",
                "dynamic": false,
                "info": "Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.",
                "input_types": [
                  "Message"
                ],
                "list": false,
                "list_add_label": "Add More",
                "load_from_db": false,
                "name": "data_template",
                "placeholder": "",
                "required": false,
                "show": true,
                "title_case": false,
                "tool_mode": false,
                "trace_as_input": true,
                "trace_as_metadata": true,
                "type": "str",
                "value": "{text}"
              },
              "input_value": {
                "_input_type": "MessageInput",
                "advanced": false,
                "display_name": "Inputs",
                "dynamic": false,
                "info": "Message to be passed as output.",
                "input_types": [
                  "Data",
                  "DataFrame",
                  "Message"
                ],
                "list": false,
                "list_add_label": "Add More",
                "load_from_db": false,
                "name": "input_value",
                "placeholder": "",
                "required": true,
                "show": true,
                "title_case": false,
                "tool_mode": false,
                "trace_as_input": true,
                "trace_as_metadata": true,
                "type": "str",
                "value": ""
              },
              "sender": {
                "_input_type": "DropdownInput",
                "advanced": true,
                "combobox": false,
                "dialog_inputs": {},
                "display_name": "Sender Type",
                "dynamic": false,
                "info": "Type of sender.",
                "name": "sender",
                "options": [
                  "Machine",
                  "User"
                ],
                "options_metadata": [],
                "placeholder": "",
                "required": false,
                "show": true,
                "title_case": false,
                "tool_mode": false,
                "trace_as_metadata": true,
                "type": "str",
                "value": "Machine"
              },
              "sender_name": {
                "_input_type": "MessageTextInput",
                "advanced": true,
                "display_name": "Sender Name",
                "dynamic": false,
                "info": "Name of the sender.",
                "input_types": [
                  "Message"
                ],
                "list": false,
                "list_add_label": "Add More",
                "load_from_db": false,
                "name": "sender_name",
                "placeholder": "",
                "required": false,
                "show": true,
                "title_case": false,
                "tool_mode": false,
                "trace_as_input": true,
                "trace_as_metadata": true,
                "type": "str",
                "value": "AI"
              },
              "session_id": {
                "_input_type": "MessageTextInput",
                "advanced": true,
                "display_name": "Session ID",
                "dynamic": false,
                "info": "The session ID of the chat. If empty, the current session ID parameter will be used.",
                "input_types": [
                  "Message"
                ],
                "list": false,
                "list_add_label": "Add More",
                "load_from_db": false,
                "name": "session_id",
                "placeholder": "",
                "required": false,
                "show": true,
                "title_case": false,
                "tool_mode": false,
                "trace_as_input": true,
                "trace_as_metadata": true,
                "type": "str",
                "value": ""
              },
              "should_store_message": {
                "_input_type": "BoolInput",
                "advanced": true,
                "display_name": "Store Messages",
                "dynamic": false,
                "info": "Store the message in the history.",
                "list": false,
                "list_add_label": "Add More",
                "name": "should_store_message",
                "placeholder": "",
                "required": false,
                "show": true,
                "title_case": false,
                "tool_mode": false,
                "trace_as_metadata": true,
                "type": "bool",
                "value": true
              }
            },
            "tool_mode": false
          },
          "showNode": false,
          "type": "ChatOutput"
        },
        "dragging": false,
        "id": "ChatOutput-X6ReB",
        "measured": {
          "height": 48,
          "width": 192
        },
        "position": {
          "x": 2791.628210329036,
          "y": 590.4917809253919
        },
        "selected": false,
        "type": "genericNode"
      },
      {
        "data": {
          "id": "note-acs4U",
          "node": {
            "description": "### 💡 Upload your resume here",
            "display_name": "",
            "documentation": "",
            "template": {
              "backgroundColor": "transparent"
            }
          },
          "type": "note"
        },
        "dragging": false,
        "height": 358,
        "id": "note-acs4U",
        "measured": {
          "height": 358,
          "width": 346
        },
        "position": {
          "x": 956.8090415611422,
          "y": 591.8723166928154
        },
        "resizing": false,
        "selected": false,
        "type": "noteNode",
        "width": 346
      },
      {
        "data": {
          "id": "note-WJEOM",
          "node": {
            "description": "## 📝 Portfolio Website Code Generator\n\nYour uploaded resume is parsed into a structured format, and output as HTML/CSS code for your own resume website!\n\n✅ **Accepted Formats:** PDF or TXT  \n✅ To ensure readability, provide clear headings, bullet points, and proper formatting. \n### 📌 Structured output fields:\n1. 🏷 **Full Name** - Candidate's full name  \n2. 📧 **Email** - A valid email address  \n3. 📞 **Phone Number** - Contact number  \n4. 🔗 **LinkedIn** - LinkedIn profile URL  \n5. 🖥 **GitHub** - GitHub profile URL (if applicable)  \n6. 🌐 **Portfolio** - Personal website or portfolio URL  \n7. 🛂 **Visa Status** - Work authorization details (if applicable)  \n8. 📝 **Summary** - A brief professional summary or objective statement  \n9. 💼 **Experience** - Work experience details (in dictionary format)  \n10. 🎓 **Education** - Education details (in dictionary format)  \n11. 🛠 **Skills** - Skills mentioned in the resume (comma-separated)  \n12. 🚀 **Projects** - Titles, descriptions, and details of projects.",
            "display_name": "",
            "documentation": "",
            "template": {}
          },
          "type": "note"
        },
        "dragging": false,
        "height": 621,
        "id": "note-WJEOM",
        "measured": {
          "height": 621,
          "width": 478
        },
        "position": {
          "x": 386.51295365584554,
          "y": 170.2187453922128
        },
        "resizing": false,
        "selected": false,
        "type": "noteNode",
        "width": 478
      },
      {
        "data": {
          "id": "note-SNz2K",
          "node": {
            "description": "### 💡 Click **Open table** to view the schema",
            "display_name": "",
            "documentation": "",
            "template": {
              "backgroundColor": "transparent"
            }
          },
          "type": "note"
        },
        "dragging": false,
        "height": 438,
        "id": "note-SNz2K",
        "measured": {
          "height": 438,
          "width": 359
        },
        "position": {
          "x": 1293.169988591412,
          "y": 592.6453642134813
        },
        "resizing": false,
        "selected": false,
        "type": "noteNode",
        "width": 359
      },
      {
        "data": {
          "id": "note-wY2lq",
          "node": {
            "description": "### 💡 Add your Anthropic API key here",
            "display_name": "",
            "documentation": "",
            "template": {
              "backgroundColor": "transparent"
            }
          },
          "type": "note"
        },
        "dragging": false,
        "height": 324,
        "id": "note-wY2lq",
        "measured": {
          "height": 324,
          "width": 362
        },
        "position": {
          "x": 924.6299565901533,
          "y": 1.8200755150596493
        },
        "resizing": false,
        "selected": false,
        "type": "noteNode",
        "width": 362
      },
      {
        "data": {
          "id": "note-uh1Dy",
          "node": {
            "description": "### 💡 Add your Anthropic API key here",
            "display_name": "",
            "documentation": "",
            "template": {
              "backgroundColor": "transparent"
            }
          },
          "type": "note"
        },
        "dragging": false,
        "height": 324,
        "id": "note-uh1Dy",
        "measured": {
          "height": 324,
          "width": 344
        },
        "position": {
          "x": 2191.028572823402,
          "y": 446.51091539068995
        },
        "resizing": false,
        "selected": false,
        "type": "noteNode",
        "width": 344
      },
      {
        "data": {
          "id": "StructuredOutput-rwiX4",
          "node": {
            "base_classes": [
              "Data",
              "DataFrame"
            ],
            "beta": false,
            "conditional_paths": [],
            "custom_fields": {},
            "description": "Uses an LLM to generate structured data. Ideal for extraction and consistency.",
            "display_name": "Structured Output",
            "documentation": "",
            "edited": false,
            "field_order": [
              "llm",
              "input_value",
              "system_prompt",
              "schema_name",
              "output_schema",
              "multiple"
            ],
            "frozen": false,
            "icon": "braces",
            "legacy": false,
            "lf_version": "1.2.0",
            "metadata": {},
            "minimized": false,
            "output_types": [],
            "outputs": [
              {
                "allows_loop": false,
                "cache": true,
                "display_name": "Structured Output",
                "group_outputs": false,
                "method": "build_structured_output",
                "name": "structured_output",
                "selected": "Data",
                "tool_mode": true,
                "types": [
                  "Data"
                ],
                "value": "__UNDEFINED__"
              },
              {
                "allows_loop": false,
                "cache": true,
                "display_name": "Structured Output",
                "group_outputs": false,
                "method": "build_structured_dataframe",
                "name": "dataframe_output",
                "selected": "DataFrame",
                "tool_mode": true,
                "types": [
                  "DataFrame"
                ],
                "value": "__UNDEFINED__"
              }
            ],
            "pinned": false,
            "template": {
              "_type": "Component",
              "code": {
                "advanced": true,
                "dynamic": true,
                "fileTypes": [],
                "file_path": "",
                "info": "",
                "list": false,
                "load_from_db": false,
                "multiline": true,
                "name": "code",
                "password": false,
                "placeholder": "",
                "required": true,
                "show": true,
                "title_case": false,
                "type": "code",
                "value": "from pydantic import BaseModel, Field, create_model\nfrom trustcall import create_extractor\n\nfrom langflow.base.models.chat_result import get_chat_result\nfrom langflow.custom.custom_component.component import Component\nfrom langflow.helpers.base_model import build_model_from_schema\nfrom langflow.io import (\n    HandleInput,\n    MessageTextInput,\n    MultilineInput,\n    Output,\n    TableInput,\n)\nfrom langflow.schema.data import Data\nfrom langflow.schema.dataframe import DataFrame\nfrom langflow.schema.table import EditMode\n\n\nclass StructuredOutputComponent(Component):\n    display_name = \"Structured Output\"\n    description = \"Uses an LLM to generate structured data. Ideal for extraction and consistency.\"\n    documentation: str = \"https://docs.langflow.org/components-processing#structured-output\"\n    name = \"StructuredOutput\"\n    icon = \"braces\"\n\n    inputs = [\n        HandleInput(\n            name=\"llm\",\n            display_name=\"Language Model\",\n            info=\"The language model to use to generate the structured output.\",\n            input_types=[\"LanguageModel\"],\n            required=True,\n        ),\n        MultilineInput(\n            name=\"input_value\",\n            display_name=\"Input Message\",\n            info=\"The input message to the language model.\",\n            tool_mode=True,\n            required=True,\n        ),\n        MultilineInput(\n            name=\"system_prompt\",\n            display_name=\"Format Instructions\",\n            info=\"The instructions to the language model for formatting the output.\",\n            value=(\n                \"You are an AI that extracts structured JSON objects from unstructured text. \"\n                \"Use a predefined schema with expected types (str, int, float, bool, dict). \"\n                \"Extract ALL relevant instances that match the schema - if multiple patterns exist, capture them all. \"\n                \"Fill missing or ambiguous values with defaults: null for missing values. \"\n                \"Remove exact duplicates but keep variations that have different field values. \"\n                \"Always return valid JSON in the expected format, never throw errors. \"\n                \"If multiple objects can be extracted, return them all in the structured format.\"\n            ),\n            required=True,\n            advanced=True,\n        ),\n        MessageTextInput(\n            name=\"schema_name\",\n            display_name=\"Schema Name\",\n            info=\"Provide a name for the output data schema.\",\n            advanced=True,\n        ),\n        TableInput(\n            name=\"output_schema\",\n            display_name=\"Output Schema\",\n            info=\"Define the structure and data types for the model's output.\",\n            required=True,\n            # TODO: remove deault value\n            table_schema=[\n                {\n                    \"name\": \"name\",\n                    \"display_name\": \"Name\",\n                    \"type\": \"str\",\n                    \"description\": \"Specify the name of the output field.\",\n                    \"default\": \"field\",\n                    \"edit_mode\": EditMode.INLINE,\n                },\n                {\n                    \"name\": \"description\",\n                    \"display_name\": \"Description\",\n                    \"type\": \"str\",\n                    \"description\": \"Describe the purpose of the output field.\",\n                    \"default\": \"description of field\",\n                    \"edit_mode\": EditMode.POPOVER,\n                },\n                {\n                    \"name\": \"type\",\n                    \"display_name\": \"Type\",\n                    \"type\": \"str\",\n                    \"edit_mode\": EditMode.INLINE,\n                    \"description\": (\"Indicate the data type of the output field (e.g., str, int, float, bool, dict).\"),\n                    \"options\": [\"str\", \"int\", \"float\", \"bool\", \"dict\"],\n                    \"default\": \"str\",\n                },\n                {\n                    \"name\": \"multiple\",\n                    \"display_name\": \"As List\",\n                    \"type\": \"boolean\",\n                    \"description\": \"Set to True if this output field should be a list of the specified type.\",\n                    \"default\": \"False\",\n                    \"edit_mode\": EditMode.INLINE,\n                },\n            ],\n            value=[\n                {\n                    \"name\": \"field\",\n                    \"description\": \"description of field\",\n                    \"type\": \"str\",\n                    \"multiple\": \"False\",\n                }\n            ],\n        ),\n    ]\n\n    outputs = [\n        Output(\n            name=\"structured_output\",\n            display_name=\"Structured Output\",\n            method=\"build_structured_output\",\n        ),\n        Output(\n            name=\"dataframe_output\",\n            display_name=\"Structured Output\",\n            method=\"build_structured_dataframe\",\n        ),\n    ]\n\n    def build_structured_output_base(self):\n        schema_name = self.schema_name or \"OutputModel\"\n\n        if not hasattr(self.llm, \"with_structured_output\"):\n            msg = \"Language model does not support structured output.\"\n            raise TypeError(msg)\n        if not self.output_schema:\n            msg = \"Output schema cannot be empty\"\n            raise ValueError(msg)\n\n        output_model_ = build_model_from_schema(self.output_schema)\n\n        output_model = create_model(\n            schema_name,\n            __doc__=f\"A list of {schema_name}.\",\n            objects=(list[output_model_], Field(description=f\"A list of {schema_name}.\")),  # type: ignore[valid-type]\n        )\n\n        try:\n            llm_with_structured_output = create_extractor(self.llm, tools=[output_model])\n        except NotImplementedError as exc:\n            msg = f\"{self.llm.__class__.__name__} does not support structured output.\"\n            raise TypeError(msg) from exc\n\n        config_dict = {\n            \"run_name\": self.display_name,\n            \"project_name\": self.get_project_name(),\n            \"callbacks\": self.get_langchain_callbacks(),\n        }\n        result = get_chat_result(\n            runnable=llm_with_structured_output,\n            system_message=self.system_prompt,\n            input_value=self.input_value,\n            config=config_dict,\n        )\n\n        # OPTIMIZATION NOTE: Simplified processing based on trustcall response structure\n        # Handle non-dict responses (shouldn't happen with trustcall, but defensive)\n        if not isinstance(result, dict):\n            return result\n\n        # Extract first response and convert BaseModel to dict\n        responses = result.get(\"responses\", [])\n        if not responses:\n            return result\n\n        # Convert BaseModel to dict (creates the \"objects\" key)\n        first_response = responses[0]\n        structured_data = first_response.model_dump() if isinstance(first_response, BaseModel) else first_response\n\n        # Extract the objects array (guaranteed to exist due to our Pydantic model structure)\n        return structured_data.get(\"objects\", structured_data)\n\n    def build_structured_output(self) -> Data:\n        output = self.build_structured_output_base()\n        if not isinstance(output, list) or not output:\n            # handle empty or unexpected type case\n            msg = \"No structured output returned\"\n            raise ValueError(msg)\n        if len(output) == 1:\n            return Data(data=output[0])\n        if len(output) > 1:\n            # Multiple outputs - wrap them in a results container\n            return Data(data={\"results\": output})\n        return Data()\n\n    def build_structured_dataframe(self) -> DataFrame:\n        output = self.build_structured_output_base()\n        if not isinstance(output, list) or not output:\n            # handle empty or unexpected type case\n            msg = \"No structured output returned\"\n            raise ValueError(msg)\n        if len(output) == 1:\n            # For single dictionary, wrap in a list to create DataFrame with one row\n            return DataFrame([output[0]])\n        if len(output) > 1:\n            # Multiple outputs - convert to DataFrame directly\n            return DataFrame(output)\n        return DataFrame()\n"
              },
              "input_value": {
                "_input_type": "MessageTextInput",
                "advanced": false,
                "display_name": "Input Message",
                "dynamic": false,
                "info": "The input message to the language model.",
                "input_types": [
                  "Message"
                ],
                "list": false,
                "list_add_label": "Add More",
                "load_from_db": false,
                "name": "input_value",
                "placeholder": "",
                "required": true,
                "show": true,
                "title_case": false,
                "tool_mode": true,
                "trace_as_input": true,
                "trace_as_metadata": true,
                "type": "str",
                "value": ""
              },
              "llm": {
                "_input_type": "HandleInput",
                "advanced": false,
                "display_name": "Language Model",
                "dynamic": false,
                "info": "The language model to use to generate the structured output.",
                "input_types": [
                  "LanguageModel"
                ],
                "list": false,
                "list_add_label": "Add More",
                "name": "llm",
                "placeholder": "",
                "required": true,
                "show": true,
                "title_case": false,
                "trace_as_metadata": true,
                "type": "other",
                "value": ""
              },
              "output_schema": {
                "_input_type": "TableInput",
                "advanced": false,
                "display_name": "Output Schema",
                "dynamic": false,
                "info": "Define the structure and data types for the model's output.",
                "is_list": true,
                "list_add_label": "Add More",
                "load_from_db": false,
                "name": "output_schema",
                "placeholder": "",
                "required": true,
                "show": true,
                "table_icon": "Table",
                "table_schema": {
                  "columns": [
                    {
                      "default": "field",
                      "description": "Specify the name of the output field.",
                      "disable_edit": false,
                      "display_name": "Name",
                      "edit_mode": "inline",
                      "filterable": true,
                      "formatter": "text",
                      "hidden": false,
                      "name": "name",
                      "sortable": true,
                      "type": "str"
                    },
                    {
                      "default": "description of field",
                      "description": "Describe the purpose of the output field.",
                      "disable_edit": false,
                      "display_name": "Description",
                      "edit_mode": "popover",
                      "filterable": true,
                      "formatter": "text",
                      "hidden": false,
                      "name": "description",
                      "sortable": true,
                      "type": "str"
                    },
                    {
                      "default": "str",
                      "description": "Indicate the data type of the output field (e.g., str, int, float, bool, list, dict).",
                      "disable_edit": false,
                      "display_name": "Type",
                      "edit_mode": "inline",
                      "filterable": true,
                      "formatter": "text",
                      "hidden": false,
                      "name": "type",
                      "options": [
                        "str",
                        "int",
                        "float",
                        "bool",
                        "list",
                        "dict"
                      ],
                      "sortable": true,
                      "type": "str"
                    },
                    {
                      "default": false,
                      "description": "Set to True if this output field should be a list of the specified type.",
                      "disable_edit": false,
                      "display_name": "Multiple",
                      "edit_mode": "inline",
                      "filterable": true,
                      "formatter": "boolean",
                      "hidden": false,
                      "name": "multiple",
                      "sortable": true,
                      "type": "boolean"
                    }
                  ]
                },
                "title_case": false,
                "tool_mode": false,
                "trace_as_metadata": true,
                "trigger_icon": "Table",
                "trigger_text": "Open table",
                "type": "table",
                "value": [
                  {
                    "description": "Full name of the candidate",
                    "multiple": "False",
                    "name": "full_name",
                    "type": "text"
                  },
                  {
                    "description": "Email ID",
                    "multiple": "False",
                    "name": "email",
                    "type": "text"
                  },
                  {
                    "description": "contact number",
                    "multiple": "False",
                    "name": "phone_number",
                    "type": "text"
                  },
                  {
                    "description": "LinkedIn URL",
                    "multiple": "False",
                    "name": "linkedin",
                    "type": "text"
                  },
                  {
                    "description": "GitHub profile URL (if applicable)",
                    "multiple": "False",
                    "name": "github",
                    "type": "text"
                  },
                  {
                    "description": "Personal website or portfolio URL",
                    "multiple": "False",
                    "name": "portfolio",
                    "type": "text"
                  },
                  {
                    "description": "Visa/work authorization details (if applicable)",
                    "multiple": "False",
                    "name": "visa_status",
                    "type": "text"
                  },
                  {
                    "description": "Short professional summary or objective statement",
                    "multiple": "False",
                    "name": "summary",
                    "type": "text"
                  },
                  {
                    "description": "dictionaries of experience details with following keys:\n    \"job_title\": Job position/title,\n\t\"company_name\": Employer or organization\n\t\"location\": Job location (remote/in-office)\n\t\"start_date\": Start date (YYYY-MM)\n\t\"end_date\": End date or \"Present\"\n\t\"responsibilities\": List of responsibilities and tasks\n\t\"achievements\": List of key achievements and contributions",
                    "multiple": "True",
                    "name": "experience",
                    "type": "dict"
                  },
                  {
                    "description": "dictionaries of Education details with following keys:\n\"degree\": Degree obtained (e.g., B.Sc., M.Sc., Ph.D.),\n\"field_of_study\": Major or specialization,\n\"institution\": University/college name,\n\"location\": Location of institution,\n\"start_date\": Start date (YYYY-MM),\n\"end_date\": Graduation/completion date (YYYY-MM),\n\"gpa\": GPA/grade (if available),\n\"relevant_courses\": List of relevant coursework (if applicable)",
                    "multiple": "True",
                    "name": "education",
                    "type": "dict"
                  },
                  {
                    "description": "skills mentioned in the resume.comma seperated.",
                    "multiple": "False",
                    "name": "skills",
                    "type": "list"
                  },
                  {
                    "description": "title and description and details of the project. Including the skills and technologies used.",
                    "multiple": "False",
                    "name": "projects",
                    "type": "text"
                  }
                ]
              },
              "schema_name": {
                "_input_type": "MessageTextInput",
                "advanced": true,
                "display_name": "Schema Name",
                "dynamic": false,
                "info": "Provide a name for the output data schema.",
                "input_types": [
                  "Message"
                ],
                "list": false,
                "list_add_label": "Add More",
                "load_from_db": false,
                "name": "schema_name",
                "placeholder": "",
                "required": false,
                "show": true,
                "title_case": false,
                "tool_mode": false,
                "trace_as_input": true,
                "trace_as_metadata": true,
                "type": "str",
                "value": ""
              },
              "system_prompt": {
                "_input_type": "MultilineInput",
                "advanced": true,
                "copy_field": false,
                "display_name": "Format Instructions",
                "dynamic": false,
                "info": "The instructions to the language model for formatting the output.",
                "input_types": [
                  "Message"
                ],
                "list": false,
                "list_add_label": "Add More",
                "load_from_db": false,
                "multiline": true,
                "name": "system_prompt",
                "placeholder": "",
                "required": true,
                "show": true,
                "title_case": false,
                "tool_mode": false,
                "trace_as_input": true,
                "trace_as_metadata": true,
                "type": "str",
                "value": "You are an AI that extracts structured JSON objects from unstructured text. Use a predefined schema with expected types (str, int, float, bool, dict). Extract ALL relevant instances that match the schema - if multiple patterns exist, capture them all. Fill missing or ambiguous values with defaults: null for missing values. Remove exact duplicates but keep variations that have different field values. Always return valid JSON in the expected format, never throw errors. If multiple objects can be extracted, return them all in the structured format."
              }
            },
            "tool_mode": false
          },
          "selected_output": "structured_output_dataframe",
          "showNode": true,
          "type": "StructuredOutput"
        },
        "dragging": false,
        "id": "StructuredOutput-rwiX4",
        "measured": {
          "height": 349,
          "width": 320
        },
        "position": {
          "x": 1306.940204747624,
          "y": 645.3388247558626
        },
        "selected": false,
        "type": "genericNode"
      },
      {
        "data": {
          "id": "parser-tptWK",
          "node": {
            "base_classes": [
              "Message"
            ],
            "beta": false,
            "category": "processing",
            "conditional_paths": [],
            "custom_fields": {},
            "description": "Format a DataFrame or Data object into text using a template. Enable 'Stringify' to convert input into a readable string instead.",
            "display_name": "Parser",
            "documentation": "",
            "edited": false,
            "field_order": [
              "mode",
              "pattern",
              "input_data",
              "sep"
            ],
            "frozen": false,
            "icon": "braces",
            "key": "parser",
            "legacy": false,
            "lf_version": "1.2.0",
            "metadata": {},
            "minimized": false,
            "output_types": [],
            "outputs": [
              {
                "allows_loop": false,
                "cache": true,
                "display_name": "Parsed Text",
                "method": "parse_combined_text",
                "name": "parsed_text",
                "selected": "Message",
                "tool_mode": true,
                "types": [
                  "Message"
                ],
                "value": "__UNDEFINED__"
              }
            ],
            "pinned": false,
            "score": 2.220446049250313e-16,
            "template": {
              "_type": "Component",
              "code": {
                "advanced": true,
                "dynamic": true,
                "fileTypes": [],
                "file_path": "",
                "info": "",
                "list": false,
                "load_from_db": false,
                "multiline": true,
                "name": "code",
                "password": false,
                "placeholder": "",
                "required": true,
                "show": true,
                "title_case": false,
                "type": "code",
                "value": "import json\nfrom typing import Any\n\nfrom langflow.custom import Component\nfrom langflow.io import (\n    BoolInput,\n    HandleInput,\n    MessageTextInput,\n    MultilineInput,\n    Output,\n    TabInput,\n)\nfrom langflow.schema import Data, DataFrame\nfrom langflow.schema.message import Message\n\n\nclass ParserComponent(Component):\n    name = \"parser\"\n    display_name = \"Parser\"\n    description = (\n        \"Format a DataFrame or Data object into text using a template. \"\n        \"Enable 'Stringify' to convert input into a readable string instead.\"\n    )\n    icon = \"braces\"\n\n    inputs = [\n        TabInput(\n            name=\"mode\",\n            display_name=\"Mode\",\n            options=[\"Parser\", \"Stringify\"],\n            value=\"Parser\",\n            info=\"Convert into raw string instead of using a template.\",\n            real_time_refresh=True,\n        ),\n        MultilineInput(\n            name=\"pattern\",\n            display_name=\"Template\",\n            info=(\n                \"Use variables within curly brackets to extract column values for DataFrames \"\n                \"or key values for Data.\"\n                \"For example: `Name: {Name}, Age: {Age}, Country: {Country}`\"\n            ),\n            value=\"Text: {text}\",  # Example default\n            dynamic=True,\n            show=True,\n            required=True,\n        ),\n        HandleInput(\n            name=\"input_data\",\n            display_name=\"Data or DataFrame\",\n            input_types=[\"DataFrame\", \"Data\"],\n            info=\"Accepts either a DataFrame or a Data object.\",\n            required=True,\n        ),\n        MessageTextInput(\n            name=\"sep\",\n            display_name=\"Separator\",\n            advanced=True,\n            value=\"\\n\",\n            info=\"String used to separate rows/items.\",\n        ),\n    ]\n\n    outputs = [\n        Output(\n            display_name=\"Parsed Text\",\n            name=\"parsed_text\",\n            info=\"Formatted text output.\",\n            method=\"parse_combined_text\",\n        ),\n    ]\n\n    def update_build_config(self, build_config, field_value, field_name=None):\n        \"\"\"Dynamically hide/show `template` and enforce requirement based on `stringify`.\"\"\"\n        if field_name == \"mode\":\n            build_config[\"pattern\"][\"show\"] = self.mode == \"Parser\"\n            build_config[\"pattern\"][\"required\"] = self.mode == \"Parser\"\n            if field_value:\n                clean_data = BoolInput(\n                    name=\"clean_data\",\n                    display_name=\"Clean Data\",\n                    info=(\n                        \"Enable to clean the data by removing empty rows and lines \"\n                        \"in each cell of the DataFrame/ Data object.\"\n                    ),\n                    value=True,\n                    advanced=True,\n                    required=False,\n                )\n                build_config[\"clean_data\"] = clean_data.to_dict()\n            else:\n                build_config.pop(\"clean_data\", None)\n\n        return build_config\n\n    def _clean_args(self):\n        \"\"\"Prepare arguments based on input type.\"\"\"\n        input_data = self.input_data\n\n        match input_data:\n            case list() if all(isinstance(item, Data) for item in input_data):\n                msg = \"List of Data objects is not supported.\"\n                raise ValueError(msg)\n            case DataFrame():\n                return input_data, None\n            case Data():\n                return None, input_data\n            case dict() if \"data\" in input_data:\n                try:\n                    if \"columns\" in input_data:  # Likely a DataFrame\n                        return DataFrame.from_dict(input_data), None\n                    # Likely a Data object\n                    return None, Data(**input_data)\n                except (TypeError, ValueError, KeyError) as e:\n                    msg = f\"Invalid structured input provided: {e!s}\"\n                    raise ValueError(msg) from e\n            case _:\n                msg = f\"Unsupported input type: {type(input_data)}. Expected DataFrame or Data.\"\n                raise ValueError(msg)\n\n    def parse_combined_text(self) -> Message:\n        \"\"\"Parse all rows/items into a single text or convert input to string if `stringify` is enabled.\"\"\"\n        # Early return for stringify option\n        if self.mode == \"Stringify\":\n            return self.convert_to_string()\n\n        df, data = self._clean_args()\n\n        lines = []\n        if df is not None:\n            for _, row in df.iterrows():\n                formatted_text = self.pattern.format(**row.to_dict())\n                lines.append(formatted_text)\n        elif data is not None:\n            formatted_text = self.pattern.format(**data.data)\n            lines.append(formatted_text)\n\n        combined_text = self.sep.join(lines)\n        self.status = combined_text\n        return Message(text=combined_text)\n\n    def _safe_convert(self, data: Any) -> str:\n        \"\"\"Safely convert input data to string.\"\"\"\n        try:\n            if isinstance(data, str):\n                return data\n            if isinstance(data, Message):\n                return data.get_text()\n            if isinstance(data, Data):\n                return json.dumps(data.data)\n            if isinstance(data, DataFrame):\n                if hasattr(self, \"clean_data\") and self.clean_data:\n                    # Remove empty rows\n                    data = data.dropna(how=\"all\")\n                    # Remove empty lines in each cell\n                    data = data.replace(r\"^\\s*$\", \"\", regex=True)\n                    # Replace multiple newlines with a single newline\n                    data = data.replace(r\"\\n+\", \"\\n\", regex=True)\n                return data.to_markdown(index=False)\n            return str(data)\n        except (ValueError, TypeError, AttributeError) as e:\n            msg = f\"Error converting data: {e!s}\"\n            raise ValueError(msg) from e\n\n    def convert_to_string(self) -> Message:\n        \"\"\"Convert input data to string with proper error handling.\"\"\"\n        result = \"\"\n        if isinstance(self.input_data, list):\n            result = \"\\n\".join([self._safe_convert(item) for item in self.input_data])\n        else:\n            result = self._safe_convert(self.input_data)\n        self.log(f\"Converted to string with length: {len(result)}\")\n\n        message = Message(text=result)\n        self.status = message\n        return message\n"
              },
              "input_data": {
                "_input_type": "HandleInput",
                "advanced": false,
                "display_name": "Data or DataFrame",
                "dynamic": false,
                "info": "Accepts either a DataFrame or a Data object.",
                "input_types": [
                  "DataFrame",
                  "Data"
                ],
                "list": false,
                "list_add_label": "Add More",
                "name": "input_data",
                "placeholder": "",
                "required": true,
                "show": true,
                "title_case": false,
                "trace_as_metadata": true,
                "type": "other",
                "value": ""
              },
              "mode": {
                "_input_type": "TabInput",
                "advanced": false,
                "display_name": "Mode",
                "dynamic": false,
                "info": "Convert into raw string instead of using a template.",
                "name": "mode",
                "options": [
                  "Parser",
                  "Stringify"
                ],
                "placeholder": "",
                "real_time_refresh": true,
                "required": false,
                "show": true,
                "title_case": false,
                "tool_mode": false,
                "trace_as_metadata": true,
                "type": "tab",
                "value": "Stringify"
              },
              "pattern": {
                "_input_type": "MultilineInput",
                "advanced": false,
                "copy_field": false,
                "display_name": "Template",
                "dynamic": true,
                "info": "Use variables within curly brackets to extract column values for DataFrames or key values for Data.For example: `Name: {Name}, Age: {Age}, Country: {Country}`",
                "input_types": [
                  "Message"
                ],
                "list": false,
                "list_add_label": "Add More",
                "load_from_db": false,
                "multiline": true,
                "name": "pattern",
                "placeholder": "",
                "required": true,
                "show": false,
                "title_case": false,
                "tool_mode": false,
                "trace_as_input": true,
                "trace_as_metadata": true,
                "type": "str",
                "value": "Text: {text}"
              },
              "sep": {
                "_input_type": "MessageTextInput",
                "advanced": true,
                "display_name": "Separator",
                "dynamic": false,
                "info": "String used to separate rows/items.",
                "input_types": [
                  "Message"
                ],
                "list": false,
                "list_add_label": "Add More",
                "load_from_db": false,
                "name": "sep",
                "placeholder": "",
                "required": false,
                "show": true,
                "title_case": false,
                "tool_mode": false,
                "trace_as_input": true,
                "trace_as_metadata": true,
                "type": "str",
                "value": "\n"
              }
            },
            "tool_mode": false
          },
          "selected_output": "parsed_text",
          "showNode": true,
          "type": "parser"
        },
        "dragging": false,
        "id": "parser-tptWK",
        "measured": {
          "height": 278,
          "width": 320
        },
        "position": {
          "x": 1739.3994366258964,
          "y": 415.8221978438559
        },
        "selected": false,
        "type": "genericNode"
      },
      {
        "data": {
          "id": "File-dfMwA",
          "node": {
            "base_classes": [
              "Message"
            ],
            "beta": false,
            "conditional_paths": [],
            "custom_fields": {},
            "description": "Loads content from one or more files.",
            "display_name": "File",
            "documentation": "",
            "edited": false,
            "field_order": [
              "path",
              "file_path",
              "separator",
              "silent_errors",
              "delete_server_file_after_processing",
              "ignore_unsupported_extensions",
              "ignore_unspecified_files",
              "use_multithreading",
              "concurrency_multithreading"
            ],
            "frozen": false,
            "icon": "file-text",
            "legacy": false,
            "metadata": {},
            "minimized": false,
            "output_types": [],
            "outputs": [
              {
                "allows_loop": false,
                "cache": true,
                "display_name": "Raw Content",
                "group_outputs": false,
                "method": "load_files_message",
                "name": "message",
                "selected": "Message",
                "tool_mode": true,
                "types": [
                  "Message"
                ],
                "value": "__UNDEFINED__"
              }
            ],
            "pinned": false,
            "template": {
              "_type": "Component",
              "advanced_mode": {
                "_input_type": "BoolInput",
                "advanced": false,
                "display_name": "Advanced Parser",
                "dynamic": false,
                "info": "Enable advanced document processing and export with Docling for PDFs, images, and office documents. Available only for single file processing.Note that advanced document processing can consume significant resources.",
                "list": false,
                "list_add_label": "Add More",
                "name": "advanced_mode",
                "placeholder": "",
                "real_time_refresh": true,
                "required": false,
                "show": false,
                "title_case": false,
                "tool_mode": false,
                "trace_as_metadata": true,
                "type": "bool",
                "value": false
              },
              "code": {
                "advanced": true,
                "dynamic": true,
                "fileTypes": [],
                "file_path": "",
                "info": "",
                "list": false,
                "load_from_db": false,
                "multiline": true,
                "name": "code",
                "password": false,
                "placeholder": "",
                "required": true,
                "show": true,
                "title_case": false,
                "type": "code",
                "value": "\"\"\"Enhanced file component with Docling support and process isolation.\n\nNotes:\n-----\n- ALL Docling parsing/export runs in a separate OS process to prevent memory\n  growth and native library state from impacting the main Langflow process.\n- Standard text/structured parsing continues to use existing BaseFileComponent\n  utilities (and optional threading via `parallel_load_data`).\n\"\"\"\n\nfrom __future__ import annotations\n\nimport json\nimport subprocess\nimport sys\nimport textwrap\nfrom copy import deepcopy\nfrom typing import TYPE_CHECKING, Any\n\nfrom langflow.base.data.base_file import BaseFileComponent\nfrom langflow.base.data.utils import TEXT_FILE_TYPES, parallel_load_data, parse_text_file_to_data\nfrom langflow.io import (\n    BoolInput,\n    DropdownInput,\n    FileInput,\n    IntInput,\n    MessageTextInput,\n    Output,\n    StrInput,\n)\nfrom langflow.schema.data import Data\nfrom langflow.schema.message import Message\n\nif TYPE_CHECKING:\n    from langflow.schema import DataFrame\n\n\nclass FileComponent(BaseFileComponent):\n    \"\"\"File component with optional Docling processing (isolated in a subprocess).\"\"\"\n\n    display_name = \"File\"\n    description = \"Loads content from one or more files.\"\n    documentation: str = \"https://docs.langflow.org/components-data#file\"\n    icon = \"file-text\"\n    name = \"File\"\n\n    # Docling-supported/compatible extensions; TEXT_FILE_TYPES are supported by the base loader.\n    VALID_EXTENSIONS = [\n        *TEXT_FILE_TYPES,\n        \"adoc\",\n        \"asciidoc\",\n        \"asc\",\n        \"bmp\",\n        \"dotx\",\n        \"dotm\",\n        \"docm\",\n        \"jpeg\",\n        \"png\",\n        \"potx\",\n        \"ppsx\",\n        \"pptm\",\n        \"potm\",\n        \"ppsm\",\n        \"pptx\",\n        \"tiff\",\n        \"xls\",\n        \"xlsx\",\n        \"xhtml\",\n        \"webp\",\n    ]\n\n    # Fixed export settings used when markdown export is requested.\n    EXPORT_FORMAT = \"Markdown\"\n    IMAGE_MODE = \"placeholder\"\n\n    # ---- Inputs / Outputs (kept as close to original as possible) -------------------\n    _base_inputs = deepcopy(BaseFileComponent._base_inputs)\n    for input_item in _base_inputs:\n        if isinstance(input_item, FileInput) and input_item.name == \"path\":\n            input_item.real_time_refresh = True\n            break\n\n    inputs = [\n        *_base_inputs,\n        BoolInput(\n            name=\"advanced_mode\",\n            display_name=\"Advanced Parser\",\n            value=False,\n            real_time_refresh=True,\n            info=(\n                \"Enable advanced document processing and export with Docling for PDFs, images, and office documents. \"\n                \"Available only for single file processing.\"\n                \"Note that advanced document processing can consume significant resources.\"\n            ),\n            show=False,\n        ),\n        DropdownInput(\n            name=\"pipeline\",\n            display_name=\"Pipeline\",\n            info=\"Docling pipeline to use\",\n            options=[\"standard\", \"vlm\"],\n            value=\"standard\",\n            advanced=True,\n            real_time_refresh=True,\n        ),\n        DropdownInput(\n            name=\"ocr_engine\",\n            display_name=\"OCR Engine\",\n            info=\"OCR engine to use. Only available when pipeline is set to 'standard'.\",\n            options=[\"None\", \"easyocr\"],\n            value=\"easyocr\",\n            show=False,\n            advanced=True,\n        ),\n        StrInput(\n            name=\"md_image_placeholder\",\n            display_name=\"Image placeholder\",\n            info=\"Specify the image placeholder for markdown exports.\",\n            value=\"<!-- image -->\",\n            advanced=True,\n            show=False,\n        ),\n        StrInput(\n            name=\"md_page_break_placeholder\",\n            display_name=\"Page break placeholder\",\n            info=\"Add this placeholder between pages in the markdown output.\",\n            value=\"\",\n            advanced=True,\n            show=False,\n        ),\n        MessageTextInput(\n            name=\"doc_key\",\n            display_name=\"Doc Key\",\n            info=\"The key to use for the DoclingDocument column.\",\n            value=\"doc\",\n            advanced=True,\n            show=False,\n        ),\n        # Deprecated input retained for backward-compatibility.\n        BoolInput(\n            name=\"use_multithreading\",\n            display_name=\"[Deprecated] Use Multithreading\",\n            advanced=True,\n            value=True,\n            info=\"Set 'Processing Concurrency' greater than 1 to enable multithreading.\",\n        ),\n        IntInput(\n            name=\"concurrency_multithreading\",\n            display_name=\"Processing Concurrency\",\n            advanced=True,\n            info=\"When multiple files are being processed, the number of files to process concurrently.\",\n            value=1,\n        ),\n        BoolInput(\n            name=\"markdown\",\n            display_name=\"Markdown Export\",\n            info=\"Export processed documents to Markdown format. Only available when advanced mode is enabled.\",\n            value=False,\n            show=False,\n        ),\n    ]\n\n    outputs = [\n        Output(display_name=\"Raw Content\", name=\"message\", method=\"load_files_message\"),\n    ]\n\n    # ------------------------------ UI helpers --------------------------------------\n\n    def _path_value(self, template: dict) -> list[str]:\n        \"\"\"Return the list of currently selected file paths from the template.\"\"\"\n        return template.get(\"path\", {}).get(\"file_path\", [])\n\n    def update_build_config(\n        self,\n        build_config: dict[str, Any],\n        field_value: Any,\n        field_name: str | None = None,\n    ) -> dict[str, Any]:\n        \"\"\"Show/hide Advanced Parser and related fields based on selection context.\"\"\"\n        if field_name == \"path\":\n            paths = self._path_value(build_config)\n            file_path = paths[0] if paths else \"\"\n            file_count = len(field_value) if field_value else 0\n\n            # Advanced mode only for single (non-tabular) file\n            allow_advanced = file_count == 1 and not file_path.endswith((\".csv\", \".xlsx\", \".parquet\"))\n            build_config[\"advanced_mode\"][\"show\"] = allow_advanced\n            if not allow_advanced:\n                build_config[\"advanced_mode\"][\"value\"] = False\n                for f in (\"pipeline\", \"ocr_engine\", \"doc_key\", \"md_image_placeholder\", \"md_page_break_placeholder\"):\n                    if f in build_config:\n                        build_config[f][\"show\"] = False\n\n        # Docling Processing\n        elif field_name == \"advanced_mode\":\n            for f in (\"pipeline\", \"ocr_engine\", \"doc_key\", \"md_image_placeholder\", \"md_page_break_placeholder\"):\n                if f in build_config:\n                    build_config[f][\"show\"] = bool(field_value)\n\n        elif field_name == \"pipeline\":\n            if field_value == \"standard\":\n                build_config[\"ocr_engine\"][\"show\"] = True\n                build_config[\"ocr_engine\"][\"value\"] = \"easyocr\"\n            else:\n                build_config[\"ocr_engine\"][\"show\"] = False\n                build_config[\"ocr_engine\"][\"value\"] = \"None\"\n\n        return build_config\n\n    def update_outputs(self, frontend_node: dict[str, Any], field_name: str, field_value: Any) -> dict[str, Any]:  # noqa: ARG002\n        \"\"\"Dynamically show outputs based on file count/type and advanced mode.\"\"\"\n        if field_name not in [\"path\", \"advanced_mode\", \"pipeline\"]:\n            return frontend_node\n\n        template = frontend_node.get(\"template\", {})\n        paths = self._path_value(template)\n        if not paths:\n            return frontend_node\n\n        frontend_node[\"outputs\"] = []\n        if len(paths) == 1:\n            file_path = paths[0] if field_name == \"path\" else frontend_node[\"template\"][\"path\"][\"file_path\"][0]\n            if file_path.endswith((\".csv\", \".xlsx\", \".parquet\")):\n                frontend_node[\"outputs\"].append(\n                    Output(display_name=\"Structured Content\", name=\"dataframe\", method=\"load_files_structured\"),\n                )\n            elif file_path.endswith(\".json\"):\n                frontend_node[\"outputs\"].append(\n                    Output(display_name=\"Structured Content\", name=\"json\", method=\"load_files_json\"),\n                )\n\n            advanced_mode = frontend_node.get(\"template\", {}).get(\"advanced_mode\", {}).get(\"value\", False)\n            if advanced_mode:\n                frontend_node[\"outputs\"].append(\n                    Output(display_name=\"Structured Output\", name=\"advanced_dataframe\", method=\"load_files_dataframe\"),\n                )\n                frontend_node[\"outputs\"].append(\n                    Output(display_name=\"Markdown\", name=\"advanced_markdown\", method=\"load_files_markdown\"),\n                )\n                frontend_node[\"outputs\"].append(\n                    Output(display_name=\"File Path\", name=\"path\", method=\"load_files_path\"),\n                )\n            else:\n                frontend_node[\"outputs\"].append(\n                    Output(display_name=\"Raw Content\", name=\"message\", method=\"load_files_message\"),\n                )\n                frontend_node[\"outputs\"].append(\n                    Output(display_name=\"File Path\", name=\"path\", method=\"load_files_path\"),\n                )\n        else:\n            # Multiple files => DataFrame output; advanced parser disabled\n            frontend_node[\"outputs\"].append(Output(display_name=\"Files\", name=\"dataframe\", method=\"load_files\"))\n\n        return frontend_node\n\n    # ------------------------------ Core processing ----------------------------------\n\n    def _is_docling_compatible(self, file_path: str) -> bool:\n        \"\"\"Lightweight extension gate for Docling-compatible types.\"\"\"\n        docling_exts = (\n            \".adoc\",\n            \".asciidoc\",\n            \".asc\",\n            \".bmp\",\n            \".csv\",\n            \".dotx\",\n            \".dotm\",\n            \".docm\",\n            \".docx\",\n            \".htm\",\n            \".html\",\n            \".jpeg\",\n            \".json\",\n            \".md\",\n            \".pdf\",\n            \".png\",\n            \".potx\",\n            \".ppsx\",\n            \".pptm\",\n            \".potm\",\n            \".ppsm\",\n            \".pptx\",\n            \".tiff\",\n            \".txt\",\n            \".xls\",\n            \".xlsx\",\n            \".xhtml\",\n            \".xml\",\n            \".webp\",\n        )\n        return file_path.lower().endswith(docling_exts)\n\n    def _process_docling_in_subprocess(self, file_path: str) -> Data | None:\n        \"\"\"Run Docling in a separate OS process and map the result to a Data object.\n\n        We avoid multiprocessing pickling by launching `python -c \"<script>\"` and\n        passing JSON config via stdin. The child prints a JSON result to stdout.\n        \"\"\"\n        if not file_path:\n            return None\n\n        args: dict[str, Any] = {\n            \"file_path\": file_path,\n            \"markdown\": bool(self.markdown),\n            \"image_mode\": str(self.IMAGE_MODE),\n            \"md_image_placeholder\": str(self.md_image_placeholder),\n            \"md_page_break_placeholder\": str(self.md_page_break_placeholder),\n            \"pipeline\": str(self.pipeline),\n            \"ocr_engine\": (\n                self.ocr_engine if self.ocr_engine and self.ocr_engine != \"None\" and self.pipeline != \"vlm\" else None\n            ),\n        }\n\n        self.log(f\"Starting Docling subprocess for file: {file_path}\")\n        self.log(args)\n\n        # Child script for isolating the docling processing\n        child_script = textwrap.dedent(\n            r\"\"\"\n            import json, sys\n\n            def try_imports():\n                # Strategy 1: latest layout\n                try:\n                    from docling.datamodel.base_models import ConversionStatus, InputFormat  # type: ignore\n                    from docling.document_converter import DocumentConverter  # type: ignore\n                    from docling_core.types.doc import ImageRefMode  # type: ignore\n                    return ConversionStatus, InputFormat, DocumentConverter, ImageRefMode, \"latest\"\n                except Exception:\n                    pass\n                # Strategy 2: alternative layout\n                try:\n                    from docling.document_converter import DocumentConverter  # type: ignore\n                    try:\n                        from docling_core.types import ConversionStatus, InputFormat  # type: ignore\n                    except Exception:\n                        try:\n                            from docling.datamodel import ConversionStatus, InputFormat  # type: ignore\n                        except Exception:\n                            class ConversionStatus: SUCCESS = \"success\"\n                            class InputFormat:\n                                PDF=\"pdf\"; IMAGE=\"image\"\n                    try:\n                        from docling_core.types.doc import ImageRefMode  # type: ignore\n                    except Exception:\n                        class ImageRefMode:\n                            PLACEHOLDER=\"placeholder\"; EMBEDDED=\"embedded\"\n                    return ConversionStatus, InputFormat, DocumentConverter, ImageRefMode, \"alternative\"\n                except Exception:\n                    pass\n                # Strategy 3: basic converter only\n                try:\n                    from docling.document_converter import DocumentConverter  # type: ignore\n                    class ConversionStatus: SUCCESS = \"success\"\n                    class InputFormat:\n                        PDF=\"pdf\"; IMAGE=\"image\"\n                    class ImageRefMode:\n                        PLACEHOLDER=\"placeholder\"; EMBEDDED=\"embedded\"\n                    return ConversionStatus, InputFormat, DocumentConverter, ImageRefMode, \"basic\"\n                except Exception as e:\n                    raise ImportError(f\"Docling imports failed: {e}\") from e\n\n            def create_converter(strategy, input_format, DocumentConverter, pipeline, ocr_engine):\n                # --- Standard PDF/IMAGE pipeline (your existing behavior), with optional OCR ---\n                if pipeline == \"standard\":\n                    try:\n                        from docling.datamodel.pipeline_options import PdfPipelineOptions  # type: ignore\n                        from docling.document_converter import PdfFormatOption  # type: ignore\n\n                        pipe = PdfPipelineOptions()\n                        pipe.do_ocr = False\n\n                        if ocr_engine:\n                            try:\n                                from docling.models.factories import get_ocr_factory  # type: ignore\n                                pipe.do_ocr = True\n                                fac = get_ocr_factory(allow_external_plugins=False)\n                                pipe.ocr_options = fac.create_options(kind=ocr_engine)\n                            except Exception:\n                                # If OCR setup fails, disable it\n                                pipe.do_ocr = False\n\n                        fmt = {}\n                        if hasattr(input_format, \"PDF\"):\n                            fmt[getattr(input_format, \"PDF\")] = PdfFormatOption(pipeline_options=pipe)\n                        if hasattr(input_format, \"IMAGE\"):\n                            fmt[getattr(input_format, \"IMAGE\")] = PdfFormatOption(pipeline_options=pipe)\n\n                        return DocumentConverter(format_options=fmt)\n                    except Exception:\n                        return DocumentConverter()\n\n                # --- Vision-Language Model (VLM) pipeline ---\n                if pipeline == \"vlm\":\n                    try:\n                        from docling.pipeline.vlm_pipeline import VlmPipeline\n                        from docling.document_converter import PdfFormatOption  # type: ignore\n\n                        vl_pipe = VlmPipelineOptions()\n\n                        # VLM paths generally don't need OCR; keep OCR off by default here.\n                        fmt = {}\n                        if hasattr(input_format, \"PDF\"):\n                            fmt[getattr(input_format, \"PDF\")] = PdfFormatOption(pipeline_cls=VlmPipeline)\n                        if hasattr(input_format, \"IMAGE\"):\n                            fmt[getattr(input_format, \"IMAGE\")] = PdfFormatOption(pipeline_cls=VlmPipeline)\n\n                        return DocumentConverter(format_options=fmt)\n                    except Exception:\n                        return DocumentConverter()\n\n                # --- Fallback: default converter with no special options ---\n                return DocumentConverter()\n\n            def export_markdown(document, ImageRefMode, image_mode, img_ph, pg_ph):\n                try:\n                    mode = getattr(ImageRefMode, image_mode.upper(), image_mode)\n                    return document.export_to_markdown(\n                        image_mode=mode,\n                        image_placeholder=img_ph,\n                        page_break_placeholder=pg_ph,\n                    )\n                except Exception:\n                    try:\n                        return document.export_to_text()\n                    except Exception:\n                        return str(document)\n\n            def to_rows(doc_dict):\n                rows = []\n                for t in doc_dict.get(\"texts\", []):\n                    prov = t.get(\"prov\") or []\n                    page_no = None\n                    if prov and isinstance(prov, list) and isinstance(prov[0], dict):\n                        page_no = prov[0].get(\"page_no\")\n                    rows.append({\n                        \"page_no\": page_no,\n                        \"label\": t.get(\"label\"),\n                        \"text\": t.get(\"text\"),\n                        \"level\": t.get(\"level\"),\n                    })\n                return rows\n\n            def main():\n                cfg = json.loads(sys.stdin.read())\n                file_path = cfg[\"file_path\"]\n                markdown = cfg[\"markdown\"]\n                image_mode = cfg[\"image_mode\"]\n                img_ph = cfg[\"md_image_placeholder\"]\n                pg_ph = cfg[\"md_page_break_placeholder\"]\n                pipeline = cfg[\"pipeline\"]\n                ocr_engine = cfg.get(\"ocr_engine\")\n                meta = {\"file_path\": file_path}\n\n                try:\n                    ConversionStatus, InputFormat, DocumentConverter, ImageRefMode, strategy = try_imports()\n                    converter = create_converter(strategy, InputFormat, DocumentConverter, pipeline, ocr_engine)\n                    try:\n                        res = converter.convert(file_path)\n                    except Exception as e:\n                        print(json.dumps({\"ok\": False, \"error\": f\"Docling conversion error: {e}\", \"meta\": meta}))\n                        return\n\n                    ok = False\n                    if hasattr(res, \"status\"):\n                        try:\n                            ok = (res.status == ConversionStatus.SUCCESS) or (str(res.status).lower() == \"success\")\n                        except Exception:\n                            ok = (str(res.status).lower() == \"success\")\n                    if not ok and hasattr(res, \"document\"):\n                        ok = getattr(res, \"document\", None) is not None\n                    if not ok:\n                        print(json.dumps({\"ok\": False, \"error\": \"Docling conversion failed\", \"meta\": meta}))\n                        return\n\n                    doc = getattr(res, \"document\", None)\n                    if doc is None:\n                        print(json.dumps({\"ok\": False, \"error\": \"Docling produced no document\", \"meta\": meta}))\n                        return\n\n                    if markdown:\n                        text = export_markdown(doc, ImageRefMode, image_mode, img_ph, pg_ph)\n                        print(json.dumps({\"ok\": True, \"mode\": \"markdown\", \"text\": text, \"meta\": meta}))\n                        return\n\n                    # structured\n                    try:\n                        doc_dict = doc.export_to_dict()\n                    except Exception as e:\n                        print(json.dumps({\"ok\": False, \"error\": f\"Docling export_to_dict failed: {e}\", \"meta\": meta}))\n                        return\n\n                    rows = to_rows(doc_dict)\n                    print(json.dumps({\"ok\": True, \"mode\": \"structured\", \"doc\": rows, \"meta\": meta}))\n                except Exception as e:\n                    print(\n                        json.dumps({\n                            \"ok\": False,\n                            \"error\": f\"Docling processing error: {e}\",\n                            \"meta\": {\"file_path\": file_path},\n                        })\n                    )\n\n            if __name__ == \"__main__\":\n                main()\n            \"\"\"\n        )\n\n        # Validate file_path to avoid command injection or unsafe input\n        if not isinstance(args[\"file_path\"], str) or any(c in args[\"file_path\"] for c in [\";\", \"|\", \"&\", \"$\", \"`\"]):\n            return Data(data={\"error\": \"Unsafe file path detected.\", \"file_path\": args[\"file_path\"]})\n\n        proc = subprocess.run(  # noqa: S603\n            [sys.executable, \"-u\", \"-c\", child_script],\n            input=json.dumps(args).encode(\"utf-8\"),\n            capture_output=True,\n            check=False,\n        )\n\n        if not proc.stdout:\n            err_msg = proc.stderr.decode(\"utf-8\", errors=\"replace\") or \"no output from child process\"\n            return Data(data={\"error\": f\"Docling subprocess error: {err_msg}\", \"file_path\": file_path})\n\n        try:\n            result = json.loads(proc.stdout.decode(\"utf-8\"))\n        except Exception as e:  # noqa: BLE001\n            err_msg = proc.stderr.decode(\"utf-8\", errors=\"replace\")\n            return Data(\n                data={\"error\": f\"Invalid JSON from Docling subprocess: {e}. stderr={err_msg}\", \"file_path\": file_path},\n            )\n\n        if not result.get(\"ok\"):\n            return Data(data={\"error\": result.get(\"error\", \"Unknown Docling error\"), **result.get(\"meta\", {})})\n\n        meta = result.get(\"meta\", {})\n        if result.get(\"mode\") == \"markdown\":\n            exported_content = str(result.get(\"text\", \"\"))\n            return Data(\n                text=exported_content,\n                data={\"exported_content\": exported_content, \"export_format\": self.EXPORT_FORMAT, **meta},\n            )\n\n        rows = list(result.get(\"doc\", []))\n        return Data(data={\"doc\": rows, \"export_format\": self.EXPORT_FORMAT, **meta})\n\n    def process_files(\n        self,\n        file_list: list[BaseFileComponent.BaseFile],\n    ) -> list[BaseFileComponent.BaseFile]:\n        \"\"\"Process input files.\n\n        - Single file + advanced_mode => Docling in a separate process.\n        - Otherwise => standard parsing in current process (optionally threaded).\n        \"\"\"\n        if not file_list:\n            msg = \"No files to process.\"\n            raise ValueError(msg)\n\n        def process_file_standard(file_path: str, *, silent_errors: bool = False) -> Data | None:\n            try:\n                return parse_text_file_to_data(file_path, silent_errors=silent_errors)\n            except FileNotFoundError as e:\n                self.log(f\"File not found: {file_path}. Error: {e}\")\n                if not silent_errors:\n                    raise\n                return None\n            except Exception as e:\n                self.log(f\"Unexpected error processing {file_path}: {e}\")\n                if not silent_errors:\n                    raise\n                return None\n\n        # Advanced path: only for a single Docling-compatible file\n        if len(file_list) == 1:\n            file_path = str(file_list[0].path)\n            if self.advanced_mode and self._is_docling_compatible(file_path):\n                advanced_data: Data | None = self._process_docling_in_subprocess(file_path)\n\n                # --- UNNEST: expand each element in `doc` to its own Data row\n                payload = getattr(advanced_data, \"data\", {}) or {}\n                doc_rows = payload.get(\"doc\")\n                if isinstance(doc_rows, list):\n                    rows: list[Data | None] = [\n                        Data(\n                            data={\n                                \"file_path\": file_path,\n                                **(item if isinstance(item, dict) else {\"value\": item}),\n                            },\n                        )\n                        for item in doc_rows\n                    ]\n                    return self.rollup_data(file_list, rows)\n\n                # If not structured, keep as-is (e.g., markdown export or error dict)\n                return self.rollup_data(file_list, [advanced_data])\n\n        # Standard multi-file (or single non-advanced) path\n        concurrency = 1 if not self.use_multithreading else max(1, self.concurrency_multithreading)\n        file_paths = [str(f.path) for f in file_list]\n        self.log(f\"Starting parallel processing of {len(file_paths)} files with concurrency: {concurrency}.\")\n        my_data = parallel_load_data(\n            file_paths,\n            silent_errors=self.silent_errors,\n            load_function=process_file_standard,\n            max_concurrency=concurrency,\n        )\n        return self.rollup_data(file_list, my_data)\n\n    # ------------------------------ Output helpers -----------------------------------\n\n    def load_files_helper(self) -> DataFrame:\n        result = self.load_files()\n\n        # Error condition - raise error if no text and an error is present\n        if not hasattr(result, \"text\"):\n            if hasattr(result, \"error\"):\n                raise ValueError(result.error[0])\n            msg = \"No content generated.\"\n            raise ValueError(msg)\n\n        return result\n\n    def load_files_dataframe(self) -> DataFrame:\n        \"\"\"Load files using advanced Docling processing and export to DataFrame format.\"\"\"\n        self.markdown = False\n        return self.load_files_helper()\n\n    def load_files_markdown(self) -> Message:\n        \"\"\"Load files using advanced Docling processing and export to Markdown format.\"\"\"\n        self.markdown = True\n        result = self.load_files_helper()\n        return Message(text=str(result.text[0]))\n"
              },
              "concurrency_multithreading": {
                "_input_type": "IntInput",
                "advanced": true,
                "display_name": "Processing Concurrency",
                "dynamic": false,
                "info": "When multiple files are being processed, the number of files to process concurrently.",
                "list": false,
                "list_add_label": "Add More",
                "name": "concurrency_multithreading",
                "placeholder": "",
                "required": false,
                "show": true,
                "title_case": false,
                "tool_mode": false,
                "trace_as_metadata": true,
                "type": "int",
                "value": 1
              },
              "delete_server_file_after_processing": {
                "_input_type": "BoolInput",
                "advanced": true,
                "display_name": "Delete Server File After Processing",
                "dynamic": false,
                "info": "If true, the Server File Path will be deleted after processing.",
                "list": false,
                "list_add_label": "Add More",
                "name": "delete_server_file_after_processing",
                "placeholder": "",
                "required": false,
                "show": true,
                "title_case": false,
                "tool_mode": false,
                "trace_as_metadata": true,
                "type": "bool",
                "value": true
              },
              "doc_key": {
                "_input_type": "MessageTextInput",
                "advanced": true,
                "display_name": "Doc Key",
                "dynamic": false,
                "info": "The key to use for the DoclingDocument column.",
                "input_types": [
                  "Message"
                ],
                "list": false,
                "list_add_label": "Add More",
                "load_from_db": false,
                "name": "doc_key",
                "placeholder": "",
                "required": false,
                "show": false,
                "title_case": false,
                "tool_mode": false,
                "trace_as_input": true,
                "trace_as_metadata": true,
                "type": "str",
                "value": "doc"
              },
              "file_path": {
                "_input_type": "HandleInput",
                "advanced": true,
                "display_name": "Server File Path",
                "dynamic": false,
                "info": "Data object with a 'file_path' property pointing to server file or a Message object with a path to the file. Supercedes 'Path' but supports same file types.",
                "input_types": [
                  "Data",
                  "Message"
                ],
                "list": true,
                "list_add_label": "Add More",
                "name": "file_path",
                "placeholder": "",
                "required": false,
                "show": true,
                "title_case": false,
                "trace_as_metadata": true,
                "type": "other",
                "value": ""
              },
              "ignore_unspecified_files": {
                "_input_type": "BoolInput",
                "advanced": true,
                "display_name": "Ignore Unspecified Files",
                "dynamic": false,
                "info": "If true, Data with no 'file_path' property will be ignored.",
                "list": false,
                "list_add_label": "Add More",
                "name": "ignore_unspecified_files",
                "placeholder": "",
                "required": false,
                "show": true,
                "title_case": false,
                "tool_mode": false,
                "trace_as_metadata": true,
                "type": "bool",
                "value": false
              },
              "ignore_unsupported_extensions": {
                "_input_type": "BoolInput",
                "advanced": true,
                "display_name": "Ignore Unsupported Extensions",
                "dynamic": false,
                "info": "If true, files with unsupported extensions will not be processed.",
                "list": false,
                "list_add_label": "Add More",
                "name": "ignore_unsupported_extensions",
                "placeholder": "",
                "required": false,
                "show": true,
                "title_case": false,
                "tool_mode": false,
                "trace_as_metadata": true,
                "type": "bool",
                "value": true
              },
              "markdown": {
                "_input_type": "BoolInput",
                "advanced": false,
                "display_name": "Markdown Export",
                "dynamic": false,
                "info": "Export processed documents to Markdown format. Only available when advanced mode is enabled.",
                "list": false,
                "list_add_label": "Add More",
                "name": "markdown",
                "placeholder": "",
                "required": false,
                "show": false,
                "title_case": false,
                "tool_mode": false,
                "trace_as_metadata": true,
                "type": "bool",
                "value": false
              },
              "md_image_placeholder": {
                "_input_type": "StrInput",
                "advanced": true,
                "display_name": "Image placeholder",
                "dynamic": false,
                "info": "Specify the image placeholder for markdown exports.",
                "list": false,
                "list_add_label": "Add More",
                "load_from_db": false,
                "name": "md_image_placeholder",
                "placeholder": "",
                "required": false,
                "show": false,
                "title_case": false,
                "tool_mode": false,
                "trace_as_metadata": true,
                "type": "str",
                "value": "<!-- image -->"
              },
              "md_page_break_placeholder": {
                "_input_type": "StrInput",
                "advanced": true,
                "display_name": "Page break placeholder",
                "dynamic": false,
                "info": "Add this placeholder between pages in the markdown output.",
                "list": false,
                "list_add_label": "Add More",
                "load_from_db": false,
                "name": "md_page_break_placeholder",
                "placeholder": "",
                "required": false,
                "show": false,
                "title_case": false,
                "tool_mode": false,
                "trace_as_metadata": true,
                "type": "str",
                "value": ""
              },
              "ocr_engine": {
                "_input_type": "DropdownInput",
                "advanced": true,
                "combobox": false,
                "dialog_inputs": {},
                "display_name": "OCR Engine",
                "dynamic": false,
                "info": "OCR engine to use. Only available when pipeline is set to 'standard'.",
                "name": "ocr_engine",
                "options": [
                  "None",
                  "easyocr"
                ],
                "options_metadata": [],
                "placeholder": "",
                "required": false,
                "show": false,
                "title_case": false,
                "toggle": false,
                "tool_mode": false,
                "trace_as_metadata": true,
                "type": "str",
                "value": ""
              },
              "path": {
                "_input_type": "FileInput",
                "advanced": false,
                "display_name": "Files",
                "dynamic": false,
                "fileTypes": [
                  "csv",
                  "json",
                  "pdf",
                  "txt",
                  "md",
                  "mdx",
                  "yaml",
                  "yml",
                  "xml",
                  "html",
                  "htm",
                  "docx",
                  "py",
                  "sh",
                  "sql",
                  "js",
                  "ts",
                  "tsx",
                  "adoc",
                  "asciidoc",
                  "asc",
                  "bmp",
                  "dotx",
                  "dotm",
                  "docm",
                  "jpeg",
                  "png",
                  "potx",
                  "ppsx",
                  "pptm",
                  "potm",
                  "ppsm",
                  "pptx",
                  "tiff",
                  "xls",
                  "xlsx",
                  "xhtml",
                  "webp",
                  "zip",
                  "tar",
                  "tgz",
                  "bz2",
                  "gz"
                ],
                "file_path": [],
                "info": "Supported file extensions: csv, json, pdf, txt, md, mdx, yaml, yml, xml, html, htm, docx, py, sh, sql, js, ts, tsx, adoc, asciidoc, asc, bmp, dotx, dotm, docm, jpeg, png, potx, ppsx, pptm, potm, ppsm, pptx, tiff, xls, xlsx, xhtml, webp; optionally bundled in file extensions: zip, tar, tgz, bz2, gz",
                "list": true,
                "list_add_label": "Add More",
                "name": "path",
                "placeholder": "",
                "real_time_refresh": true,
                "required": false,
                "show": true,
                "temp_file": false,
                "title_case": false,
                "trace_as_metadata": true,
                "type": "file",
                "value": ""
              },
              "pipeline": {
                "_input_type": "DropdownInput",
                "advanced": true,
                "combobox": false,
                "dialog_inputs": {},
                "display_name": "Pipeline",
                "dynamic": false,
                "info": "Docling pipeline to use",
                "name": "pipeline",
                "options": [
                  "standard",
                  "vlm"
                ],
                "options_metadata": [],
                "placeholder": "",
                "required": false,
                "show": true,
                "title_case": false,
                "toggle": false,
                "tool_mode": false,
                "trace_as_metadata": true,
                "type": "str",
                "value": "standard"
              },
              "separator": {
                "_input_type": "StrInput",
                "advanced": true,
                "display_name": "Separator",
                "dynamic": false,
                "info": "Specify the separator to use between multiple outputs in Message format.",
                "list": false,
                "list_add_label": "Add More",
                "load_from_db": false,
                "name": "separator",
                "placeholder": "",
                "required": false,
                "show": true,
                "title_case": false,
                "tool_mode": false,
                "trace_as_metadata": true,
                "type": "str",
                "value": "\n\n"
              },
              "silent_errors": {
                "_input_type": "BoolInput",
                "advanced": true,
                "display_name": "Silent Errors",
                "dynamic": false,
                "info": "If true, errors will not raise an exception.",
                "list": false,
                "list_add_label": "Add More",
                "name": "silent_errors",
                "placeholder": "",
                "required": false,
                "show": true,
                "title_case": false,
                "tool_mode": false,
                "trace_as_metadata": true,
                "type": "bool",
                "value": false
              },
              "use_multithreading": {
                "_input_type": "BoolInput",
                "advanced": true,
                "display_name": "[Deprecated] Use Multithreading",
                "dynamic": false,
                "info": "Set 'Processing Concurrency' greater than 1 to enable multithreading.",
                "list": false,
                "list_add_label": "Add More",
                "name": "use_multithreading",
                "placeholder": "",
                "required": false,
                "show": true,
                "title_case": false,
                "tool_mode": false,
                "trace_as_metadata": true,
                "type": "bool",
                "value": true
              }
            },
            "tool_mode": false
          },
          "showNode": true,
          "type": "File"
        },
        "dragging": false,
        "id": "File-dfMwA",
        "measured": {
          "height": 230,
          "width": 320
        },
        "position": {
          "x": 927.3702382252801,
          "y": 647.5603858397075
        },
        "selected": false,
        "type": "genericNode"
      },
      {
        "data": {
          "id": "LanguageModelComponent-HrqxT",
          "node": {
            "base_classes": [
              "LanguageModel",
              "Message"
            ],
            "beta": false,
            "conditional_paths": [],
            "custom_fields": {},
            "description": "Runs a language model given a specified provider. ",
            "display_name": "Language Model",
            "documentation": "",
            "edited": false,
            "field_order": [
              "provider",
              "model_name",
              "api_key",
              "input_value",
              "system_message",
              "stream",
              "temperature"
            ],
            "frozen": false,
            "icon": "brain-circuit",
            "legacy": false,
            "metadata": {
              "keywords": [
                "model",
                "llm",
                "language model",
                "large language model"
              ]
            },
            "minimized": false,
            "output_types": [],
            "outputs": [
              {
                "allows_loop": false,
                "cache": true,
                "display_name": "Model Response",
                "group_outputs": false,
                "method": "text_response",
                "name": "text_output",
                "options": null,
                "required_inputs": null,
                "tool_mode": true,
                "types": [
                  "Message"
                ],
                "value": "__UNDEFINED__"
              },
              {
                "allows_loop": false,
                "cache": true,
                "display_name": "Language Model",
                "group_outputs": false,
                "method": "build_model",
                "name": "model_output",
                "options": null,
                "required_inputs": null,
                "selected": "LanguageModel",
                "tool_mode": true,
                "types": [
                  "LanguageModel"
                ],
                "value": "__UNDEFINED__"
              }
            ],
            "pinned": false,
            "priority": 0,
            "template": {
              "_type": "Component",
              "api_key": {
                "_input_type": "SecretStrInput",
                "advanced": false,
                "display_name": "Anthropic API Key",
                "dynamic": false,
                "info": "Model Provider API key",
                "input_types": [],
                "load_from_db": true,
                "name": "api_key",
                "password": true,
                "placeholder": "",
                "real_time_refresh": true,
                "required": false,
                "show": true,
                "title_case": false,
                "type": "str",
                "value": "ANTHROPIC_API_KEY"
              },
              "code": {
                "advanced": true,
                "dynamic": true,
                "fileTypes": [],
                "file_path": "",
                "info": "",
                "list": false,
                "load_from_db": false,
                "multiline": true,
                "name": "code",
                "password": false,
                "placeholder": "",
                "required": true,
                "show": true,
                "title_case": false,
                "type": "code",
                "value": "from typing import Any\n\nfrom langchain_anthropic import ChatAnthropic\nfrom langchain_google_genai import ChatGoogleGenerativeAI\nfrom langchain_openai import ChatOpenAI\n\nfrom langflow.base.models.anthropic_constants import ANTHROPIC_MODELS\nfrom langflow.base.models.google_generative_ai_constants import GOOGLE_GENERATIVE_AI_MODELS\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.base.models.openai_constants import OPENAI_CHAT_MODEL_NAMES, OPENAI_REASONING_MODEL_NAMES\nfrom langflow.field_typing import LanguageModel\nfrom langflow.field_typing.range_spec import RangeSpec\nfrom langflow.inputs.inputs import BoolInput\nfrom langflow.io import DropdownInput, MessageInput, MultilineInput, SecretStrInput, SliderInput\nfrom langflow.schema.dotdict import dotdict\n\n\nclass LanguageModelComponent(LCModelComponent):\n    display_name = \"Language Model\"\n    description = \"Runs a language model given a specified provider.\"\n    documentation: str = \"https://docs.langflow.org/components-models\"\n    icon = \"brain-circuit\"\n    category = \"models\"\n    priority = 0  # Set priority to 0 to make it appear first\n\n    inputs = [\n        DropdownInput(\n            name=\"provider\",\n            display_name=\"Model Provider\",\n            options=[\"OpenAI\", \"Anthropic\", \"Google\"],\n            value=\"OpenAI\",\n            info=\"Select the model provider\",\n            real_time_refresh=True,\n            options_metadata=[{\"icon\": \"OpenAI\"}, {\"icon\": \"Anthropic\"}, {\"icon\": \"GoogleGenerativeAI\"}],\n        ),\n        DropdownInput(\n            name=\"model_name\",\n            display_name=\"Model Name\",\n            options=OPENAI_CHAT_MODEL_NAMES + OPENAI_REASONING_MODEL_NAMES,\n            value=OPENAI_CHAT_MODEL_NAMES[0],\n            info=\"Select the model to use\",\n            real_time_refresh=True,\n        ),\n        SecretStrInput(\n            name=\"api_key\",\n            display_name=\"OpenAI API Key\",\n            info=\"Model Provider API key\",\n            required=False,\n            show=True,\n            real_time_refresh=True,\n        ),\n        MessageInput(\n            name=\"input_value\",\n            display_name=\"Input\",\n            info=\"The input text to send to the model\",\n        ),\n        MultilineInput(\n            name=\"system_message\",\n            display_name=\"System Message\",\n            info=\"A system message that helps set the behavior of the assistant\",\n            advanced=False,\n        ),\n        BoolInput(\n            name=\"stream\",\n            display_name=\"Stream\",\n            info=\"Whether to stream the response\",\n            value=False,\n            advanced=True,\n        ),\n        SliderInput(\n            name=\"temperature\",\n            display_name=\"Temperature\",\n            value=0.1,\n            info=\"Controls randomness in responses\",\n            range_spec=RangeSpec(min=0, max=1, step=0.01),\n            advanced=True,\n        ),\n    ]\n\n    def build_model(self) -> LanguageModel:\n        provider = self.provider\n        model_name = self.model_name\n        temperature = self.temperature\n        stream = self.stream\n\n        if provider == \"OpenAI\":\n            if not self.api_key:\n                msg = \"OpenAI API key is required when using OpenAI provider\"\n                raise ValueError(msg)\n\n            if model_name in OPENAI_REASONING_MODEL_NAMES:\n                # reasoning models do not support temperature (yet)\n                temperature = None\n\n            return ChatOpenAI(\n                model_name=model_name,\n                temperature=temperature,\n                streaming=stream,\n                openai_api_key=self.api_key,\n            )\n        if provider == \"Anthropic\":\n            if not self.api_key:\n                msg = \"Anthropic API key is required when using Anthropic provider\"\n                raise ValueError(msg)\n            return ChatAnthropic(\n                model=model_name,\n                temperature=temperature,\n                streaming=stream,\n                anthropic_api_key=self.api_key,\n            )\n        if provider == \"Google\":\n            if not self.api_key:\n                msg = \"Google API key is required when using Google provider\"\n                raise ValueError(msg)\n            return ChatGoogleGenerativeAI(\n                model=model_name,\n                temperature=temperature,\n                streaming=stream,\n                google_api_key=self.api_key,\n            )\n        msg = f\"Unknown provider: {provider}\"\n        raise ValueError(msg)\n\n    def update_build_config(self, build_config: dotdict, field_value: Any, field_name: str | None = None) -> dotdict:\n        if field_name == \"provider\":\n            if field_value == \"OpenAI\":\n                build_config[\"model_name\"][\"options\"] = OPENAI_CHAT_MODEL_NAMES + OPENAI_REASONING_MODEL_NAMES\n                build_config[\"model_name\"][\"value\"] = OPENAI_CHAT_MODEL_NAMES[0]\n                build_config[\"api_key\"][\"display_name\"] = \"OpenAI API Key\"\n            elif field_value == \"Anthropic\":\n                build_config[\"model_name\"][\"options\"] = ANTHROPIC_MODELS\n                build_config[\"model_name\"][\"value\"] = ANTHROPIC_MODELS[0]\n                build_config[\"api_key\"][\"display_name\"] = \"Anthropic API Key\"\n            elif field_value == \"Google\":\n                build_config[\"model_name\"][\"options\"] = GOOGLE_GENERATIVE_AI_MODELS\n                build_config[\"model_name\"][\"value\"] = GOOGLE_GENERATIVE_AI_MODELS[0]\n                build_config[\"api_key\"][\"display_name\"] = \"Google API Key\"\n        elif field_name == \"model_name\" and field_value.startswith(\"o1\") and self.provider == \"OpenAI\":\n            # Hide system_message for o1 models - currently unsupported\n            if \"system_message\" in build_config:\n                build_config[\"system_message\"][\"show\"] = False\n        elif field_name == \"model_name\" and not field_value.startswith(\"o1\") and \"system_message\" in build_config:\n            build_config[\"system_message\"][\"show\"] = True\n        return build_config\n"
              },
              "input_value": {
                "_input_type": "MessageInput",
                "advanced": false,
                "display_name": "Input",
                "dynamic": false,
                "info": "The input text to send to the model",
                "input_types": [
                  "Message"
                ],
                "list": false,
                "list_add_label": "Add More",
                "load_from_db": false,
                "name": "input_value",
                "placeholder": "",
                "required": false,
                "show": true,
                "title_case": false,
                "tool_mode": false,
                "trace_as_input": true,
                "trace_as_metadata": true,
                "type": "str",
                "value": ""
              },
              "model_name": {
                "_input_type": "DropdownInput",
                "advanced": false,
                "combobox": false,
                "dialog_inputs": {},
                "display_name": "Model Name",
                "dynamic": false,
                "info": "Select the model to use",
                "name": "model_name",
                "options": [
                  "claude-opus-4-20250514",
                  "claude-sonnet-4-20250514",
                  "claude-3-7-sonnet-latest",
                  "claude-3-5-sonnet-latest",
                  "claude-3-5-haiku-latest",
                  "claude-3-opus-latest",
                  "claude-3-sonnet-20240229"
                ],
                "options_metadata": [],
                "placeholder": "",
                "required": false,
                "show": true,
                "title_case": false,
                "toggle": false,
                "tool_mode": false,
                "trace_as_metadata": true,
                "type": "str",
                "value": "claude-3-5-sonnet-latest"
              },
              "provider": {
                "_input_type": "DropdownInput",
                "advanced": false,
                "combobox": false,
                "dialog_inputs": {},
                "display_name": "Model Provider",
                "dynamic": false,
                "info": "Select the model provider",
                "name": "provider",
                "options": [
                  "OpenAI",
                  "Anthropic",
                  "Google"
                ],
                "options_metadata": [
                  {
                    "icon": "OpenAI"
                  },
                  {
                    "icon": "Anthropic"
                  },
                  {
                    "icon": "GoogleGenerativeAI"
                  }
                ],
                "placeholder": "",
                "real_time_refresh": true,
                "required": false,
                "show": true,
                "title_case": false,
                "toggle": false,
                "tool_mode": false,
                "trace_as_metadata": true,
                "type": "str",
                "value": "Anthropic"
              },
              "stream": {
                "_input_type": "BoolInput",
                "advanced": true,
                "display_name": "Stream",
                "dynamic": false,
                "info": "Whether to stream the response",
                "list": false,
                "list_add_label": "Add More",
                "name": "stream",
                "placeholder": "",
                "required": false,
                "show": true,
                "title_case": false,
                "tool_mode": false,
                "trace_as_metadata": true,
                "type": "bool",
                "value": false
              },
              "system_message": {
                "_input_type": "MultilineInput",
                "advanced": true,
                "copy_field": false,
                "display_name": "System Message",
                "dynamic": false,
                "info": "A system message that helps set the behavior of the assistant",
                "input_types": [
                  "Message"
                ],
                "list": false,
                "list_add_label": "Add More",
                "load_from_db": false,
                "multiline": true,
                "name": "system_message",
                "placeholder": "",
                "required": false,
                "show": true,
                "title_case": false,
                "tool_mode": false,
                "trace_as_input": true,
                "trace_as_metadata": true,
                "type": "str",
                "value": ""
              },
              "temperature": {
                "_input_type": "SliderInput",
                "advanced": true,
                "display_name": "Temperature",
                "dynamic": false,
                "info": "Controls randomness in responses",
                "max_label": "",
                "max_label_icon": "",
                "min_label": "",
                "min_label_icon": "",
                "name": "temperature",
                "placeholder": "",
                "range_spec": {
                  "max": 1,
                  "min": 0,
                  "step": 0.01,
                  "step_type": "float"
                },
                "required": false,
                "show": true,
                "slider_buttons": false,
                "slider_buttons_options": [],
                "slider_input": false,
                "title_case": false,
                "tool_mode": false,
                "type": "slider",
                "value": 0.1
              }
            },
            "tool_mode": false
          },
          "selected_output": "model_output",
          "showNode": true,
          "type": "LanguageModelComponent"
        },
        "dragging": false,
        "id": "LanguageModelComponent-HrqxT",
        "measured": {
          "height": 451,
          "width": 320
        },
        "position": {
          "x": 923.390837663514,
          "y": 80.65046750436001
        },
        "selected": false,
        "type": "genericNode"
      },
      {
        "data": {
          "id": "LanguageModelComponent-QdlJs",
          "node": {
            "base_classes": [
              "LanguageModel",
              "Message"
            ],
            "beta": false,
            "conditional_paths": [],
            "custom_fields": {},
            "description": "Runs a language model given a specified provider. ",
            "display_name": "Language Model",
            "documentation": "",
            "edited": false,
            "field_order": [
              "provider",
              "model_name",
              "api_key",
              "input_value",
              "system_message",
              "stream",
              "temperature"
            ],
            "frozen": false,
            "icon": "brain-circuit",
            "legacy": false,
            "metadata": {
              "keywords": [
                "model",
                "llm",
                "language model",
                "large language model"
              ]
            },
            "minimized": false,
            "output_types": [],
            "outputs": [
              {
                "allows_loop": false,
                "cache": true,
                "display_name": "Model Response",
                "group_outputs": false,
                "method": "text_response",
                "name": "text_output",
                "options": null,
                "required_inputs": null,
                "selected": "Message",
                "tool_mode": true,
                "types": [
                  "Message"
                ],
                "value": "__UNDEFINED__"
              },
              {
                "allows_loop": false,
                "cache": true,
                "display_name": "Language Model",
                "group_outputs": false,
                "method": "build_model",
                "name": "model_output",
                "options": null,
                "required_inputs": null,
                "selected": "LanguageModel",
                "tool_mode": true,
                "types": [
                  "LanguageModel"
                ],
                "value": "__UNDEFINED__"
              }
            ],
            "pinned": false,
            "priority": 0,
            "template": {
              "_type": "Component",
              "api_key": {
                "_input_type": "SecretStrInput",
                "advanced": false,
                "display_name": "Anthropic API Key",
                "dynamic": false,
                "info": "Model Provider API key",
                "input_types": [],
                "load_from_db": true,
                "name": "api_key",
                "password": true,
                "placeholder": "",
                "real_time_refresh": true,
                "required": false,
                "show": true,
                "title_case": false,
                "type": "str",
                "value": "ANTHROPIC_API_KEY"
              },
              "code": {
                "advanced": true,
                "dynamic": true,
                "fileTypes": [],
                "file_path": "",
                "info": "",
                "list": false,
                "load_from_db": false,
                "multiline": true,
                "name": "code",
                "password": false,
                "placeholder": "",
                "required": true,
                "show": true,
                "title_case": false,
                "type": "code",
                "value": "from typing import Any\n\nfrom langchain_anthropic import ChatAnthropic\nfrom langchain_google_genai import ChatGoogleGenerativeAI\nfrom langchain_openai import ChatOpenAI\n\nfrom langflow.base.models.anthropic_constants import ANTHROPIC_MODELS\nfrom langflow.base.models.google_generative_ai_constants import GOOGLE_GENERATIVE_AI_MODELS\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.base.models.openai_constants import OPENAI_CHAT_MODEL_NAMES, OPENAI_REASONING_MODEL_NAMES\nfrom langflow.field_typing import LanguageModel\nfrom langflow.field_typing.range_spec import RangeSpec\nfrom langflow.inputs.inputs import BoolInput\nfrom langflow.io import DropdownInput, MessageInput, MultilineInput, SecretStrInput, SliderInput\nfrom langflow.schema.dotdict import dotdict\n\n\nclass LanguageModelComponent(LCModelComponent):\n    display_name = \"Language Model\"\n    description = \"Runs a language model given a specified provider.\"\n    documentation: str = \"https://docs.langflow.org/components-models\"\n    icon = \"brain-circuit\"\n    category = \"models\"\n    priority = 0  # Set priority to 0 to make it appear first\n\n    inputs = [\n        DropdownInput(\n            name=\"provider\",\n            display_name=\"Model Provider\",\n            options=[\"OpenAI\", \"Anthropic\", \"Google\"],\n            value=\"OpenAI\",\n            info=\"Select the model provider\",\n            real_time_refresh=True,\n            options_metadata=[{\"icon\": \"OpenAI\"}, {\"icon\": \"Anthropic\"}, {\"icon\": \"GoogleGenerativeAI\"}],\n        ),\n        DropdownInput(\n            name=\"model_name\",\n            display_name=\"Model Name\",\n            options=OPENAI_CHAT_MODEL_NAMES + OPENAI_REASONING_MODEL_NAMES,\n            value=OPENAI_CHAT_MODEL_NAMES[0],\n            info=\"Select the model to use\",\n            real_time_refresh=True,\n        ),\n        SecretStrInput(\n            name=\"api_key\",\n            display_name=\"OpenAI API Key\",\n            info=\"Model Provider API key\",\n            required=False,\n            show=True,\n            real_time_refresh=True,\n        ),\n        MessageInput(\n            name=\"input_value\",\n            display_name=\"Input\",\n            info=\"The input text to send to the model\",\n        ),\n        MultilineInput(\n            name=\"system_message\",\n            display_name=\"System Message\",\n            info=\"A system message that helps set the behavior of the assistant\",\n            advanced=False,\n        ),\n        BoolInput(\n            name=\"stream\",\n            display_name=\"Stream\",\n            info=\"Whether to stream the response\",\n            value=False,\n            advanced=True,\n        ),\n        SliderInput(\n            name=\"temperature\",\n            display_name=\"Temperature\",\n            value=0.1,\n            info=\"Controls randomness in responses\",\n            range_spec=RangeSpec(min=0, max=1, step=0.01),\n            advanced=True,\n        ),\n    ]\n\n    def build_model(self) -> LanguageModel:\n        provider = self.provider\n        model_name = self.model_name\n        temperature = self.temperature\n        stream = self.stream\n\n        if provider == \"OpenAI\":\n            if not self.api_key:\n                msg = \"OpenAI API key is required when using OpenAI provider\"\n                raise ValueError(msg)\n\n            if model_name in OPENAI_REASONING_MODEL_NAMES:\n                # reasoning models do not support temperature (yet)\n                temperature = None\n\n            return ChatOpenAI(\n                model_name=model_name,\n                temperature=temperature,\n                streaming=stream,\n                openai_api_key=self.api_key,\n            )\n        if provider == \"Anthropic\":\n            if not self.api_key:\n                msg = \"Anthropic API key is required when using Anthropic provider\"\n                raise ValueError(msg)\n            return ChatAnthropic(\n                model=model_name,\n                temperature=temperature,\n                streaming=stream,\n                anthropic_api_key=self.api_key,\n            )\n        if provider == \"Google\":\n            if not self.api_key:\n                msg = \"Google API key is required when using Google provider\"\n                raise ValueError(msg)\n            return ChatGoogleGenerativeAI(\n                model=model_name,\n                temperature=temperature,\n                streaming=stream,\n                google_api_key=self.api_key,\n            )\n        msg = f\"Unknown provider: {provider}\"\n        raise ValueError(msg)\n\n    def update_build_config(self, build_config: dotdict, field_value: Any, field_name: str | None = None) -> dotdict:\n        if field_name == \"provider\":\n            if field_value == \"OpenAI\":\n                build_config[\"model_name\"][\"options\"] = OPENAI_CHAT_MODEL_NAMES + OPENAI_REASONING_MODEL_NAMES\n                build_config[\"model_name\"][\"value\"] = OPENAI_CHAT_MODEL_NAMES[0]\n                build_config[\"api_key\"][\"display_name\"] = \"OpenAI API Key\"\n            elif field_value == \"Anthropic\":\n                build_config[\"model_name\"][\"options\"] = ANTHROPIC_MODELS\n                build_config[\"model_name\"][\"value\"] = ANTHROPIC_MODELS[0]\n                build_config[\"api_key\"][\"display_name\"] = \"Anthropic API Key\"\n            elif field_value == \"Google\":\n                build_config[\"model_name\"][\"options\"] = GOOGLE_GENERATIVE_AI_MODELS\n                build_config[\"model_name\"][\"value\"] = GOOGLE_GENERATIVE_AI_MODELS[0]\n                build_config[\"api_key\"][\"display_name\"] = \"Google API Key\"\n        elif field_name == \"model_name\" and field_value.startswith(\"o1\") and self.provider == \"OpenAI\":\n            # Hide system_message for o1 models - currently unsupported\n            if \"system_message\" in build_config:\n                build_config[\"system_message\"][\"show\"] = False\n        elif field_name == \"model_name\" and not field_value.startswith(\"o1\") and \"system_message\" in build_config:\n            build_config[\"system_message\"][\"show\"] = True\n        return build_config\n"
              },
              "input_value": {
                "_input_type": "MessageInput",
                "advanced": false,
                "display_name": "Input",
                "dynamic": false,
                "info": "The input text to send to the model",
                "input_types": [
                  "Message"
                ],
                "list": false,
                "list_add_label": "Add More",
                "load_from_db": false,
                "name": "input_value",
                "placeholder": "",
                "required": false,
                "show": true,
                "title_case": false,
                "tool_mode": false,
                "trace_as_input": true,
                "trace_as_metadata": true,
                "type": "str",
                "value": ""
              },
              "model_name": {
                "_input_type": "DropdownInput",
                "advanced": false,
                "combobox": false,
                "dialog_inputs": {},
                "display_name": "Model Name",
                "dynamic": false,
                "info": "Select the model to use",
                "name": "model_name",
                "options": [
                  "claude-opus-4-20250514",
                  "claude-sonnet-4-20250514",
                  "claude-3-7-sonnet-latest",
                  "claude-3-5-sonnet-latest",
                  "claude-3-5-haiku-latest",
                  "claude-3-opus-latest",
                  "claude-3-sonnet-20240229"
                ],
                "options_metadata": [],
                "placeholder": "",
                "required": false,
                "show": true,
                "title_case": false,
                "toggle": false,
                "tool_mode": false,
                "trace_as_metadata": true,
                "type": "str",
                "value": "claude-3-5-sonnet-latest"
              },
              "provider": {
                "_input_type": "DropdownInput",
                "advanced": false,
                "combobox": false,
                "dialog_inputs": {},
                "display_name": "Model Provider",
                "dynamic": false,
                "info": "Select the model provider",
                "name": "provider",
                "options": [
                  "OpenAI",
                  "Anthropic",
                  "Google"
                ],
                "options_metadata": [
                  {
                    "icon": "OpenAI"
                  },
                  {
                    "icon": "Anthropic"
                  },
                  {
                    "icon": "GoogleGenerativeAI"
                  }
                ],
                "placeholder": "",
                "real_time_refresh": true,
                "required": false,
                "show": true,
                "title_case": false,
                "toggle": false,
                "tool_mode": false,
                "trace_as_metadata": true,
                "type": "str",
                "value": "Anthropic"
              },
              "stream": {
                "_input_type": "BoolInput",
                "advanced": true,
                "display_name": "Stream",
                "dynamic": false,
                "info": "Whether to stream the response",
                "list": false,
                "list_add_label": "Add More",
                "name": "stream",
                "placeholder": "",
                "required": false,
                "show": true,
                "title_case": false,
                "tool_mode": false,
                "trace_as_metadata": true,
                "type": "bool",
                "value": false
              },
              "system_message": {
                "_input_type": "MultilineInput",
                "advanced": false,
                "copy_field": false,
                "display_name": "System Message",
                "dynamic": false,
                "info": "A system message that helps set the behavior of the assistant",
                "input_types": [
                  "Message"
                ],
                "list": false,
                "list_add_label": "Add More",
                "load_from_db": false,
                "multiline": true,
                "name": "system_message",
                "placeholder": "",
                "required": false,
                "show": true,
                "title_case": false,
                "tool_mode": false,
                "trace_as_input": true,
                "trace_as_metadata": true,
                "type": "str",
                "value": ""
              },
              "temperature": {
                "_input_type": "SliderInput",
                "advanced": true,
                "display_name": "Temperature",
                "dynamic": false,
                "info": "Controls randomness in responses",
                "max_label": "",
                "max_label_icon": "",
                "min_label": "",
                "min_label_icon": "",
                "name": "temperature",
                "placeholder": "",
                "range_spec": {
                  "max": 1,
                  "min": 0,
                  "step": 0.01,
                  "step_type": "float"
                },
                "required": false,
                "show": true,
                "slider_buttons": false,
                "slider_buttons_options": [],
                "slider_input": false,
                "title_case": false,
                "tool_mode": false,
                "type": "slider",
                "value": 0.1
              }
            },
            "tool_mode": false
          },
          "selected_output": "text_output",
          "showNode": true,
          "type": "LanguageModelComponent"
        },
        "dragging": false,
        "id": "LanguageModelComponent-QdlJs",
        "measured": {
          "height": 534,
          "width": 320
        },
        "position": {
          "x": 2186.279431622904,
          "y": 451.16763265323283
        },
        "selected": false,
        "type": "genericNode"
      },
      {
        "data": {
          "id": "note-BstqH",
          "node": {
            "description": "### 💡 Add your Anthropic API key here",
            "display_name": "",
            "documentation": "",
            "template": {
              "backgroundColor": "transparent"
            }
          },
          "type": "note"
        },
        "dragging": false,
        "id": "note-BstqH",
        "measured": {
          "height": 324,
          "width": 324
        },
        "position": {
          "x": 2177.24956539088,
          "y": 384.73691533198325
        },
        "selected": false,
        "type": "noteNode"
      }
    ],
    "viewport": {
      "x": -342.31789184604554,
      "y": 186.2718754536295,
      "zoom": 0.6178978805328279
    }
  },
  "description": "This template transforms PDF or TXT resume documents into structured JSON, generating a portfolio website HTML code from the structured data.",
  "endpoint_name": null,
  "id": "c36b3b7b-79e6-4158-9daa-aeef89196bd6",
  "is_component": false,
  "last_tested_version": "1.4.3",
  "name": "Portfolio Website Code Generator",
  "tags": [
    "chatbots",
    "coding"
  ]
}