Split Langflow into Langflow and Langflow Base (#1562)

* Initial Restructure

* Replace import langflow for import langflow_base

* Fix dependencies

* 🔧 chore(Makefile): refactor build process to separate base and frontend builds for better organization and maintainability

* 🚀 chore(Makefile): update build_frontend command to copy frontend build to the correct directory
🔖 chore(pyproject.toml): update python and httpx dependencies versions
🔧 chore(__init__.py): update import statement for load_flow_from_json function

* 🔖 chore(pyproject.toml): update package version from 0.0.6 to 0.0.8 to reflect changes in the codebase

* 🚀 feat(server.ts): change port variable case from lowercase port to uppercase PORT to improve semantics
🚀 feat(server.ts): add support for process.env.PORT environment variable to be able to run app on a configurable port

* 🐛 fix(server.ts): change port variable case from lowercase port to uppercase PORT to improve semantics
✨ feat(server.ts): add support for process.env.PORT environment variable to be able to run app on a configurable port
🚚 chore(pyproject.toml): update langflow-base version from 0.0.8 to 0.0.10
✨ feat(server.ts): add new agent component LCAgentComponent to langflow_base
✨ feat(server.ts): add new model component LCModelComponent to langflow_base
✨ feat(server.ts): add new helper functions docs_to_records and records_to_text to langflow_base
✨ feat(server.ts): add new flow helper functions list_flows, load_flow, run_flow, generate_function_for_flow, get_flow_inputs, build_schema_from_inputs to langflow_base
✨ feat(server.ts): add new prompt component PromptComponent to langflow_base
✨ feat(server.ts): add new chat components ChatInput and ChatOutput to langflow_base
✨ feat(server.ts): add new model component OpenAIModelComponent to langflow_base
🚚 chore(main.py): update import path from langflow.main to langflow_base.main
🚚 chore(service.py): update import path from langflow.services.database.manager to langflow_base.services.database.manager
🚚 chore(factory.py): update import path from langflow.services to langflow_base.services
🚚 chore(service.py): update import path from langflow.services.plugins to langflow_base.services.plugins
🚚 chore(utils.py): update import path from langflow.services to langflow_base.services
🚚 chore(validate.py): update import path from langflow.field_typing to langflow_base.field_typing
🚚 chore(pyproject.toml): update langflow-base version from 0.0.8 to 0.0.10

* Update Makefile to install backend dependencies and build langflow

* Add langflow main module and update __init__.py

* Update langflow install process to use implicit namespace

* Add langflow-base as a local dependency

* Add setup_poetry target to Makefile

* Update Poetry version and add poetry-monorepo-dependency-plugin

* Refactor code to improve performance and readability

* Update imports to custom and load

* Update content-hash in poetry.lock

---------

Co-authored-by: Matheus <jacquesmats@gmail.com>
Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@logspace.ai>
This commit is contained in:
Matheus Jacques 2024-03-26 13:26:30 +01:00 • committed by GitHub
commit 8172e62236
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
466 changed files with 5418 additions and 1144 deletions

View file

@ -0,0 +1,348 @@
import platform
import socket
import sys
import time
import webbrowser
from pathlib import Path
from typing import Optional
import httpx
import typer
from dotenv import load_dotenv
from multiprocess import Process, cpu_count # type: ignore
from rich import box
from rich import print as rprint
from rich.console import Console
from rich.panel import Panel
from rich.table import Table
from langflow.main import setup_app
from langflow.services.database.utils import session_getter
from langflow.services.deps import get_db_service, get_settings_service
from langflow.services.utils import initialize_services, initialize_settings_service
from langflow.utils.logger import configure, logger
console = Console()
app = typer.Typer(no_args_is_help=True)
def get_number_of_workers(workers=None):
if workers == -1 or workers is None:
workers = (cpu_count() * 2) + 1
logger.debug(f"Number of workers: {workers}")
return workers
def display_results(results):
"""
Display the results of the migration.
"""
for table_results in results:
table = Table(title=f"Migration {table_results.table_name}")
table.add_column("Name")
table.add_column("Type")
table.add_column("Status")
for result in table_results.results:
status = "Success" if result.success else "Failure"
color = "green" if result.success else "red"
table.add_row(result.name, result.type, f"[{color}]{status}[/{color}]")
console.print(table)
console.print() # Print a new line
def set_var_for_macos_issue():
# OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
# we need to set this var is we are running on MacOS
# otherwise we get an error when running gunicorn
if platform.system() in ["Darwin"]:
import os
os.environ["OBJC_DISABLE_INITIALIZE_FORK_SAFETY"] = "YES"
# https://stackoverflow.com/questions/75747888/uwsgi-segmentation-fault-with-flask-python-app-behind-nginx-after-running-for-2 # noqa
os.environ["no_proxy"] = "*" # to avoid error with gunicorn
logger.debug("Set OBJC_DISABLE_INITIALIZE_FORK_SAFETY to YES to avoid error")
def update_settings(
config: str,
cache: Optional[str] = None,
dev: bool = False,
remove_api_keys: bool = False,
components_path: Optional[Path] = None,
store: bool = True,
):
"""Update the settings from a config file."""
# Check for database_url in the environment variables
initialize_settings_service()
settings_service = get_settings_service()
if config:
logger.debug(f"Loading settings from {config}")
settings_service.settings.update_from_yaml(config, dev=dev)
if remove_api_keys:
logger.debug(f"Setting remove_api_keys to {remove_api_keys}")
settings_service.settings.update_settings(REMOVE_API_KEYS=remove_api_keys)
if cache:
logger.debug(f"Setting cache to {cache}")
settings_service.settings.update_settings(CACHE=cache)
if components_path:
logger.debug(f"Adding component path {components_path}")
settings_service.settings.update_settings(COMPONENTS_PATH=components_path)
if not store:
logger.debug("Setting store to False")
settings_service.settings.update_settings(STORE=False)
@app.command()
def run(
host: str = typer.Option("127.0.0.1", help="Host to bind the server to.", envvar="LANGFLOW_HOST"),
workers: int = typer.Option(1, help="Number of worker processes.", envvar="LANGFLOW_WORKERS"),
timeout: int = typer.Option(300, help="Worker timeout in seconds."),
port: int = typer.Option(7860, help="Port to listen on.", envvar="LANGFLOW_PORT"),
components_path: Optional[Path] = typer.Option(
Path(__file__).parent / "components",
help="Path to the directory containing custom components.",
envvar="LANGFLOW_COMPONENTS_PATH",
),
config: str = typer.Option(Path(__file__).parent / "config.yaml", help="Path to the configuration file."),
# .env file param
env_file: Path = typer.Option(None, help="Path to the .env file containing environment variables."),
log_level: str = typer.Option("critical", help="Logging level.", envvar="LANGFLOW_LOG_LEVEL"),
log_file: Path = typer.Option("logs/langflow.log", help="Path to the log file.", envvar="LANGFLOW_LOG_FILE"),
cache: Optional[str] = typer.Option(
envvar="LANGFLOW_LANGCHAIN_CACHE",
help="Type of cache to use. (InMemoryCache, SQLiteCache)",
default=None,
),
dev: bool = typer.Option(False, help="Run in development mode (may contain bugs)"),
path: str = typer.Option(
None,
help="Path to the frontend directory containing build files. This is for development purposes only.",
envvar="LANGFLOW_FRONTEND_PATH",
),
open_browser: bool = typer.Option(
True,
help="Open the browser after starting the server.",
envvar="LANGFLOW_OPEN_BROWSER",
),
remove_api_keys: bool = typer.Option(
False,
help="Remove API keys from the projects saved in the database.",
envvar="LANGFLOW_REMOVE_API_KEYS",
),
backend_only: bool = typer.Option(
False,
help="Run only the backend server without the frontend.",
envvar="LANGFLOW_BACKEND_ONLY",
),
store: bool = typer.Option(
True,
help="Enables the store features.",
envvar="LANGFLOW_STORE",
),
):
"""
Run the Langflow.
"""
set_var_for_macos_issue()
# override env variables with .env file
if env_file:
load_dotenv(env_file, override=True)
configure(log_level=log_level, log_file=log_file)
update_settings(
config,
dev=dev,
remove_api_keys=remove_api_keys,
cache=cache,
components_path=components_path,
store=store,
)
# create path object if path is provided
static_files_dir: Optional[Path] = Path(path) if path else None
app = setup_app(static_files_dir=static_files_dir, backend_only=backend_only)
# check if port is being used
if is_port_in_use(port, host):
port = get_free_port(port)
options = {
"bind": f"{host}:{port}",
"workers": get_number_of_workers(workers),
"timeout": timeout,
}
# Define an env variable to know if we are just testing the server
if "pytest" in sys.modules:
return
if platform.system() in ["Windows"]:
# Run using uvicorn on MacOS and Windows
# Windows doesn't support gunicorn
# MacOS requires an env variable to be set to use gunicorn
run_on_windows(host, port, log_level, options, app)
else:
# Run using gunicorn on Linux
run_on_mac_or_linux(host, port, log_level, options, app, open_browser)
def run_on_mac_or_linux(host, port, log_level, options, app, open_browser=True):
webapp_process = Process(target=run_langflow, args=(host, port, log_level, options, app))
webapp_process.start()
status_code = 0
while status_code != 200:
try:
status_code = httpx.get(f"http://{host}:{port}/health").status_code
except Exception:
time.sleep(1)
print_banner(host, port)
if open_browser:
webbrowser.open(f"http://{host}:{port}")
def run_on_windows(host, port, log_level, options, app):
"""
Run the Langflow server on Windows.
"""
print_banner(host, port)
run_langflow(host, port, log_level, options, app)
def is_port_in_use(port, host="localhost"):
"""
Check if a port is in use.
Args:
port (int): The port number to check.
host (str): The host to check the port on. Defaults to 'localhost'.
Returns:
bool: True if the port is in use, False otherwise.
"""
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
return s.connect_ex((host, port)) == 0
def get_free_port(port):
"""
Given a used port, find a free port.
Args:
port (int): The port number to check.
Returns:
int: A free port number.
"""
while is_port_in_use(port):
port += 1
return port
def print_banner(host, port):
# console = Console()
word = "Langflow"
colors = ["#3300cc"]
styled_word = ""
for i, char in enumerate(word):
color = colors[i % len(colors)]
styled_word += f"[{color}]{char}[/]"
# Title with emojis and gradient text
title = (
f"[bold]Welcome to :chains: {styled_word} [/bold]\n\n"
f"Access [link=http://{host}:{port}]http://{host}:{port}[/link]"
)
info_text = (
"Collaborate, and contribute at our "
"[bold][link=https://github.com/logspace-ai/langflow]GitHub Repo[/link][/bold] :rocket:"
)
# Create a panel with the title and the info text, and a border around it
panel = Panel(f"{title}\n{info_text}", box=box.ROUNDED, border_style="blue", expand=False)
# Print the banner with a separator line before and after
rprint(panel)
def run_langflow(host, port, log_level, options, app):
"""
Run Langflow server on localhost
"""
try:
if platform.system() in ["Windows"]:
# Run using uvicorn on MacOS and Windows
# Windows doesn't support gunicorn
# MacOS requires an env variable to be set to use gunicorn
import uvicorn
uvicorn.run(app, host=host, port=port, log_level=log_level)
else:
from langflow.server import LangflowApplication
LangflowApplication(app, options).run()
except KeyboardInterrupt:
pass
except Exception as e:
logger.exception(e)
sys.exit(1)
@app.command()
def superuser(
username: str = typer.Option(..., prompt=True, help="Username for the superuser."),
password: str = typer.Option(..., prompt=True, hide_input=True, help="Password for the superuser."),
log_level: str = typer.Option("critical", help="Logging level.", envvar="LANGFLOW_LOG_LEVEL"),
):
"""
Create a superuser.
"""
configure(log_level=log_level)
initialize_services()
db_service = get_db_service()
with session_getter(db_service) as session:
from langflow.services.auth.utils import create_super_user
if create_super_user(db=session, username=username, password=password):
# Verify that the superuser was created
from langflow.services.database.models.user.model import User
user: User = session.query(User).filter(User.username == username).first()
if user is None or not user.is_superuser:
typer.echo("Superuser creation failed.")
return
typer.echo("Superuser created successfully.")
else:
typer.echo("Superuser creation failed.")
@app.command()
def migration(test: bool = typer.Option(True, help="Run migrations in test mode.")):
"""
Run or test migrations.
"""
initialize_services()
db_service = get_db_service()
if not test:
db_service.run_migrations()
results = db_service.run_migrations_test()
display_results(results)
def main():
app()
if __name__ == "__main__":
main()

View file

@ -66,14 +66,10 @@ def run_migrations_online() -> None:
try:
from langflow.services.database.factory import DatabaseServiceFactory
from langflow.services.deps import get_db_service
from langflow.services.manager import (initialize_settings_service,
service_manager)
from langflow.services.schema import ServiceType
from langflow.services.manager import initialize_settings_service, service_manager
initialize_settings_service()
service_manager.register_factory(
DatabaseServiceFactory()
)
service_manager.register_factory(DatabaseServiceFactory())
connectable = get_db_service().engine
except Exception as e:
logger.error(f"Error getting database engine: {e}")
@ -87,9 +83,7 @@ def run_migrations_online() -> None:
poolclass=pool.NullPool,
)
with connectable.connect() as connection:
context.configure(
connection=connection, target_metadata=target_metadata, render_as_batch=True
)
context.configure(connection=connection, target_metadata=target_metadata, render_as_batch=True)
with context.begin_transaction():
context.run_migrations()

