langflow-ai / langflow

⛓️ Langflow is a visual framework for building multi-agent and RAG applications. It's open-source, Python-powered, fully customizable, model and vector store agnostic.

Home Page:http://www.langflow.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

The outout of the Chat Input is not been recognized as text by OpenAI model

DevPaby opened this issue · comments

Describe the bug

  • I have implemented the flow:
    Chat Input [output message/text] -> [input] OpenAI Model [output text] -> [input] Chat Output.

  • When running the playground chat to test the flow I receive the error message:
    Error building vertex Azure OpenAI: 2 validation errors for HumanMessage content str type expected (type=type_error.str) content value is not a valid list (type=type_error.list)

  • Input Chat :
    from typing import Optional

from langflow.base.io.chat import ChatComponent
from langflow.schema.message import Message
from langflow.field_typing import Text
from typing import Union

class ChatInput(ChatComponent):
display_name = "Chat Input"
description = "Get chat inputs from the Playground."
icon = "ChatInput"

def build_config(self):
    build_config = super().build_config()
    build_config["input_value"] = {
        "input_types": [],
        "display_name": "Text",
        "multiline": True,
    }
    build_config["return_message"] = {
        "display_name": "Return Record",
        "advanced": True,
    }

    return build_config

def build(
    self,
    sender: Optional[str] = "User",
    sender_name: Optional[str] = "User",
    input_value: Optional[str] = None,
    files: Optional[list[str]] = None,
    session_id: Optional[str] = None,
    return_message: Optional[bool] = True,
) -> Union[Message, Text]:
    
    # THis has been included to make sure the input is a string
    if isinstance(input_value, list):
        input_value = " ".join(input_value)
    elif not isinstance(input_value, str):
        input_value = str(input_value)
       
    # Included to check the output of the Chat Input
    print(f"Processed input_value: {input_value} (type: {type(input_value)})") 

    # Output: 

"""
Processed input_value: Hello (type: <class 'str'>)
D:\Dev\LangChain\lesson1\venv\Lib\site-packages\pydantic\main.py:1042: PydanticDeprecatedSince20: The __fields__ attribute is deprecated, use model_fields instead. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.7/migration/
warnings.warn(
D:\Dev\LangChain\lesson1\venv\Lib\site-packages\pydantic\main.py:347: UserWarning: Pydantic serializer warnings:
Expected Union[str, dict[any, any], general-fields] but got list - serialized value may not be as expected
return self.pydantic_serializer.to_python(
"""

    return super().build_with_record(
        sender=sender,
        sender_name=sender_name,
        input_value=input_value,
        files=files,
        session_id=session_id,
        return_message=return_message,
    )

Screenshots

image

image

Hello, @DevPaby! I'm here to help you with any issues or questions you have. Feel free to ask me anything!

The error you're encountering indicates that the HumanMessage content is expected to be a string, but it is being received as a list. This issue can be resolved by ensuring that the input_value in the ChatInput component is always a string before it is passed to the OpenAI model.

Your current implementation already includes a check to convert input_value to a string if it is a list or any other type. However, the error suggests that this conversion might not be happening correctly in all cases.

Here is a refined version of your ChatInput component to ensure the input_value is always a string:

from typing import Optional, Union
from langflow.base.io.chat import ChatComponent
from langflow.schema.message import Message
from langflow.field_typing import Text

class ChatInput(ChatComponent):
    display_name = "Chat Input"
    description = "Get chat inputs from the Playground."
    icon = "ChatInput"

    def build_config(self):
        build_config = super().build_config()
        build_config["input_value"] = {
            "input_types": [],
            "display_name": "Text",
            "multiline": True,
        }
        build_config["return_message"] = {
            "display_name": "Return Record",
            "advanced": True,
        }
        return build_config

    def build(
        self,
        sender: Optional[str] = "User",
        sender_name: Optional[str] = "User",
        input_value: Optional[str] = None,
        files: Optional[list[str]] = None,
        session_id: Optional[str] = None,
        return_message: Optional[bool] = True,
    ) -> Union[Message, Text]:
        
        # Ensure input_value is a string
        if isinstance(input_value, list):
            input_value = " ".join(input_value)
        elif not isinstance(input_value, str):
            input_value = str(input_value)
        
        # Debugging output
        print(f"Processed input_value: {input_value} (type: {type(input_value)})") 

        return super().build_with_record(
            sender=sender,
            sender_name=sender_name,
            input_value=input_value,
            files=files,
            session_id=session_id,
            return_message=return_message,
        )

