Global variables implementation (#1548)

This PR is related to the Global Variables functionality.


![image](https://github.com/logspace-ai/langflow/assets/62335616/0829db58-c26c-499f-9d59-c11fa0a1cf5b)
When clicking the Globe, it's possible to use global variables in any
InputComponent.
When hovering an item, it's possible to delete it.
When clicking on Add New Variable, it's possible to add a new global
variable.
This commit is contained in:
Lucas Oliveira 2024-03-27 23:24:59 +02:00 • committed by GitHub
commit 54fb1ba0bb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
90 changed files with 1626 additions and 1385 deletions

View file

@ -14,7 +14,7 @@ on:
- "src/backend/**"
env:
POETRY_VERSION: "1.7.0"
POETRY_VERSION: "1.8.2"
jobs:
lint:
@ -22,7 +22,6 @@ jobs:
strategy:
matrix:
python-version:
- "3.9"
- "3.10"
- "3.11"
steps:

View file

@ -46,7 +46,7 @@ format:
lint:
make install_backend
poetry run mypy src/backend
poetry run mypy --namespace-packages -p "langflow"
poetry run ruff . --fix
install_frontend:

View file

@ -23,7 +23,7 @@ ENV PYTHONUNBUFFERED=1 \
\
# poetry
# https://python-poetry.org/docs/configuration/#using-environment-variables
POETRY_VERSION=1.7.1 \
POETRY_VERSION=1.8.2 \
# make poetry install to this location
POETRY_HOME="/opt/poetry" \
# make poetry create the virtual environment in the project's root

View file

@ -23,7 +23,7 @@ ENV PYTHONUNBUFFERED=1 \
\
# poetry
# https://python-poetry.org/docs/configuration/#using-environment-variables
POETRY_VERSION=1.7.1 \
POETRY_VERSION=1.8.2 \
# make poetry install to this location
POETRY_HOME="/opt/poetry" \
# make poetry create the virtual environment in the project's root

View file

@ -23,7 +23,7 @@ ENV PYTHONUNBUFFERED=1 \
\
# poetry
# https://python-poetry.org/docs/configuration/#using-environment-variables
POETRY_VERSION=1.5.1 \
POETRY_VERSION=1.8.2 \
# make poetry install to this location
POETRY_HOME="/opt/poetry" \
# make poetry create the virtual environment in the project's root

View file

@ -285,7 +285,12 @@ def run_langflow(host, port, log_level, options, app):
# MacOS requires an env variable to be set to use gunicorn
import uvicorn
uvicorn.run(app, host=host, port=port, log_level=log_level)
uvicorn.run(
app,
host=host,
port=port,
log_level=log_level.lower(),
)
else:
from langflow.server import LangflowApplication

View file

@ -1,199 +0,0 @@
from typing import TYPE_CHECKING, Any, Callable, Coroutine, List, Optional, Tuple, Union
from pydantic.v1 import BaseModel, Field, create_model
from sqlmodel import select
from langflow.schema.schema import INPUT_FIELD_NAME, Record
from langflow.services.database.models.flow.model import Flow
from langflow.services.deps import session_scope
if TYPE_CHECKING:
from langflow.graph.graph.base import Graph
from langflow.graph.vertex.base import Vertex
INPUT_TYPE_MAP = {
"ChatInput": {"type_hint": "Optional[str]", "default": '""'},
"TextInput": {"type_hint": "Optional[str]", "default": '""'},
"JSONInput": {"type_hint": "Optional[dict]", "default": "{}"},
}
def list_flows(*, user_id: Optional[str] = None) -> List[Record]:
if not user_id:
raise ValueError("Session is invalid")
try:
with session_scope() as session:
flows = session.exec(
select(Flow).where(Flow.user_id == user_id).where(Flow.is_component == False) # noqa
).all()
flows_records = [flow.to_record() for flow in flows]
return flows_records
except Exception as e:
raise ValueError(f"Error listing flows: {e}")
async def load_flow(
user_id: str, flow_id: Optional[str] = None, flow_name: Optional[str] = None, tweaks: Optional[dict] = None
) -> "Graph":
from langflow.graph.graph.base import Graph
from langflow.processing.process import process_tweaks
if not flow_id and not flow_name:
raise ValueError("Flow ID or Flow Name is required")
if not flow_id and flow_name:
flow_id = find_flow(flow_name, user_id)
if not flow_id:
raise ValueError(f"Flow {flow_name} not found")
with session_scope() as session:
graph_data = flow.data if (flow := session.get(Flow, flow_id)) else None
if not graph_data:
raise ValueError(f"Flow {flow_id} not found")
if tweaks:
graph_data = process_tweaks(graph_data=graph_data, tweaks=tweaks)
graph = Graph.from_payload(graph_data, flow_id=flow_id)
return graph
def find_flow(flow_name: str, user_id: str) -> Optional[str]:
with session_scope() as session:
flow = session.exec(select(Flow).where(Flow.name == flow_name).where(Flow.user_id == user_id)).first()
return flow.id if flow else None
async def run_flow(
inputs: Union[dict, List[dict]] = None,
tweaks: Optional[dict] = None,
flow_id: Optional[str] = None,
flow_name: Optional[str] = None,
user_id: Optional[str] = None,
) -> Any:
graph = await load_flow(user_id, flow_id, flow_name, tweaks)
if inputs is None:
inputs = []
inputs_list = []
inputs_components = []
types = []
for input_dict in inputs:
inputs_list.append({INPUT_FIELD_NAME: input_dict.get("input_value")})
inputs_components.append(input_dict.get("components", []))
types.append(input_dict.get("type", []))
return await graph.arun(inputs_list, inputs_components=inputs_components, types=types)
def generate_function_for_flow(inputs: List["Vertex"], flow_id: str) -> Coroutine:
"""
Generate a dynamic flow function based on the given inputs and flow ID.
Args:
inputs (List[Vertex]): The list of input vertices for the flow.
flow_id (str): The ID of the flow.
Returns:
Coroutine: The dynamic flow function.
Raises:
None
Example:
inputs = [vertex1, vertex2]
flow_id = "my_flow"
function = generate_function_for_flow(inputs, flow_id)
result = function(input1, input2)
"""
# Prepare function arguments with type hints and default values
args = [
f"{input_.display_name.lower().replace(' ', '_')}: {INPUT_TYPE_MAP[input_.base_name]['type_hint']} = {INPUT_TYPE_MAP[input_.base_name]['default']}"
for input_ in inputs
]
# Maintain original argument names for constructing the tweaks dictionary
original_arg_names = [input_.display_name for input_ in inputs]
# Prepare a Pythonic, valid function argument string
func_args = ", ".join(args)
# Map original argument names to their corresponding Pythonic variable names in the function
arg_mappings = ", ".join(
f'"{original_name}": {name}'
for original_name, name in zip(original_arg_names, [arg.split(":")[0] for arg in args])
)
func_body = f"""
from typing import Optional
async def flow_function({func_args}):
tweaks = {{ {arg_mappings} }}
from langflow.helpers.flow import run_flow
from langchain_core.tools import ToolException
try:
return await run_flow(
tweaks={{key: {{'input_value': value}} for key, value in tweaks.items()}},
flow_id="{flow_id}",
)
except Exception as e:
raise ToolException(f'Error running flow: ' + e)
"""
compiled_func = compile(func_body, "<string>", "exec")
local_scope = {}
exec(compiled_func, globals(), local_scope)
return local_scope["flow_function"]
def build_function_and_schema(flow_record: Record, graph: "Graph") -> Tuple[Callable, BaseModel]:
"""
Builds a dynamic function and schema for a given flow.
Args:
flow_record (Record): The flow record containing information about the flow.
graph (Graph): The graph representing the flow.
Returns:
Tuple[Callable, BaseModel]: A tuple containing the dynamic function and the schema.
"""
flow_id = flow_record.id
inputs = get_flow_inputs(graph)
dynamic_flow_function = generate_function_for_flow(inputs, flow_id)
schema = build_schema_from_inputs(flow_record.name, inputs)
return dynamic_flow_function, schema
def get_flow_inputs(graph: "Graph") -> List["Vertex"]:
"""
Retrieves the flow inputs from the given graph.
Args:
graph (Graph): The graph object representing the flow.
Returns:
List[Record]: A list of input records, where each record contains the ID, name, and description of the input vertex.
"""
inputs = []
for vertex in graph.vertices:
if vertex.is_input:
inputs.append(vertex)
return inputs
def build_schema_from_inputs(name: str, inputs: List[tuple[str, str, str]]) -> BaseModel:
"""
Builds a schema from the given inputs.
Args:
name (str): The name of the schema.
inputs (List[tuple[str, str, str]]): A list of tuples representing the inputs.
Each tuple contains three elements: the input name, the input type, and the input description.
Returns:
BaseModel: The schema model.
"""
fields = {}
for input_ in inputs:
field_name = input_.display_name.lower().replace(" ", "_")
description = input_.description
fields[field_name] = (str, Field(default="", description=description))
return create_model(name, **fields)

View file

@ -1,34 +0,0 @@
from langchain_core.documents import Document
from langflow.schema import Record
def docs_to_records(documents: list[Document]) -> list[Record]:
"""
Converts a list of Documents to a list of Records.
Args:
documents (list[Document]): The list of Documents to convert.
Returns:
list[Record]: The converted list of Records.
"""
return [Record.from_document(document) for document in documents]
def records_to_text(template: str, records: list[Record]) -> str:
"""
Converts a list of Records to a list of texts.
Args:
records (list[Record]): The list of Records to convert.
Returns:
list[str]: The converted list of texts.
"""
if isinstance(records, Record):
records = [records]
# Check if there are any format strings in the template
formated_records = [template.format(data=record.data, **record.data) for record in records]
return "\n".join(formated_records)

View file

@ -0,0 +1,65 @@
"""Replace Credential table with Variable
Revision ID: 1a110b568907
Revises: 63b9c451fd30
Create Date: 2024-03-25 09:40:02.743453
"""
from typing import Sequence, Union
import sqlalchemy as sa
import sqlmodel
from alembic import op
from sqlalchemy.engine.reflection import Inspector
# revision identifiers, used by Alembic.
revision: str = "1a110b568907"
down_revision: Union[str, None] = "63b9c451fd30"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
conn = op.get_bind()
inspector = Inspector.from_engine(conn) # type: ignore
table_names = inspector.get_table_names()
# ### commands auto generated by Alembic - please adjust! ###
if "variable" not in table_names:
op.create_table(
"variable",
sa.Column("name", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
sa.Column("value", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
sa.Column("type", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
sa.Column("id", sqlmodel.sql.sqltypes.GUID(), nullable=False),
sa.Column("created_at", sa.DateTime(), nullable=False),
sa.Column("updated_at", sa.DateTime(), nullable=True),
sa.Column("user_id", sqlmodel.sql.sqltypes.GUID(), nullable=False),
sa.ForeignKeyConstraint(["user_id"], ["user.id"], name="fk_variable_user_id"),
sa.PrimaryKeyConstraint("id"),
)
if "credential" in table_names:
op.drop_table("credential")
# ### end Alembic commands ###
def downgrade() -> None:
conn = op.get_bind()
inspector = Inspector.from_engine(conn) # type: ignore
table_names = inspector.get_table_names()
# ### commands auto generated by Alembic - please adjust! ###
if "credential" not in table_names:
op.create_table(
"credential",
sa.Column("name", sa.VARCHAR(), nullable=True),
sa.Column("value", sa.VARCHAR(), nullable=True),
sa.Column("provider", sa.VARCHAR(), nullable=True),
sa.Column("user_id", sa.CHAR(length=32), nullable=False),
sa.Column("id", sa.CHAR(length=32), nullable=False),
sa.Column("created_at", sa.DATETIME(), nullable=False),
sa.Column("updated_at", sa.DATETIME(), nullable=True),
sa.ForeignKeyConstraint(["user_id"], ["user.id"], name="fk_credential_user_id"),
sa.PrimaryKeyConstraint("id"),
)
if "variable" in table_names:
op.drop_table("variable")
# ### end Alembic commands ###

View file

@ -4,7 +4,6 @@ from fastapi import APIRouter
from langflow.api.v1 import (
api_key_router,
chat_router,
credentials_router,
endpoints_router,
files_router,
flows_router,
@ -13,6 +12,7 @@ from langflow.api.v1 import (
store_router,
users_router,
validate_router,
variables_router,
)
router = APIRouter(
@ -26,6 +26,6 @@ router.include_router(flows_router)
router.include_router(users_router)
router.include_router(api_key_router)
router.include_router(login_router)
router.include_router(credentials_router)
router.include_router(variables_router)
router.include_router(files_router)
router.include_router(monitor_router)

View file

@ -125,6 +125,9 @@ def update_template_field(frontend_template, key, value_dict):
template_field["value"] = ""
template_field["file_path"] = file_path_value
if "load_from_db" in value_dict and value_dict["load_from_db"]:
template_field["load_from_db"] = value_dict["load_from_db"]
def get_file_path_value(file_path):
"""Get the file path value if the file exists, else return empty string."""
@ -161,7 +164,7 @@ def get_is_component_from_data(data: dict):
async def check_langflow_version(component: StoreComponentCreate):
from langflow import __version__ as current_version
from langflow.version.version import __version__ as current_version # type: ignore
if not component.last_tested_version:
component.last_tested_version = current_version

View file

@ -1,6 +1,5 @@
from langflow.api.v1.api_key import router as api_key_router
from langflow.api.v1.chat import router as chat_router
from langflow.api.v1.credential import router as credentials_router
from langflow.api.v1.endpoints import router as endpoints_router
from langflow.api.v1.files import router as files_router
from langflow.api.v1.flows import router as flows_router
@ -9,6 +8,7 @@ from langflow.api.v1.monitor import router as monitor_router
from langflow.api.v1.store import router as store_router
from langflow.api.v1.users import router as users_router
from langflow.api.v1.validate import router as validate_router
from langflow.api.v1.variable import router as variables_router
__all__ = [
"chat_router",
@ -19,7 +19,7 @@ __all__ = [
"users_router",
"api_key_router",
"login_router",
"credentials_router",
"variables_router",
"monitor_router",
"files_router",
]

View file

@ -1,111 +0,0 @@
from datetime import datetime
from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException
from sqlmodel import Session, select
from langflow.services.auth import utils as auth_utils
from langflow.services.auth.utils import get_current_active_user
from langflow.services.database.models.credential import Credential, CredentialCreate, CredentialRead, CredentialUpdate
from langflow.services.database.models.user.model import User
from langflow.services.deps import get_session, get_settings_service
router = APIRouter(prefix="/credentials", tags=["Credentials"])
@router.post("/", response_model=CredentialRead, status_code=201)
def create_credential(
*,
session: Session = Depends(get_session),
credential: CredentialCreate,
current_user: User = Depends(get_current_active_user),
settings_service=Depends(get_settings_service),
):
"""Create a new credential."""
try:
# check if credential name already exists
credential_exists = session.exec(
select(Credential).where(Credential.name == credential.name, Credential.user_id == current_user.id)
).first()
if credential_exists:
raise HTTPException(status_code=400, detail="Credential name already exists")
credential_dict = credential.model_dump()
credential_dict["user_id"] = current_user.id
db_credential = Credential.model_validate(credential_dict)
if not db_credential.value:
raise HTTPException(status_code=400, detail="Credential value cannot be empty")
encrypted = auth_utils.encrypt_api_key(db_credential.value, settings_service=settings_service)
db_credential.value = encrypted
db_credential.user_id = current_user.id
session.add(db_credential)
session.commit()
session.refresh(db_credential)
return db_credential
except Exception as e:
if isinstance(e, HTTPException):
raise e
raise HTTPException(status_code=500, detail=str(e)) from e
@router.get("/", response_model=list[CredentialRead], status_code=200)
def read_credentials(
*,
session: Session = Depends(get_session),
current_user: User = Depends(get_current_active_user),
):
"""Read all credentials."""
try:
credentials = session.exec(select(Credential).where(Credential.user_id == current_user.id)).all()
return credentials
except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) from e
@router.patch("/{credential_id}", response_model=CredentialRead, status_code=200)
def update_credential(
*,
session: Session = Depends(get_session),
credential_id: UUID,
credential: CredentialUpdate,
current_user: User = Depends(get_current_active_user),
):
"""Update a credential."""
try:
db_credential = session.exec(
select(Credential).where(Credential.id == credential_id, Credential.user_id == current_user.id)
).first()
if not db_credential:
raise HTTPException(status_code=404, detail="Credential not found")
credential_data = credential.model_dump(exclude_unset=True)
for key, value in credential_data.items():
setattr(db_credential, key, value)
db_credential.updated_at = datetime.utcnow()
session.commit()
session.refresh(db_credential)
return db_credential
except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) from e
@router.delete("/{credential_id}", response_model=CredentialRead, status_code=200)
def delete_credential(
*,
session: Session = Depends(get_session),
credential_id: UUID,
current_user: User = Depends(get_current_active_user),
):
"""Delete a credential."""
try:
db_credential = session.exec(
select(Credential).where(Credential.id == credential_id, Credential.user_id == current_user.id)
).first()
if not db_credential:
raise HTTPException(status_code=404, detail="Credential not found")
session.delete(db_credential)
session.commit()
return db_credential
except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) from e

View file

@ -239,7 +239,7 @@ async def create_upload_file(
# get endpoint to return version of langflow
@router.get("/version")
def get_version():
from langflow.version import __version__
from langflow.version import __version__ # type: ignore
return {"version": __version__}

View file

@ -0,0 +1,113 @@
from datetime import datetime
from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException
from sqlmodel import Session, select
from langflow.services.auth import utils as auth_utils
from langflow.services.auth.utils import get_current_active_user
from langflow.services.database.models.user.model import User
from langflow.services.database.models.variable import Variable, VariableCreate, VariableRead, VariableUpdate
from langflow.services.deps import get_session, get_settings_service
router = APIRouter(prefix="/variables", tags=["Variables"])
@router.post("/", response_model=VariableRead, status_code=201)
def create_variable(
*,
session: Session = Depends(get_session),
variable: VariableCreate,
current_user: User = Depends(get_current_active_user),
settings_service=Depends(get_settings_service),
):
"""Create a new variable."""
try:
# check if variable name already exists
variable_exists = session.exec(
select(Variable).where(
Variable.name == variable.name,
Variable.user_id == current_user.id,
)
).first()
if variable_exists:
raise HTTPException(status_code=400, detail="Variable name already exists")
variable_dict = variable.model_dump()
variable_dict["user_id"] = current_user.id
db_variable = Variable.model_validate(variable_dict)
if not db_variable.value:
raise HTTPException(status_code=400, detail="Variable value cannot be empty")
encrypted = auth_utils.encrypt_api_key(db_variable.value, settings_service=settings_service)
db_variable.value = encrypted
db_variable.user_id = current_user.id
session.add(db_variable)
session.commit()
session.refresh(db_variable)
return db_variable
except Exception as e:
if isinstance(e, HTTPException):
raise e
raise HTTPException(status_code=500, detail=str(e)) from e
@router.get("/", response_model=list[VariableRead], status_code=200)
def read_variables(
*,
session: Session = Depends(get_session),
current_user: User = Depends(get_current_active_user),
):
"""Read all variables."""
try:
variables = session.exec(select(Variable).where(Variable.user_id == current_user.id)).all()
return variables
except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) from e
@router.patch("/{variable_id}", response_model=VariableRead, status_code=200)
def update_variable(
*,
session: Session = Depends(get_session),
variable_id: UUID,
variable: VariableUpdate,
current_user: User = Depends(get_current_active_user),
):
"""Update a variable."""
try:
db_variable = session.exec(
select(Variable).where(Variable.id == variable_id, Variable.user_id == current_user.id)
).first()
if not db_variable:
raise HTTPException(status_code=404, detail="Variable not found")
variable_data = variable.model_dump(exclude_unset=True)
for key, value in variable_data.items():
setattr(db_variable, key, value)
db_variable.updated_at = datetime.utcnow()
session.commit()
session.refresh(db_variable)
return db_variable
except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) from e
@router.delete("/{variable_id}", status_code=204)
def delete_variable(
*,
session: Session = Depends(get_session),
variable_id: UUID,
current_user: User = Depends(get_current_active_user),
):
"""Delete a variable."""
try:
db_variable = session.exec(
select(Variable).where(Variable.id == variable_id, Variable.user_id == current_user.id)
).first()
if not db_variable:
raise HTTPException(status_code=404, detail="Variable not found")
session.delete(db_variable)
session.commit()
except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) from e

View file

@ -1,8 +1,10 @@
from typing import List, Union
from typing import List, Optional, Union, cast
from langchain.agents import AgentExecutor, BaseMultiActionAgent, BaseSingleActionAgent
from langchain_core.runnables import Runnable
from langflow.custom import CustomComponent
from langflow.field_typing import BaseMemory, Text, Tool
from langflow.interface.custom.custom_component import CustomComponent
class LCAgentComponent(CustomComponent):
@ -38,11 +40,11 @@ class LCAgentComponent(CustomComponent):
async def run_agent(
self,
agent: Union[BaseSingleActionAgent, BaseMultiActionAgent, AgentExecutor],
agent: Union[Runnable, BaseSingleActionAgent, BaseMultiActionAgent, AgentExecutor],
inputs: str,
input_variables: list[str],
tools: List[Tool],
memory: BaseMemory = None,
memory: Optional[BaseMemory] = None,
handle_parsing_errors: bool = True,
output_key: str = "output",
) -> Text:
@ -50,7 +52,11 @@ class LCAgentComponent(CustomComponent):
runnable = agent
else:
runnable = AgentExecutor.from_agent_and_tools(
agent=agent, tools=tools, verbose=True, memory=memory, handle_parsing_errors=handle_parsing_errors
agent=agent, # type: ignore
tools=tools,
verbose=True,
memory=memory,
handle_parsing_errors=handle_parsing_errors,
)
input_dict = {"input": inputs}
for var in input_variables:
@ -59,11 +65,11 @@ class LCAgentComponent(CustomComponent):
result = await runnable.ainvoke(input_dict)
self.status = result
if output_key in result:
return result.get(output_key)
return cast(str, result.get(output_key))
elif "output" not in result:
if output_key != "output":
raise ValueError(f"Output key not found in result. Tried '{output_key}' and 'output'.")
else:
raise ValueError("Output key not found in result. Tried 'output'.")
return result.get("output")
return cast(str, result.get("output"))

View file

@ -1,10 +1,10 @@
from typing import Optional
from typing import Optional, Union
from langchain_core.language_models.chat_models import BaseChatModel
from langchain_core.language_models.llms import LLM
from langchain_core.messages import HumanMessage, SystemMessage
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
class LCModelComponent(CustomComponent):
@ -34,15 +34,15 @@ class LCModelComponent(CustomComponent):
def get_chat_result(
self, runnable: BaseChatModel, stream: bool, input_value: str, system_message: Optional[str] = None
):
messages = []
messages: list[Union[HumanMessage, SystemMessage]] = []
if system_message:
messages.append(SystemMessage(system_message))
messages.append(SystemMessage(content=system_message))
if input_value:
messages.append(HumanMessage(input_value))
messages.append(HumanMessage(content=input_value))
if stream:
result = runnable.stream(messages)
return runnable.stream(messages)
else:
message = runnable.invoke(messages)
result = message.content
self.status = result
return result
return result

View file

@ -1,4 +1,4 @@
from typing import List
from typing import List, Optional
from langchain.agents import create_xml_agent
from langchain_core.prompts import PromptTemplate
@ -69,7 +69,7 @@ class XMLAgentComponent(LCAgentComponent):
llm: BaseLLM,
tools: List[Tool],
prompt: str,
memory: BaseMemory = None,
memory: Optional[BaseMemory] = None,
tool_template: str = "{name}: {description}",
handle_parsing_errors: bool = True,
) -> Text:

View file

@ -22,7 +22,7 @@ class CohereEmbeddingsComponent(CustomComponent):
self,
request_timeout: Optional[float] = None,
cohere_api_key: str = "",
max_retries: Optional[int] = None,
max_retries: int = 3,
model: str = "embed-english-v2.0",
truncate: Optional[str] = None,
user_agent: str = "langchain",

View file

@ -1,7 +1,6 @@
from typing import Any, Callable, Dict, List, Optional, Union
from langchain_openai.embeddings.base import OpenAIEmbeddings
from pydantic.v1.types import SecretStr
from langflow.field_typing import NestedDict
from langflow.interface.custom.custom_component import CustomComponent
@ -100,8 +99,6 @@ class OpenAIEmbeddingsComponent(CustomComponent):
if disallowed_special == ["all"]:
disallowed_special = "all" # type: ignore
api_key = SecretStr(openai_api_key) if openai_api_key else None
return OpenAIEmbeddings(
tiktoken_enabled=tiktoken_enable,
default_headers=default_headers,
@ -116,7 +113,7 @@ class OpenAIEmbeddingsComponent(CustomComponent):
model=model,
model_kwargs=model_kwargs,
base_url=openai_api_base,
api_key=api_key,
api_key=openai_api_key,
openai_api_type=openai_api_type,
api_version=openai_api_version,
organization=openai_organization,

Some files were not shown because too many files have changed in this diff Show more