View file

@ -26,20 +26,13 @@ def upgrade() -> None:
flow_constraints = inspector.get_unique_constraints("flow")
user_constraints = inspector.get_unique_constraints("user")
try:
if not any(
constraint["name"] == "uq_apikey_id" for constraint in api_key_constraints
):
if not any(constraint["name"] == "uq_apikey_id" for constraint in api_key_constraints):
with op.batch_alter_table("apikey", schema=None) as batch_op:
batch_op.create_unique_constraint("uq_apikey_id", ["id"])
if not any(
constraint["name"] == "uq_flow_id" for constraint in flow_constraints
):
if not any(constraint["name"] == "uq_flow_id" for constraint in flow_constraints):
with op.batch_alter_table("flow", schema=None) as batch_op:
batch_op.create_unique_constraint("uq_flow_id", ["id"])
if not any(
constraint["name"] == "uq_user_id" for constraint in user_constraints
):
if not any(constraint["name"] == "uq_user_id" for constraint in user_constraints):
with op.batch_alter_table("user", schema=None) as batch_op:
batch_op.create_unique_constraint("uq_user_id", ["id"])
except Exception as e:
@ -57,16 +50,13 @@ def downgrade() -> None:
flow_constraints = inspector.get_unique_constraints("flow")
user_constraints = inspector.get_unique_constraints("user")
try:
if any(
constraint["name"] == "uq_apikey_id" for constraint in api_key_constraints
):
if any(constraint["name"] == "uq_apikey_id" for constraint in api_key_constraints):
with op.batch_alter_table("user", schema=None) as batch_op:
batch_op.drop_constraint("uq_user_id", type_="unique")
if any(constraint["name"] == "uq_flow_id" for constraint in flow_constraints):
with op.batch_alter_table("flow", schema=None) as batch_op:
batch_op.drop_constraint("uq_flow_id", type_="unique")
if any(constraint["name"] == "uq_user_id" for constraint in user_constraints):
with op.batch_alter_table("apikey", schema=None) as batch_op:
batch_op.drop_constraint("uq_apikey_id", type_="unique")
except Exception as e:

View file

@ -24,10 +24,8 @@ def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
try:
with op.batch_alter_table("apikey", schema=None) as batch_op:
batch_op.alter_column(
"name", existing_type=sqlmodel.sql.sqltypes.AutoString(), nullable=True
)
except Exception as e:
batch_op.alter_column("name", existing_type=sqlmodel.sql.sqltypes.AutoString(), nullable=True)
except Exception:
pass
# ### end Alembic commands ###
@ -37,6 +35,6 @@ def downgrade() -> None:
try:
with op.batch_alter_table("apikey", schema=None) as batch_op:
batch_op.alter_column("name", existing_type=sa.VARCHAR(), nullable=False)
except Exception as e:
except Exception:
pass
# ### end Alembic commands ###

View file

@ -31,23 +31,16 @@ def upgrade() -> None:
# and other related indices
if "flowstyle" in existing_tables:
op.drop_table("flowstyle")
if "ix_flowstyle_flow_id" in [
index["name"] for index in inspector.get_indexes("flowstyle")
]:
op.drop_index(
"ix_flowstyle_flow_id", table_name="flowstyle", if_exists=True
)
if "ix_flowstyle_flow_id" in [index["name"] for index in inspector.get_indexes("flowstyle")]:
op.drop_index("ix_flowstyle_flow_id", table_name="flowstyle", if_exists=True)
existing_indices_flow = []
existing_fks_flow = []
if "flow" in existing_tables:
existing_indices_flow = [
index["name"] for index in inspector.get_indexes("flow")
]
existing_indices_flow = [index["name"] for index in inspector.get_indexes("flow")]
# Existing foreign keys for the 'flow' table, if it exists
existing_fks_flow = [
fk["referred_table"] + "." + fk["referred_columns"][0]
for fk in inspector.get_foreign_keys("flow")
fk["referred_table"] + "." + fk["referred_columns"][0] for fk in inspector.get_foreign_keys("flow")
]
# Now check if the columns user_id exists in the 'flow' table
# If it does not exist, we need to create the foreign key
@ -67,9 +60,7 @@ def upgrade() -> None:
sa.UniqueConstraint("id", name="uq_user_id"),
)
with op.batch_alter_table("user", schema=None) as batch_op:
batch_op.create_index(
batch_op.f("ix_user_username"), ["username"], unique=True
)
batch_op.create_index(batch_op.f("ix_user_username"), ["username"], unique=True)
if "apikey" not in existing_tables:
op.create_table(
@ -82,20 +73,14 @@ def upgrade() -> None:
sa.Column("id", sqlmodel.sql.sqltypes.GUID(), nullable=False),
sa.Column("api_key", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
sa.Column("user_id", sqlmodel.sql.sqltypes.GUID(), nullable=False),
sa.ForeignKeyConstraint(
["user_id"], ["user.id"], name="fk_apikey_user_id_user"
),
sa.ForeignKeyConstraint(["user_id"], ["user.id"], name="fk_apikey_user_id_user"),
sa.PrimaryKeyConstraint("id", name="pk_apikey"),
sa.UniqueConstraint("id", name="uq_apikey_id"),
)
with op.batch_alter_table("apikey", schema=None) as batch_op:
batch_op.create_index(
batch_op.f("ix_apikey_api_key"), ["api_key"], unique=True
)
batch_op.create_index(batch_op.f("ix_apikey_api_key"), ["api_key"], unique=True)
batch_op.create_index(batch_op.f("ix_apikey_name"), ["name"], unique=False)
batch_op.create_index(
batch_op.f("ix_apikey_user_id"), ["user_id"], unique=False
)
batch_op.create_index(batch_op.f("ix_apikey_user_id"), ["user_id"], unique=False)
if "flow" not in existing_tables:
op.create_table(
"flow",
@ -104,9 +89,7 @@ def upgrade() -> None:
sa.Column("description", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
sa.Column("id", sqlmodel.sql.sqltypes.GUID(), nullable=False),
sa.Column("user_id", sqlmodel.sql.sqltypes.GUID(), nullable=False),
sa.ForeignKeyConstraint(
["user_id"], ["user.id"], name="fk_flow_user_id_user"
),
sa.ForeignKeyConstraint(["user_id"], ["user.id"], name="fk_flow_user_id_user"),
sa.PrimaryKeyConstraint("id", name="pk_flow"),
sa.UniqueConstraint("id", name="uq_flow_id"),
)
@ -129,16 +112,12 @@ def upgrade() -> None:
if "user.id" not in existing_fks_flow:
batch_op.create_foreign_key("fk_flow_user_id", "user", ["user_id"], ["id"])
if "ix_flow_description" not in existing_indices_flow:
batch_op.create_index(
batch_op.f("ix_flow_description"), ["description"], unique=False
)
batch_op.create_index(batch_op.f("ix_flow_description"), ["description"], unique=False)
if "ix_flow_name" not in existing_indices_flow:
batch_op.create_index(batch_op.f("ix_flow_name"), ["name"], unique=False)
with op.batch_alter_table("flow", schema=None) as batch_op:
if "ix_flow_user_id" not in existing_indices_flow:
batch_op.create_index(
batch_op.f("ix_flow_user_id"), ["user_id"], unique=False
)
batch_op.create_index(batch_op.f("ix_flow_user_id"), ["user_id"], unique=False)
# ### end Alembic commands ###

View file

@ -31,9 +31,7 @@ def upgrade() -> None:
"credential",
sa.Column("name", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
sa.Column("value", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
sa.Column(
"provider", sqlmodel.sql.sqltypes.AutoString(), nullable=True
),
sa.Column("provider", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
sa.Column("user_id", sqlmodel.sql.sqltypes.GUID(), nullable=False),
sa.Column("id", sqlmodel.sql.sqltypes.GUID(), nullable=False),
sa.Column("created_at", sa.DateTime(), nullable=False),

View file

@ -23,20 +23,14 @@ 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()
table_names = inspector.get_table_names() # noqa
column_names = [column["name"] for column in inspector.get_columns("flow")]
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table("flow", schema=None) as batch_op:
if "icon" not in column_names:
batch_op.add_column(
sa.Column("icon", sqlmodel.sql.sqltypes.AutoString(), nullable=True)
)
batch_op.add_column(sa.Column("icon", sqlmodel.sql.sqltypes.AutoString(), nullable=True))
if "icon_bg_color" not in column_names:
batch_op.add_column(
sa.Column(
"icon_bg_color", sqlmodel.sql.sqltypes.AutoString(), nullable=True
)
)
batch_op.add_column(sa.Column("icon_bg_color", sqlmodel.sql.sqltypes.AutoString(), nullable=True))
# ### end Alembic commands ###
@ -44,7 +38,7 @@ def upgrade() -> None:
def downgrade() -> None:
conn = op.get_bind()
inspector = Inspector.from_engine(conn) # type: ignore
table_names = inspector.get_table_names()
table_names = inspector.get_table_names() # noqa
column_names = [column["name"] for column in inspector.get_columns("flow")]
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table("flow", schema=None) as batch_op:

View file

@ -29,18 +29,14 @@ def upgrade() -> None:
try:
if "is_component" not in flow_columns:
with op.batch_alter_table("flow", schema=None) as batch_op:
batch_op.add_column(
sa.Column("is_component", sa.Boolean(), nullable=True)
)
except Exception as e:
batch_op.add_column(sa.Column("is_component", sa.Boolean(), nullable=True))
except Exception:
pass
try:
if "store_api_key" not in user_columns:
with op.batch_alter_table("user", schema=None) as batch_op:
batch_op.add_column(
sa.Column("store_api_key", sqlmodel.AutoString(), nullable=True)
)
except Exception as e:
batch_op.add_column(sa.Column("store_api_key", sqlmodel.AutoString(), nullable=True))
except Exception:
pass
# ### end Alembic commands ###

View file

@ -30,9 +30,7 @@ def upgrade() -> None:
try:
if "name" in api_key_columns:
with op.batch_alter_table("apikey", schema=None) as batch_op:
batch_op.alter_column(
"name", existing_type=sa.VARCHAR(), nullable=False
)
batch_op.alter_column("name", existing_type=sa.VARCHAR(), nullable=False)
except Exception as e:
print(e)
@ -40,15 +38,9 @@ def upgrade() -> None:
try:
with op.batch_alter_table("flow", schema=None) as batch_op:
if "updated_at" not in flow_columns:
batch_op.add_column(
sa.Column("updated_at", sa.DateTime(), nullable=True)
)
batch_op.add_column(sa.Column("updated_at", sa.DateTime(), nullable=True))
if "folder" not in flow_columns:
batch_op.add_column(
sa.Column(
"folder", sqlmodel.sql.sqltypes.AutoString(), nullable=True
)
)
batch_op.add_column(sa.Column("folder", sqlmodel.sql.sqltypes.AutoString(), nullable=True))
except Exception as e:
print(e)
@ -68,7 +60,6 @@ def downgrade() -> None:
pass
try:
with op.batch_alter_table("apikey", schema=None) as batch_op:
batch_op.alter_column("name", existing_type=sa.VARCHAR(), nullable=True)
except Exception as e:

View file

@ -32,33 +32,19 @@ def upgrade() -> None:
with op.batch_alter_table("flow", schema=None) as batch_op:
flow_columns = [column["name"] for column in inspector.get_columns("flow")]
if "is_component" not in flow_columns:
batch_op.add_column(
sa.Column("is_component", sa.Boolean(), nullable=True)
)
batch_op.add_column(sa.Column("is_component", sa.Boolean(), nullable=True))
if "updated_at" not in flow_columns:
batch_op.add_column(
sa.Column("updated_at", sa.DateTime(), nullable=True)
)
batch_op.add_column(sa.Column("updated_at", sa.DateTime(), nullable=True))
if "folder" not in flow_columns:
batch_op.add_column(
sa.Column(
"folder", sqlmodel.sql.sqltypes.AutoString(), nullable=True
)
)
batch_op.add_column(sa.Column("folder", sqlmodel.sql.sqltypes.AutoString(), nullable=True))
if "user_id" not in flow_columns:
batch_op.add_column(
sa.Column("user_id", sqlmodel.sql.sqltypes.GUID(), nullable=True)
)
batch_op.add_column(sa.Column("user_id", sqlmodel.sql.sqltypes.GUID(), nullable=True))
indices = inspector.get_indexes("flow")
indices_names = [index["name"] for index in indices]
if "ix_flow_user_id" not in indices_names:
batch_op.create_index(
batch_op.f("ix_flow_user_id"), ["user_id"], unique=False
)
batch_op.create_index(batch_op.f("ix_flow_user_id"), ["user_id"], unique=False)
if "fk_flow_user_id_user" not in indices_names:
batch_op.create_foreign_key(
"fk_flow_user_id_user", "user", ["user_id"], ["id"]
)
batch_op.create_foreign_key("fk_flow_user_id_user", "user", ["user_id"], ["id"])
except Exception:
pass

View file

@ -33,21 +33,13 @@ def upgrade() -> None:
if "updated_at" not in flow_columns:
batch_op.add_column(sa.Column("updated_at", sa.DateTime(), nullable=True))
if "folder" not in flow_columns:
batch_op.add_column(
sa.Column("folder", sqlmodel.sql.sqltypes.AutoString(), nullable=True)
)
batch_op.add_column(sa.Column("folder", sqlmodel.sql.sqltypes.AutoString(), nullable=True))
if "user_id" not in flow_columns:
batch_op.add_column(
sa.Column("user_id", sqlmodel.sql.sqltypes.GUID(), nullable=True)
)
batch_op.add_column(sa.Column("user_id", sqlmodel.sql.sqltypes.GUID(), nullable=True))
if "ix_flow_user_id" not in flow_indexes:
batch_op.create_index(
batch_op.f("ix_flow_user_id"), ["user_id"], unique=False
)
batch_op.create_index(batch_op.f("ix_flow_user_id"), ["user_id"], unique=False)
if "flow_user_id_fkey" not in flow_fks:
batch_op.create_foreign_key(
"flow_user_id_fkey", "user", ["user_id"], ["id"]
)
batch_op.create_foreign_key("flow_user_id_fkey", "user", ["user_id"], ["id"])
def downgrade() -> None:

View file

@ -19,7 +19,7 @@ depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
connection = op.get_bind()
connection = op.get_bind() # noqa
pass
# ### end Alembic commands ###

View file

@ -22,9 +22,7 @@ def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
try:
with op.batch_alter_table("flow", schema=None) as batch_op:
batch_op.alter_column(
"user_id", existing_type=sa.CHAR(length=32), nullable=True
)
batch_op.alter_column("user_id", existing_type=sa.CHAR(length=32), nullable=True)
except Exception as e:
print(e)
pass
@ -36,9 +34,7 @@ def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
try:
with op.batch_alter_table("flow", schema=None) as batch_op:
batch_op.alter_column(
"user_id", existing_type=sa.CHAR(length=32), nullable=False
)
batch_op.alter_column("user_id", existing_type=sa.CHAR(length=32), nullable=False)
except Exception as e:
print(e)
pass

View file

@ -31,9 +31,7 @@ def upgrade() -> None:
try:
if "credential" in tables and "fk_credential_user_id" not in foreign_keys_names:
with op.batch_alter_table("credential", schema=None) as batch_op:
batch_op.create_foreign_key(
"fk_credential_user_id", "user", ["user_id"], ["id"]
)
batch_op.create_foreign_key("fk_credential_user_id", "user", ["user_id"], ["id"])
except Exception as e:
print(e)
pass

View file

@ -8,20 +8,10 @@ from langflow.api.v1.schemas import ApiKeyCreateRequest, ApiKeysResponse
from langflow.services.auth import utils as auth_utils
# Assuming you have these methods in your service layer
from langflow.services.database.models.api_key.crud import (
create_api_key,
delete_api_key,
get_api_keys,
)
from langflow.services.database.models.api_key.model import (
ApiKeyCreate,
UnmaskedApiKeyRead,
)
from langflow.services.database.models.api_key.crud import create_api_key, delete_api_key, get_api_keys
from langflow.services.database.models.api_key.model import ApiKeyCreate, UnmaskedApiKeyRead
from langflow.services.database.models.user.model import User
from langflow.services.deps import (
get_session,
get_settings_service,
)
from langflow.services.deps import get_session, get_settings_service
if TYPE_CHECKING:
pass

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 import __version__
from langflow.version import __version__
return {"version": __version__}

View file

@ -4,6 +4,8 @@ from io import BytesIO
from fastapi import APIRouter, Depends, HTTPException, UploadFile
from fastapi.responses import StreamingResponse
from langflow.api.v1.schemas import UploadFileResponse
from langflow.services.auth.utils import get_current_active_user
from langflow.services.database.models.flow import Flow

View file

@ -12,12 +12,7 @@ from langflow.api.utils import remove_api_keys, validate_is_component
from langflow.api.v1.schemas import FlowListCreate, FlowListRead
from langflow.initial_setup.setup import STARTER_FOLDER_NAME
from langflow.services.auth.utils import get_current_active_user
from langflow.services.database.models.flow import (
Flow,
FlowCreate,
FlowRead,
FlowUpdate,
)
from langflow.services.database.models.flow import Flow, FlowCreate, FlowRead, FlowUpdate
from langflow.services.database.models.user.model import User
from langflow.services.deps import get_session, get_settings_service
from langflow.services.settings.service import SettingsService

View file

@ -1,6 +1,8 @@
from typing import Optional
from fastapi import APIRouter, Depends, HTTPException, Query
from langflow.services.deps import get_monitor_service
from langflow.services.monitor.schema import VertexBuildMapModel
from langflow.services.monitor.service import MonitorService

View file

@ -3,12 +3,7 @@ from collections import defaultdict
from fastapi import APIRouter, HTTPException
from loguru import logger
from langflow.api.v1.base import (
Code,
CodeValidationResponse,
PromptValidationResponse,
ValidatePromptRequest,
)
from langflow.api.v1.base import Code, CodeValidationResponse, PromptValidationResponse, ValidatePromptRequest
from langflow.base.prompts.utils import (
add_new_variables_to_template,
get_old_custom_fields,

View file

@ -1,9 +1,8 @@
from typing import List, Union
from langchain.agents import AgentExecutor, BaseMultiActionAgent, BaseSingleActionAgent
from langflow import CustomComponent
from langflow.field_typing import BaseMemory, Text, Tool
from langflow.interface.custom.custom_component import CustomComponent
class LCAgentComponent(CustomComponent):

View file

@ -1,8 +1,8 @@
import warnings
from typing import Optional, Union
from langflow import CustomComponent
from langflow.field_typing import Text
from langflow.interface.custom.custom_component import CustomComponent
from langflow.memory import add_messages
from langflow.schema import Record

View file

@ -1,7 +1,7 @@
from typing import Optional
from langflow import CustomComponent
from langflow.field_typing import Text
from langflow.interface.custom.custom_component import CustomComponent
class TextComponent(CustomComponent):

View file

@ -4,7 +4,7 @@ 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 import CustomComponent
from langflow.interface.custom.custom_component import CustomComponent
class LCModelComponent(CustomComponent):

View file

@ -1,8 +1,9 @@
from typing import Callable, List, Optional, Union
from langchain.agents import AgentExecutor, AgentType, initialize_agent, types
from langflow import CustomComponent
from langflow.field_typing import BaseChatMemory, BaseLanguageModel, Tool
from langflow.interface.custom.custom_component import CustomComponent
class AgentInitializerComponent(CustomComponent):

View file

@ -1,6 +1,6 @@
from langchain_experimental.agents.agent_toolkits.csv.base import create_csv_agent
from langflow import CustomComponent
from langflow.custom import CustomComponent
from langflow.field_typing import AgentExecutor, BaseLanguageModel

View file

@ -1,9 +1,10 @@
from langflow import CustomComponent
from langchain.agents import AgentExecutor, create_json_agent
from langchain_community.agent_toolkits.json.toolkit import JsonToolkit
from langflow.field_typing import (
BaseLanguageModel,
)
from langchain_community.agent_toolkits.json.toolkit import JsonToolkit
from langflow.interface.custom.custom_component import CustomComponent
class JsonAgentComponent(CustomComponent):

View file

@ -9,8 +9,9 @@ from langchain.prompts.chat import MessagesPlaceholder
from langchain.schema.memory import BaseMemory
from langchain.tools import Tool
from langchain_community.chat_models import ChatOpenAI
from langflow import CustomComponent
from langflow.field_typing.range_spec import RangeSpec
from langflow.interface.custom.custom_component import CustomComponent
class ConversationalAgent(CustomComponent):

View file

@ -1,10 +1,12 @@
from langflow import CustomComponent
from typing import Union, Callable
from typing import Callable, Union
from langchain.agents import AgentExecutor
from langflow.field_typing import BaseLanguageModel
from langchain_community.agent_toolkits.sql.base import create_sql_agent
from langchain.sql_database import SQLDatabase
from langchain_community.agent_toolkits import SQLDatabaseToolkit
from langchain_community.agent_toolkits.sql.base import create_sql_agent
from langflow.field_typing import BaseLanguageModel
from langflow.interface.custom.custom_component import CustomComponent
class SQLAgentComponent(CustomComponent):

View file

@ -1,8 +1,10 @@
from langflow import CustomComponent
from typing import Callable, Union
from langchain.agents import AgentExecutor, create_vectorstore_agent
from langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreToolkit
from typing import Union, Callable
from langflow.field_typing import BaseLanguageModel
from langflow.interface.custom.custom_component import CustomComponent
class VectorStoreAgentComponent(CustomComponent):

View file

@ -1,9 +1,11 @@
from langflow import CustomComponent
from langchain_core.language_models.base import BaseLanguageModel
from langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreRouterToolkit
from langchain.agents import create_vectorstore_router_agent
from typing import Callable
from langchain.agents import create_vectorstore_router_agent
from langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreRouterToolkit
from langchain_core.language_models.base import BaseLanguageModel
from langflow.interface.custom.custom_component import CustomComponent
class VectorStoreRouterAgentComponent(CustomComponent):
display_name = "VectorStoreRouterAgent"

View file

@ -2,8 +2,8 @@ from typing import Optional
from langchain.chains import ConversationChain
from langflow import CustomComponent
from langflow.field_typing import BaseLanguageModel, BaseMemory, Text
from langflow.interface.custom.custom_component import CustomComponent
class ConversationChainComponent(CustomComponent):

View file

@ -2,13 +2,8 @@ from typing import Optional
from langchain.chains import LLMChain
from langflow import CustomComponent
from langflow.field_typing import (
BaseLanguageModel,
BaseMemory,
BasePromptTemplate,
Text,
)
from langflow.field_typing import BaseLanguageModel, BaseMemory, BasePromptTemplate, Text
from langflow.interface.custom.custom_component import CustomComponent
class LLMChainComponent(CustomComponent):

View file

@ -1,7 +1,7 @@
from langchain.chains import LLMCheckerChain
from langflow import CustomComponent
from langflow.field_typing import BaseLanguageModel, Text
from langflow.interface.custom.custom_component import CustomComponent
class LLMCheckerChainComponent(CustomComponent):

View file

@ -2,8 +2,8 @@ from typing import Optional
from langchain.chains import LLMChain, LLMMathChain
from langflow import CustomComponent
from langflow.field_typing import BaseLanguageModel, BaseMemory, Text
from langflow.interface.custom.custom_component import CustomComponent
class LLMMathChainComponent(CustomComponent):

View file

@ -4,8 +4,8 @@ from langchain.chains.combine_documents.base import BaseCombineDocumentsChain
from langchain.chains.retrieval_qa.base import RetrievalQA
from langchain_core.documents import Document
from langflow import CustomComponent
from langflow.field_typing import BaseMemory, BaseRetriever, Text
from langflow.interface.custom.custom_component import CustomComponent
class RetrievalQAComponent(CustomComponent):

View file

@ -3,8 +3,8 @@ from typing import Optional
from langchain.chains import RetrievalQAWithSourcesChain
from langchain_core.documents import Document
from langflow import CustomComponent
from langflow.field_typing import BaseLanguageModel, BaseMemory, BaseRetriever, Text
from langflow.interface.custom.custom_component import CustomComponent
class RetrievalQAWithSourcesChainComponent(CustomComponent):

View file

@ -5,8 +5,8 @@ from langchain_community.utilities.sql_database import SQLDatabase
from langchain_core.prompts import PromptTemplate
from langchain_core.runnables import Runnable
from langflow import CustomComponent
from langflow.field_typing import BaseLanguageModel, Text
from langflow.interface.custom.custom_component import CustomComponent
class SQLGeneratorComponent(CustomComponent):

View file

@ -4,7 +4,7 @@ from typing import List, Optional
import httpx
from langflow import CustomComponent
from langflow.interface.custom.custom_component import CustomComponent
from langflow.schema import Record

View file

@ -1,11 +1,7 @@
from typing import Any, Dict, List, Optional
from langflow import CustomComponent
from langflow.base.data.utils import (
parallel_load_records,
parse_text_file_to_record,
retrieve_file_paths,
)
from langflow.base.data.utils import parallel_load_records, parse_text_file_to_record, retrieve_file_paths
from langflow.interface.custom.custom_component import CustomComponent
from langflow.schema import Record

View file

@ -1,7 +1,7 @@
from typing import Any, Dict, List
from langflow import CustomComponent
from langflow.base.data.utils import TEXT_FILE_TYPES, parse_text_file_to_record
from langflow.interface.custom.custom_component import CustomComponent
from langflow.schema import Record

View file

@ -1,6 +1,6 @@
from typing import List
from langflow import CustomComponent
from langflow.interface.custom.custom_component import CustomComponent
from langflow.schema import Record
from langflow.utils.constants import LOADERS_INFO

View file

@ -2,7 +2,7 @@ from typing import Any, Dict
from langchain_community.document_loaders.web_base import WebBaseLoader
from langflow import CustomComponent
from langflow.interface.custom.custom_component import CustomComponent
from langflow.schema import Record

View file

@ -3,8 +3,7 @@ from typing import Optional
from langchain.embeddings.base import Embeddings
from langchain_community.embeddings import BedrockEmbeddings
from langflow import CustomComponent
from langflow.interface.custom.custom_component import CustomComponent
class AmazonBedrockEmeddingsComponent(CustomComponent):

View file

@ -1,7 +1,7 @@
from langchain.embeddings.base import Embeddings
from langchain_community.embeddings import AzureOpenAIEmbeddings
from langflow import CustomComponent
from langflow.interface.custom.custom_component import CustomComponent
class AzureOpenAIEmbeddingsComponent(CustomComponent):

View file

@ -1,7 +1,8 @@
from typing import Optional
from langchain_community.embeddings.cohere import CohereEmbeddings
from langflow import CustomComponent
from langflow.interface.custom.custom_component import CustomComponent
class CohereEmbeddingsComponent(CustomComponent):

View file

@ -1,7 +1,9 @@
from langflow import CustomComponent
from typing import Optional, Dict
from typing import Dict, Optional
from langchain_community.embeddings.huggingface import HuggingFaceEmbeddings
from langflow.interface.custom.custom_component import CustomComponent
class HuggingFaceEmbeddingsComponent(CustomComponent):
display_name = "HuggingFaceEmbeddings"

View file

@ -1,9 +1,10 @@
from typing import Dict, Optional
from langchain_community.embeddings.huggingface import HuggingFaceInferenceAPIEmbeddings
from langflow import CustomComponent
from pydantic.v1.types import SecretStr
from langflow.interface.custom.custom_component import CustomComponent
class HuggingFaceInferenceAPIEmbeddingsComponent(CustomComponent):
display_name = "HuggingFaceInferenceAPIEmbeddings"

View file

@ -1,9 +1,10 @@
from typing import Optional
from langflow import CustomComponent
from langchain.embeddings.base import Embeddings
from langchain_community.embeddings import OllamaEmbeddings
from langflow.interface.custom.custom_component import CustomComponent
class OllamaEmbeddingsComponent(CustomComponent):
"""

View file

@ -1,10 +1,11 @@
from typing import Any, Callable, Dict, List, Optional, Union
from langchain_openai.embeddings.base import OpenAIEmbeddings
from langflow import CustomComponent
from langflow.field_typing import NestedDict
from pydantic.v1.types import SecretStr
from langflow.field_typing import NestedDict
from langflow.interface.custom.custom_component import CustomComponent
class OpenAIEmbeddingsComponent(CustomComponent):
display_name = "OpenAIEmbeddings"

View file

@ -1,6 +1,8 @@
from langflow import CustomComponent
from typing import List, Optional
from langchain_community.embeddings import VertexAIEmbeddings
from typing import Optional, List
from langflow.interface.custom.custom_component import CustomComponent
class VertexAIEmbeddingsComponent(CustomComponent):

View file

@ -1,4 +1,4 @@
from langflow import CustomComponent
from langflow.interface.custom.custom_component import CustomComponent
from langflow.memory import delete_messages, get_messages

View file

@ -1,4 +1,4 @@
from langflow import CustomComponent
from langflow.interface.custom.custom_component import CustomComponent
from langflow.schema import Record

View file

@ -3,7 +3,7 @@ from typing import Any, List, Optional, Text
from langchain_core.tools import StructuredTool
from loguru import logger
from langflow import CustomComponent
from langflow.custom import CustomComponent
from langflow.field_typing import Tool
from langflow.graph.graph.base import Graph
from langflow.helpers.flow import build_function_and_schema

View file

@ -1,4 +1,4 @@
from langflow import CustomComponent
from langflow.interface.custom.custom_component import CustomComponent
from langflow.schema import Record

View file

@ -1,6 +1,6 @@
from typing import List
from langflow import CustomComponent
from langflow.interface.custom.custom_component import CustomComponent
from langflow.schema import Record

View file

@ -1,4 +1,4 @@
from langflow import CustomComponent
from langflow.interface.custom.custom_component import CustomComponent
from langflow.schema import Record

View file

@ -1,6 +1,6 @@
from typing import Optional
from langflow import CustomComponent
from langflow.interface.custom.custom_component import CustomComponent
from langflow.schema import Record

View file

@ -1,6 +1,6 @@
from typing import Any, List, Optional
from langflow import CustomComponent
from langflow.custom import CustomComponent
from langflow.field_typing import NestedDict, Text
from langflow.graph.schema import ResultData
from langflow.schema import Record, dotdict

View file

@ -1,7 +1,7 @@
from langchain_core.runnables import Runnable
from langflow import CustomComponent
from langflow.field_typing import Text
from langflow.interface.custom.custom_component import CustomComponent
class RunnableExecComponent(CustomComponent):

View file

@ -1,8 +1,8 @@
from langchain_community.tools.sql_database.tool import QuerySQLDataBaseTool
from langchain_experimental.sql.base import SQLDatabase
from langflow import CustomComponent
from langflow.field_typing import Text
from langflow.interface.custom.custom_component import CustomComponent
class SQLExecutorComponent(CustomComponent):

View file

@ -2,7 +2,7 @@ from typing import Any, List, Optional, Text, Tuple
from loguru import logger
from langflow import CustomComponent
from langflow.custom import CustomComponent
from langflow.graph.graph.base import Graph
from langflow.graph.schema import ResultData, RunOutputs
from langflow.schema import Record

View file

@ -1,5 +1,5 @@
from langflow import CustomComponent
from langflow.field_typing import Data
from langflow.interface.custom.custom_component import CustomComponent
class Component(CustomComponent):

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