Additionally, ensure that the OpenAI model component is correctly configured to handle the input_value as a string. The expected structure and data type for the HumanMessage content in the OpenAI model component is Text [1].

If the issue persists, double-check the flow configuration and ensure that the input_value is correctly passed as a string throughout the entire flow.

To continue talking to Dosu, mention @dosu.

@dosu, You provide the same code I gave you. I have tried that code and its not working. Any other way to solve this?

To resolve the issue where the output of the Chat Input is not being recognized as text by the OpenAI model, you need to ensure that the value passed to the InputListComponent is always an array. The provided code already includes a check to convert a string value to an array:

if (typeof value === "string") {
  value = [value];
}

Make sure this conversion is correctly applied before the value is used. This ensures that the value is always in the expected array format, preventing the error "content str type expected (type=type_error.str) content value is not a valid list (type=type_error.list)".

Here's the relevant part of the code with the conversion:

import { useEffect } from "react";
import { InputListComponentType } from "../../types/components";

import _ from "lodash";
import { classNames } from "../../utils/utils";
import IconComponent from "../genericIconComponent";
import { Input } from "../ui/input";

export default function InputListComponent({
  value,
  onChange,
  disabled,
  editNode = false,
  componentName,
  playgroundDisabled,
}: InputListComponentType): JSX.Element {
  useEffect(() => {
    if (disabled && value.length > 0 && value[0] !== "") {
      onChange([""]);
    }
  }, [disabled]);

  // @TODO Recursive Character Text Splitter - the value might be in string format, whereas the InputListComponent specifically requires an array format. To ensure smooth operation and prevent potential errors, it's crucial that we handle the conversion from a string to an array with the string as its element.
  if (typeof value === "string") {
    value = [value];
  }

  if (!value?.length) value = [""];

  return (
    <div
      className={classNames(
        value.length > 1 && editNode ? "my-1" : "",
        "flex flex-col gap-3",
      )}
    >
      {value.map((singleValue, idx) => {
        return (
          <div key={idx} className="flex w-full gap-3">
            <Input
              disabled={disabled || playgroundDisabled}
              type="text"
              value={singleValue}
              className={editNode ? "input-edit-node" : ""}
              placeholder="Type something..."
              onChange={(event) => {
                let newInputList = _.cloneDeep(value);
                newInputList[idx] = event.target.value;
                onChange(newInputList);
              }}
              data-testid={
                `input-list-input${editNode ? "-edit" : ""}_${componentName}-` +
                idx
              }
            />
            {idx === value.length - 1 ? (
              <button
                onClick={(e) => {
                  let newInputList = _.cloneDeep(value);
                  newInputList.push("");
                  onChange(newInputList);
                  e.preventDefault();
                }}
                data-testid={
                  `input-list-plus-btn${
                    editNode ? "-edit" : ""
                  }_${componentName}-` + idx
                }
                disabled={disabled || playgroundDisabled}
              >
                <IconComponent
                  name="Plus"
                  className={"h-4 w-4 hover:text-accent-foreground"}
                />
              </button>
            ) : (
              <button
                data-testid={
                  `input-list-minus-btn${
                    editNode ? "-edit" : ""
                  }_${componentName}-` + idx
                }
                onClick={(e) => {
                  let newInputList = _.cloneDeep(value);
                  newInputList.splice(idx, 1);
                  onChange(newInputList);
                  e.preventDefault();
                }}
                disabled={disabled || playgroundDisabled}
              >
                <IconComponent
                  name="X"
                  className={`h-4 w-4 ${
                    disabled || playgroundDisabled
                      ? ""
                      : "hover:text-accent-foreground"
                  }`}
                />
              </button>
            )}
          </div>
        );
      })}
    </div>
  );
}

Ensure that this code is correctly implemented and that the value passed to the InputListComponent is properly converted to an array if it is initially a string. This should resolve the error you are encountering [1][2].

To continue talking to Dosu, mention @dosu.

same as #2182

Please insert the API key directly instead of using a variable. There is still a bug with using the variable.

duplicated of #2182 and working 1.0.5