feat: migrate from loguru to structlog (#9321)
* refactor: Enhance logging configuration with structured logging and buffer support * feat: Add structlog dependency for enhanced logging support * refactor: Update ruff dependency to version 0.12.7 and remove unused pylint references * Refactor logging imports to use langflow.logging.logger - Replaced instances of loguru logger with langflow.logging.logger across multiple files. - Updated logging calls to use asynchronous methods where applicable (e.g., await logger.awarning). - Ensured consistent logging practices throughout the codebase by standardizing the logger import. * refactor: Add missing docstring rule to ruff configuration * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes * fix: update logger calls to use async methods in DatabaseService * fix: update logger calls to use async methods in initialize_database and session_getter * fix: update logger calls to use async methods in LangflowRunnerExperimental * fix: update logger calls to use async methods across various services * Refactor logging to use asynchronous logger methods across multiple components - Updated logging calls in to use async logger methods for error handling and debugging. - Modified to utilize async logging for error messages during file deletion. - Changed logging in , , and other agent-related files to use async methods for error and debug messages. - Refactored logging in various components including , , , and others to ensure consistent use of async logging. - Updated , , and to replace synchronous logging with asynchronous counterparts. - Ensured all logging changes maintain the original message structure while enhancing performance with async capabilities. * [autofix.ci] apply automated fixes * fix: update logger calls to use async methods in various components * feat: add InterceptHandler to route standard logging messages to structlog * refactor: remove async_file parameter from logger configuration * fix: correct log level mapping and enhance log rotation validation * refactor: remove unused logging import and streamline schema imports * Refactor logging in AssemblyAI components and other modules to use exc_info for better error tracing - Updated logging statements in AssemblyAI components (e.g., assemblyai_get_subtitles, assemblyai_lemur, assemblyai_list_transcripts, etc.) to use logger.debug with exc_info=True for improved error context. - Modified logging in various helper and utility functions to enhance error reporting. - Ensured consistent logging practices across the codebase for better maintainability and debugging. * refactor: remove InterceptHandler from logger configuration to avoid recursion * refactor: enhance test coverage for logger module with comprehensive test cases * refactor: add rule to ignore mutable objects without __hash__ method in linter * fix various lint issues * refactor: update function signatures to improve clarity and consistency * refactor: streamline import statements and enhance response handling in voice mode * refactor: simplify lifespan cleanup logic * refactor: remove unused caplog fixture and improve graph test clarity * fix: specify logger type as BoundLogger for clarity * [autofix.ci] apply automated fixes * refactor: remove unused logger and correct return statement in arun_flow_from_json * refactor: update logger usage to support async methods in tests * fix: correct datetime bounds for hypothesis strategies to avoid timezone issues * fix: update warning message for invalid string input type in tests * refactor: simplify message handling tests by removing database session mocks * refactor: remove redundant comment from test_max_size function in test_logger.py * fix: update patch target for DEV setting in remove_exception_in_production test * fix: update patch target for DEV setting in remove_exception_in_production test * fix: update patching of DEV setting in remove_exception_in_production tests to use module import --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
3ecf9640b7
commit
a1629a7553
203 changed files with 2038 additions and 1250 deletions
|
|
@ -113,8 +113,6 @@ dependencies = [
|
|||
"pydantic-ai>=0.0.19",
|
||||
"smolagents>=1.8.0",
|
||||
"apify-client>=1.8.1",
|
||||
"pylint>=3.3.4",
|
||||
"ruff>=0.9.7",
|
||||
"langchain-graph-retriever==0.6.1",
|
||||
"graph-retriever==0.6.1",
|
||||
"ibm-watsonx-ai>=1.3.1",
|
||||
|
|
@ -127,6 +125,7 @@ dependencies = [
|
|||
"docling_core>=2.36.1",
|
||||
"filelock>=3.18.0",
|
||||
"jigsawstack==0.2.7",
|
||||
"structlog>=25.4.0",
|
||||
"aiosqlite==0.21.0",
|
||||
"fastparquet>=2024.11.0",
|
||||
"traceloop-sdk>=0.43.1",
|
||||
|
|
@ -138,7 +137,7 @@ dev = [
|
|||
"types-redis>=4.6.0.5",
|
||||
"ipykernel>=6.29.0",
|
||||
"mypy>=1.11.0",
|
||||
"ruff>=0.9.7,<0.10",
|
||||
"ruff>=0.12.7",
|
||||
"httpx>=0.27.0",
|
||||
"pytest>=8.2.0",
|
||||
"types-requests>=2.32.0",
|
||||
|
|
@ -298,7 +297,9 @@ ignore = [
|
|||
"TD002", # Missing author in TODO
|
||||
"TD003", # Missing issue link in TODO
|
||||
"TRY301", # A bit too harsh (Abstract `raise` to an inner function)
|
||||
|
||||
"PLC0415", # Inline imports
|
||||
"D10", # Missing docstrings
|
||||
"PLW1641", # Object does not implement `__hash__` method (mutable objects shouldn't be hashable)
|
||||
# Rules that are TODOs
|
||||
"ANN",
|
||||
]
|
||||
|
|
@ -308,6 +309,7 @@ external = ["RUF027"]
|
|||
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
"scripts/*" = ["D1", "INP", "T201"]
|
||||
"src/backend/base/langflow/alembic/versions/*" = ["INP001", "D415", "PGH003"]
|
||||
"src/backend/tests/*" = [
|
||||
"D1",
|
||||
"PLR2004",
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ def wait_for_server_ready(host, port, protocol) -> None:
|
|||
except HTTPError:
|
||||
time.sleep(1)
|
||||
except Exception: # noqa: BLE001
|
||||
logger.opt(exception=True).debug("Error while waiting for the server to become ready.")
|
||||
logger.debug("Error while waiting for the server to become ready.", exc_info=True)
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,19 +6,19 @@ Create Date: 2024-04-12 18:11:06.454037
|
|||
|
||||
"""
|
||||
|
||||
from typing import Sequence, Union
|
||||
from collections.abc import Sequence
|
||||
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
from loguru import logger
|
||||
from sqlalchemy.dialects import postgresql
|
||||
from sqlalchemy.engine.reflection import Inspector
|
||||
|
||||
from langflow.logging.logger import logger
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "4e5980a44eaa"
|
||||
down_revision: Union[str, None] = "79e675cb6752"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
down_revision: str | None = "79e675cb6752"
|
||||
branch_labels: str | Sequence[str] | None = None
|
||||
depends_on: str | Sequence[str] | None = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
|
|
@ -37,11 +37,10 @@ def upgrade() -> None:
|
|||
type_=sa.DateTime(timezone=True),
|
||||
existing_nullable=False,
|
||||
)
|
||||
elif created_at_column is None:
|
||||
logger.warning("Column 'created_at' not found in table 'apikey'")
|
||||
else:
|
||||
if created_at_column is None:
|
||||
logger.warning("Column 'created_at' not found in table 'apikey'")
|
||||
else:
|
||||
logger.warning(f"Column 'created_at' has type {created_at_column['type']} in table 'apikey'")
|
||||
logger.warning(f"Column 'created_at' has type {created_at_column['type']} in table 'apikey'")
|
||||
if "variable" in table_names:
|
||||
columns = inspector.get_columns("variable")
|
||||
created_at_column = next((column for column in columns if column["name"] == "created_at"), None)
|
||||
|
|
@ -54,11 +53,10 @@ def upgrade() -> None:
|
|||
type_=sa.DateTime(timezone=True),
|
||||
existing_nullable=True,
|
||||
)
|
||||
elif created_at_column is None:
|
||||
logger.warning("Column 'created_at' not found in table 'variable'")
|
||||
else:
|
||||
if created_at_column is None:
|
||||
logger.warning("Column 'created_at' not found in table 'variable'")
|
||||
else:
|
||||
logger.warning(f"Column 'created_at' has type {created_at_column['type']} in table 'variable'")
|
||||
logger.warning(f"Column 'created_at' has type {created_at_column['type']} in table 'variable'")
|
||||
if updated_at_column is not None and isinstance(updated_at_column["type"], postgresql.TIMESTAMP):
|
||||
batch_op.alter_column(
|
||||
"updated_at",
|
||||
|
|
@ -66,11 +64,10 @@ def upgrade() -> None:
|
|||
type_=sa.DateTime(timezone=True),
|
||||
existing_nullable=True,
|
||||
)
|
||||
elif updated_at_column is None:
|
||||
logger.warning("Column 'updated_at' not found in table 'variable'")
|
||||
else:
|
||||
if updated_at_column is None:
|
||||
logger.warning("Column 'updated_at' not found in table 'variable'")
|
||||
else:
|
||||
logger.warning(f"Column 'updated_at' has type {updated_at_column['type']} in table 'variable'")
|
||||
logger.warning(f"Column 'updated_at' has type {updated_at_column['type']} in table 'variable'")
|
||||
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
|
@ -92,11 +89,10 @@ def downgrade() -> None:
|
|||
type_=postgresql.TIMESTAMP(),
|
||||
existing_nullable=True,
|
||||
)
|
||||
elif updated_at_column is None:
|
||||
logger.warning("Column 'updated_at' not found in table 'variable'")
|
||||
else:
|
||||
if updated_at_column is None:
|
||||
logger.warning("Column 'updated_at' not found in table 'variable'")
|
||||
else:
|
||||
logger.warning(f"Column 'updated_at' has type {updated_at_column['type']} in table 'variable'")
|
||||
logger.warning(f"Column 'updated_at' has type {updated_at_column['type']} in table 'variable'")
|
||||
if created_at_column is not None and isinstance(created_at_column["type"], sa.DateTime):
|
||||
batch_op.alter_column(
|
||||
"created_at",
|
||||
|
|
@ -104,11 +100,10 @@ def downgrade() -> None:
|
|||
type_=postgresql.TIMESTAMP(),
|
||||
existing_nullable=True,
|
||||
)
|
||||
elif created_at_column is None:
|
||||
logger.warning("Column 'created_at' not found in table 'variable'")
|
||||
else:
|
||||
if created_at_column is None:
|
||||
logger.warning("Column 'created_at' not found in table 'variable'")
|
||||
else:
|
||||
logger.warning(f"Column 'created_at' has type {created_at_column['type']} in table 'variable'")
|
||||
logger.warning(f"Column 'created_at' has type {created_at_column['type']} in table 'variable'")
|
||||
|
||||
if "apikey" in table_names:
|
||||
columns = inspector.get_columns("apikey")
|
||||
|
|
@ -121,10 +116,9 @@ def downgrade() -> None:
|
|||
type_=postgresql.TIMESTAMP(),
|
||||
existing_nullable=False,
|
||||
)
|
||||
elif created_at_column is None:
|
||||
logger.warning("Column 'created_at' not found in table 'apikey'")
|
||||
else:
|
||||
if created_at_column is None:
|
||||
logger.warning("Column 'created_at' not found in table 'apikey'")
|
||||
else:
|
||||
logger.warning(f"Column 'created_at' has type {created_at_column['type']} in table 'apikey'")
|
||||
logger.warning(f"Column 'created_at' has type {created_at_column['type']} in table 'apikey'")
|
||||
|
||||
# ### end Alembic commands ###
|
||||
|
|
|
|||
|
|
@ -6,16 +6,16 @@ Create Date: 2024-04-13 10:57:23.061709
|
|||
|
||||
"""
|
||||
|
||||
from typing import Sequence, Union
|
||||
from collections.abc import Sequence
|
||||
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
from loguru import logger
|
||||
from sqlalchemy.engine.reflection import Inspector
|
||||
|
||||
down_revision: Union[str, None] = "4e5980a44eaa"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
from langflow.logging.logger import logger
|
||||
|
||||
down_revision: str | None = "4e5980a44eaa"
|
||||
branch_labels: str | Sequence[str] | None = None
|
||||
depends_on: str | Sequence[str] | None = None
|
||||
|
||||
# Revision identifiers, used by Alembic.
|
||||
revision = "58b28437a398"
|
||||
|
|
|
|||
|
|
@ -6,19 +6,19 @@ Create Date: 2024-04-11 19:23:10.697335
|
|||
|
||||
"""
|
||||
|
||||
from typing import Sequence, Union
|
||||
from collections.abc import Sequence
|
||||
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
from loguru import logger
|
||||
from sqlalchemy.dialects import postgresql
|
||||
from sqlalchemy.engine.reflection import Inspector
|
||||
|
||||
from langflow.logging.logger import logger
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "79e675cb6752"
|
||||
down_revision: Union[str, None] = "e3bc869fa272"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
down_revision: str | None = "e3bc869fa272"
|
||||
branch_labels: str | Sequence[str] | None = None
|
||||
depends_on: str | Sequence[str] | None = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
|
|
@ -37,11 +37,10 @@ def upgrade() -> None:
|
|||
type_=sa.DateTime(timezone=True),
|
||||
existing_nullable=False,
|
||||
)
|
||||
elif created_at_column is None:
|
||||
logger.warning("Column 'created_at' not found in table 'apikey'")
|
||||
else:
|
||||
if created_at_column is None:
|
||||
logger.warning("Column 'created_at' not found in table 'apikey'")
|
||||
else:
|
||||
logger.warning(f"Column 'created_at' has type {created_at_column['type']} in table 'apikey'")
|
||||
logger.warning(f"Column 'created_at' has type {created_at_column['type']} in table 'apikey'")
|
||||
if "variable" in table_names:
|
||||
columns = inspector.get_columns("variable")
|
||||
created_at_column = next((column for column in columns if column["name"] == "created_at"), None)
|
||||
|
|
@ -54,11 +53,10 @@ def upgrade() -> None:
|
|||
type_=sa.DateTime(timezone=True),
|
||||
existing_nullable=True,
|
||||
)
|
||||
elif created_at_column is None:
|
||||
logger.warning("Column 'created_at' not found in table 'variable'")
|
||||
else:
|
||||
if created_at_column is None:
|
||||
logger.warning("Column 'created_at' not found in table 'variable'")
|
||||
else:
|
||||
logger.warning(f"Column 'created_at' has type {created_at_column['type']} in table 'variable'")
|
||||
logger.warning(f"Column 'created_at' has type {created_at_column['type']} in table 'variable'")
|
||||
if updated_at_column is not None and isinstance(updated_at_column["type"], postgresql.TIMESTAMP):
|
||||
batch_op.alter_column(
|
||||
"updated_at",
|
||||
|
|
@ -66,11 +64,10 @@ def upgrade() -> None:
|
|||
type_=sa.DateTime(timezone=True),
|
||||
existing_nullable=True,
|
||||
)
|
||||
elif updated_at_column is None:
|
||||
logger.warning("Column 'updated_at' not found in table 'variable'")
|
||||
else:
|
||||
if updated_at_column is None:
|
||||
logger.warning("Column 'updated_at' not found in table 'variable'")
|
||||
else:
|
||||
logger.warning(f"Column 'updated_at' has type {updated_at_column['type']} in table 'variable'")
|
||||
logger.warning(f"Column 'updated_at' has type {updated_at_column['type']} in table 'variable'")
|
||||
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
|
@ -92,11 +89,10 @@ def downgrade() -> None:
|
|||
type_=postgresql.TIMESTAMP(),
|
||||
existing_nullable=True,
|
||||
)
|
||||
elif updated_at_column is None:
|
||||
logger.warning("Column 'updated_at' not found in table 'variable'")
|
||||
else:
|
||||
if updated_at_column is None:
|
||||
logger.warning("Column 'updated_at' not found in table 'variable'")
|
||||
else:
|
||||
logger.warning(f"Column 'updated_at' has type {updated_at_column['type']} in table 'variable'")
|
||||
logger.warning(f"Column 'updated_at' has type {updated_at_column['type']} in table 'variable'")
|
||||
if created_at_column is not None and isinstance(created_at_column["type"], sa.DateTime):
|
||||
batch_op.alter_column(
|
||||
"created_at",
|
||||
|
|
@ -104,11 +100,10 @@ def downgrade() -> None:
|
|||
type_=postgresql.TIMESTAMP(),
|
||||
existing_nullable=True,
|
||||
)
|
||||
elif created_at_column is None:
|
||||
logger.warning("Column 'created_at' not found in table 'variable'")
|
||||
else:
|
||||
if created_at_column is None:
|
||||
logger.warning("Column 'created_at' not found in table 'variable'")
|
||||
else:
|
||||
logger.warning(f"Column 'created_at' has type {created_at_column['type']} in table 'variable'")
|
||||
logger.warning(f"Column 'created_at' has type {created_at_column['type']} in table 'variable'")
|
||||
|
||||
if "apikey" in table_names:
|
||||
columns = inspector.get_columns("apikey")
|
||||
|
|
@ -121,10 +116,9 @@ def downgrade() -> None:
|
|||
type_=postgresql.TIMESTAMP(),
|
||||
existing_nullable=False,
|
||||
)
|
||||
elif created_at_column is None:
|
||||
logger.warning("Column 'created_at' not found in table 'apikey'")
|
||||
else:
|
||||
if created_at_column is None:
|
||||
logger.warning("Column 'created_at' not found in table 'apikey'")
|
||||
else:
|
||||
logger.warning(f"Column 'created_at' has type {created_at_column['type']} in table 'apikey'")
|
||||
logger.warning(f"Column 'created_at' has type {created_at_column['type']} in table 'apikey'")
|
||||
|
||||
# ### end Alembic commands ###
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
"""Add unique constraints
|
||||
"""Add unique constraints.
|
||||
|
||||
Revision ID: b2fa308044b5
|
||||
Revises: 0b8757876a7c
|
||||
|
|
@ -6,25 +6,25 @@ Create Date: 2024-01-26 13:31:14.797548
|
|||
|
||||
"""
|
||||
|
||||
from typing import Sequence, Union
|
||||
from collections.abc import Sequence
|
||||
|
||||
import sqlalchemy as sa
|
||||
import sqlmodel
|
||||
from alembic import op
|
||||
from loguru import logger # noqa
|
||||
from sqlalchemy.engine.reflection import Inspector
|
||||
|
||||
from langflow.logging.logger import logger
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "b2fa308044b5"
|
||||
down_revision: Union[str, None] = "0b8757876a7c"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
down_revision: str | None = "0b8757876a7c"
|
||||
branch_labels: str | Sequence[str] | None = None
|
||||
depends_on: str | Sequence[str] | None = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
conn = op.get_bind()
|
||||
inspector = sa.inspect(conn) # type: ignore
|
||||
inspector = sa.inspect(conn)
|
||||
tables = inspector.get_table_names()
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
try:
|
||||
|
|
@ -53,14 +53,13 @@ def upgrade() -> None:
|
|||
if "fk_flow_user_id_user" not in constraint_names:
|
||||
batch_op.create_foreign_key("fk_flow_user_id_user", "user", ["user_id"], ["id"])
|
||||
|
||||
except Exception as e:
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.exception(f"Error during upgrade: {e}")
|
||||
pass
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
conn = op.get_bind()
|
||||
inspector = sa.inspect(conn) # type: ignore
|
||||
inspector = sa.inspect(conn)
|
||||
try:
|
||||
# Re-create the dropped table 'flowstyle' if it was previously dropped in upgrade
|
||||
if "flowstyle" not in inspector.get_table_names():
|
||||
|
|
@ -97,6 +96,6 @@ def downgrade() -> None:
|
|||
if "fk_flow_user_id_user" in constraint_names:
|
||||
batch_op.drop_constraint("fk_flow_user_id_user", type_="foreignkey")
|
||||
|
||||
except Exception as e:
|
||||
except Exception as e: # noqa: BLE001
|
||||
# It's generally a good idea to log the exception or handle it in a way other than a bare pass
|
||||
print(f"Error during downgrade: {e}")
|
||||
logger.exception(f"Error during downgrade: {e}")
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import uuid
|
|||
from collections.abc import AsyncIterator
|
||||
|
||||
from fastapi import BackgroundTasks, HTTPException, Response
|
||||
from loguru import logger
|
||||
from sqlmodel import select
|
||||
|
||||
from langflow.api.disconnect import DisconnectHandlerStreamingResponse
|
||||
|
|
@ -20,16 +19,12 @@ from langflow.api.utils import (
|
|||
get_top_level_vertices,
|
||||
parse_exception,
|
||||
)
|
||||
from langflow.api.v1.schemas import (
|
||||
FlowDataRequest,
|
||||
InputValueRequest,
|
||||
ResultDataResponse,
|
||||
VertexBuildResponse,
|
||||
)
|
||||
from langflow.api.v1.schemas import FlowDataRequest, InputValueRequest, ResultDataResponse, VertexBuildResponse
|
||||
from langflow.events.event_manager import EventManager
|
||||
from langflow.exceptions.component import ComponentBuildError
|
||||
from langflow.graph.graph.base import Graph
|
||||
from langflow.graph.utils import log_vertex_build
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.message import ErrorMessage
|
||||
from langflow.schema.schema import OutputValue
|
||||
from langflow.services.database.models.flow.model import Flow
|
||||
|
|
@ -75,7 +70,7 @@ async def start_flow_build(
|
|||
)
|
||||
queue_service.start_job(job_id, task_coro)
|
||||
except Exception as e:
|
||||
logger.exception("Failed to create queue and start task")
|
||||
await logger.aexception("Failed to create queue and start task")
|
||||
raise HTTPException(status_code=500, detail=str(e)) from e
|
||||
return job_id
|
||||
|
||||
|
|
@ -91,7 +86,7 @@ async def get_flow_events_response(
|
|||
main_queue, event_manager, event_task, _ = queue_service.get_queue_data(job_id)
|
||||
if event_delivery in (EventDeliveryType.STREAMING, EventDeliveryType.DIRECT):
|
||||
if event_task is None:
|
||||
logger.error(f"No event task found for job {job_id}")
|
||||
await logger.aerror(f"No event task found for job {job_id}")
|
||||
raise HTTPException(status_code=404, detail="No event task found for job")
|
||||
return await create_flow_response(
|
||||
queue=main_queue,
|
||||
|
|
@ -130,19 +125,19 @@ async def get_flow_events_response(
|
|||
content = "\n".join([event for event in events if event is not None])
|
||||
return Response(content=content, media_type="application/x-ndjson")
|
||||
except asyncio.CancelledError as exc:
|
||||
logger.info(f"Event polling was cancelled for job {job_id}")
|
||||
await logger.ainfo(f"Event polling was cancelled for job {job_id}")
|
||||
raise HTTPException(status_code=499, detail="Event polling was cancelled") from exc
|
||||
except asyncio.TimeoutError:
|
||||
logger.warning(f"Timeout while waiting for events for job {job_id}")
|
||||
await logger.awarning(f"Timeout while waiting for events for job {job_id}")
|
||||
return Response(content="", media_type="application/x-ndjson") # Return empty response instead of error
|
||||
|
||||
except JobQueueNotFoundError as exc:
|
||||
logger.error(f"Job not found: {job_id}. Error: {exc!s}")
|
||||
await logger.aerror(f"Job not found: {job_id}. Error: {exc!s}")
|
||||
raise HTTPException(status_code=404, detail=f"Job not found: {exc!s}") from exc
|
||||
except Exception as exc:
|
||||
if isinstance(exc, HTTPException):
|
||||
raise
|
||||
logger.exception(f"Unexpected error processing flow events for job {job_id}")
|
||||
await logger.aexception(f"Unexpected error processing flow events for job {job_id}")
|
||||
raise HTTPException(status_code=500, detail=f"Unexpected error: {exc!s}") from exc
|
||||
|
||||
|
||||
|
|
@ -161,9 +156,9 @@ async def create_flow_response(
|
|||
break
|
||||
get_time = time.time()
|
||||
yield value.decode("utf-8")
|
||||
logger.debug(f"Event {event_id} consumed in {get_time - put_time:.4f}s")
|
||||
await logger.adebug(f"Event {event_id} consumed in {get_time - put_time:.4f}s")
|
||||
except Exception as exc: # noqa: BLE001
|
||||
logger.exception(f"Error consuming event: {exc}")
|
||||
await logger.aexception(f"Error consuming event: {exc}")
|
||||
break
|
||||
|
||||
def on_disconnect() -> None:
|
||||
|
|
@ -233,7 +228,7 @@ async def generate_flow_events(
|
|||
|
||||
if "stream or streaming set to True" in str(exc):
|
||||
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
||||
logger.exception("Error checking build status")
|
||||
await logger.aexception("Error checking build status")
|
||||
raise HTTPException(status_code=500, detail=str(exc)) from exc
|
||||
return first_layer, vertices_to_run, graph
|
||||
|
||||
|
|
@ -317,7 +312,7 @@ async def generate_flow_events(
|
|||
tb = exc.formatted_traceback
|
||||
else:
|
||||
tb = traceback.format_exc()
|
||||
logger.exception("Error building Component")
|
||||
await logger.aexception("Error building Component")
|
||||
params = format_exception_message(exc)
|
||||
message = {"errorMessage": params, "stackTrace": tb}
|
||||
valid = False
|
||||
|
|
@ -390,7 +385,7 @@ async def generate_flow_events(
|
|||
component_error_message=str(exc),
|
||||
),
|
||||
)
|
||||
logger.exception("Error building Component")
|
||||
await logger.aexception("Error building Component")
|
||||
message = parse_exception(exc)
|
||||
raise HTTPException(status_code=500, detail=message) from exc
|
||||
|
||||
|
|
@ -411,7 +406,7 @@ async def generate_flow_events(
|
|||
try:
|
||||
vertex_build_response: VertexBuildResponse = await _build_vertex(vertex_id, graph, event_manager)
|
||||
except asyncio.CancelledError as exc:
|
||||
logger.error(f"Build cancelled: {exc}")
|
||||
await logger.aerror(f"Build cancelled: {exc}")
|
||||
raise
|
||||
|
||||
# send built event or error event
|
||||
|
|
@ -459,7 +454,7 @@ async def generate_flow_events(
|
|||
background_tasks.add_task(graph.end_all_traces_in_context())
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Error building vertices: {e}")
|
||||
await logger.aerror(f"Error building vertices: {e}")
|
||||
custom_component = graph.get_vertex(vertex_id).custom_component
|
||||
trace_name = getattr(custom_component, "trace_name", None)
|
||||
error_message = ErrorMessage(
|
||||
|
|
@ -499,11 +494,11 @@ async def cancel_flow_build(
|
|||
_, _, event_task, _ = queue_service.get_queue_data(job_id)
|
||||
|
||||
if event_task is None:
|
||||
logger.warning(f"No event task found for job_id {job_id}")
|
||||
await logger.awarning(f"No event task found for job_id {job_id}")
|
||||
return True # Nothing to cancel is still a success
|
||||
|
||||
if event_task.done():
|
||||
logger.info(f"Task for job_id {job_id} is already completed")
|
||||
await logger.ainfo(f"Task for job_id {job_id} is already completed")
|
||||
return True # Nothing to cancel is still a success
|
||||
|
||||
# Store the task reference to check status after cleanup
|
||||
|
|
@ -515,18 +510,18 @@ async def cancel_flow_build(
|
|||
except asyncio.CancelledError:
|
||||
# Check if the task was actually cancelled
|
||||
if task_before_cleanup.cancelled():
|
||||
logger.info(f"Successfully cancelled flow build for job_id {job_id} (CancelledError caught)")
|
||||
await logger.ainfo(f"Successfully cancelled flow build for job_id {job_id} (CancelledError caught)")
|
||||
return True
|
||||
# If the task wasn't cancelled, re-raise the exception
|
||||
logger.error(f"CancelledError caught but task for job_id {job_id} was not cancelled")
|
||||
await logger.aerror(f"CancelledError caught but task for job_id {job_id} was not cancelled")
|
||||
raise
|
||||
|
||||
# If no exception was raised, verify that the task was actually cancelled
|
||||
# The task should be done (cancelled) after cleanup
|
||||
if task_before_cleanup.cancelled():
|
||||
logger.info(f"Successfully cancelled flow build for job_id {job_id}")
|
||||
await logger.ainfo(f"Successfully cancelled flow build for job_id {job_id}")
|
||||
return True
|
||||
|
||||
# If we get here, the task wasn't cancelled properly
|
||||
logger.error(f"Failed to cancel flow build for job_id {job_id}, task is still running")
|
||||
await logger.aerror(f"Failed to cancel flow build for job_id {job_id}, task is still running")
|
||||
return False
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import uuid
|
||||
|
||||
from fastapi import APIRouter, HTTPException, status
|
||||
from loguru import logger
|
||||
from pydantic import BaseModel
|
||||
from sqlmodel import select
|
||||
|
||||
from langflow.api.utils import DbSession
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.services.database.models.flow.model import Flow
|
||||
from langflow.services.deps import get_chat_service
|
||||
|
||||
|
|
@ -49,7 +49,7 @@ async def health_check(
|
|||
(await session.exec(stmt)).first()
|
||||
response.db = "ok"
|
||||
except Exception: # noqa: BLE001
|
||||
logger.exception("Error checking database")
|
||||
await logger.aexception("Error checking database")
|
||||
|
||||
try:
|
||||
chat = get_chat_service()
|
||||
|
|
@ -57,7 +57,7 @@ async def health_check(
|
|||
await chat.get_cache("health_check")
|
||||
response.chat = "ok"
|
||||
except Exception: # noqa: BLE001
|
||||
logger.exception("Error checking chat service")
|
||||
await logger.aexception("Error checking chat service")
|
||||
|
||||
if response.has_error():
|
||||
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=response.model_dump())
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ from typing import TYPE_CHECKING, Annotated, Any
|
|||
|
||||
from fastapi import Depends, HTTPException, Query
|
||||
from fastapi_pagination import Params
|
||||
from loguru import logger
|
||||
from sqlalchemy import delete
|
||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||
|
||||
from langflow.graph.graph.base import Graph
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.services.auth.utils import get_current_active_user, get_current_active_user_mcp
|
||||
from langflow.services.database.models.flow.model import Flow
|
||||
from langflow.services.database.models.message.model import MessageTable
|
||||
|
|
@ -119,7 +119,7 @@ async def check_langflow_version(component: StoreComponentCreate) -> None:
|
|||
if langflow_version is None:
|
||||
raise HTTPException(status_code=500, detail="Unable to verify the latest version of Langflow")
|
||||
if langflow_version != component.last_tested_version:
|
||||
logger.warning(
|
||||
await logger.awarning(
|
||||
f"Your version of Langflow ({component.last_tested_version}) is outdated. "
|
||||
f"Please update to the latest version ({langflow_version}) and try again."
|
||||
)
|
||||
|
|
@ -371,7 +371,7 @@ async def verify_public_flow_and_get_user(flow_id: uuid.UUID, client_id: str | N
|
|||
user = await get_user_by_flow_id_or_endpoint_name(str(flow_id))
|
||||
|
||||
except Exception as exc:
|
||||
logger.exception(f"Error getting user for public flow {flow_id}")
|
||||
await logger.aexception(f"Error getting user for public flow {flow_id}")
|
||||
raise HTTPException(status_code=403, detail="Flow is not accessible") from exc
|
||||
|
||||
if not user:
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@ from uuid import UUID
|
|||
|
||||
from langchain_core.agents import AgentAction, AgentFinish
|
||||
from langchain_core.callbacks.base import AsyncCallbackHandler
|
||||
from loguru import logger
|
||||
from typing_extensions import override
|
||||
|
||||
from langflow.api.v1.schemas import ChatResponse, PromptResponse
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.services.deps import get_chat_service, get_socket_service
|
||||
from langflow.utils.util import remove_ansi_escape_codes
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ class AsyncStreamingLLMCallbackHandleSIO(AsyncCallbackHandler):
|
|||
for resp in resps:
|
||||
await self.socketio_service.emit_token(to=self.sid, data=resp.model_dump())
|
||||
except Exception: # noqa: BLE001
|
||||
logger.exception("Error sending response")
|
||||
await logger.aexception("Error sending response")
|
||||
|
||||
async def on_tool_error(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -6,23 +6,10 @@ import traceback
|
|||
import uuid
|
||||
from typing import TYPE_CHECKING, Annotated
|
||||
|
||||
from fastapi import (
|
||||
APIRouter,
|
||||
BackgroundTasks,
|
||||
Body,
|
||||
Depends,
|
||||
HTTPException,
|
||||
Request,
|
||||
status,
|
||||
)
|
||||
from fastapi import APIRouter, BackgroundTasks, Body, Depends, HTTPException, Request, status
|
||||
from fastapi.responses import StreamingResponse
|
||||
from loguru import logger
|
||||
|
||||
from langflow.api.build import (
|
||||
cancel_flow_build,
|
||||
get_flow_events_response,
|
||||
start_flow_build,
|
||||
)
|
||||
from langflow.api.build import cancel_flow_build, get_flow_events_response, start_flow_build
|
||||
from langflow.api.limited_background_tasks import LimitVertexBuildBackgroundTasks
|
||||
from langflow.api.utils import (
|
||||
CurrentActiveUser,
|
||||
|
|
@ -48,6 +35,7 @@ from langflow.api.v1.schemas import (
|
|||
from langflow.exceptions.component import ComponentBuildError
|
||||
from langflow.graph.graph.base import Graph
|
||||
from langflow.graph.utils import log_vertex_build
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.schema import OutputValue
|
||||
from langflow.services.cache.utils import CacheMiss
|
||||
from langflow.services.chat.service import ChatService
|
||||
|
|
@ -135,7 +123,7 @@ async def retrieve_vertices_order(
|
|||
)
|
||||
if "stream or streaming set to True" in str(exc):
|
||||
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
||||
logger.exception("Error checking build status")
|
||||
await logger.aexception("Error checking build status")
|
||||
raise HTTPException(status_code=500, detail=str(exc)) from exc
|
||||
|
||||
|
||||
|
|
@ -239,17 +227,17 @@ async def cancel_build(
|
|||
return CancelFlowResponse(success=False, message="Failed to cancel flow build")
|
||||
except asyncio.CancelledError:
|
||||
# If CancelledError reaches here, it means the task was not successfully cancelled
|
||||
logger.error(f"Failed to cancel flow build for job_id {job_id} (CancelledError caught)")
|
||||
await logger.aerror(f"Failed to cancel flow build for job_id {job_id} (CancelledError caught)")
|
||||
return CancelFlowResponse(success=False, message="Failed to cancel flow build")
|
||||
except ValueError as exc:
|
||||
# Job not found
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc
|
||||
except JobQueueNotFoundError as exc:
|
||||
logger.error(f"Job not found: {job_id}. Error: {exc!s}")
|
||||
await logger.aerror(f"Job not found: {job_id}. Error: {exc!s}")
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Job not found: {exc!s}") from exc
|
||||
except Exception as exc:
|
||||
# Any other unexpected error
|
||||
logger.exception(f"Error cancelling flow build for job_id {job_id}: {exc}")
|
||||
await logger.aexception(f"Error cancelling flow build for job_id {job_id}: {exc}")
|
||||
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(exc)) from exc
|
||||
|
||||
|
||||
|
|
@ -297,7 +285,7 @@ async def build_vertex(
|
|||
cache = await chat_service.get_cache(flow_id_str)
|
||||
if isinstance(cache, CacheMiss):
|
||||
# If there's no cache
|
||||
logger.warning(f"No cache found for {flow_id_str}. Building graph starting at {vertex_id}")
|
||||
await logger.awarning(f"No cache found for {flow_id_str}. Building graph starting at {vertex_id}")
|
||||
graph = await build_graph_from_db(
|
||||
flow_id=flow_id,
|
||||
session=await anext(get_session()),
|
||||
|
|
@ -331,7 +319,7 @@ async def build_vertex(
|
|||
tb = exc.formatted_traceback
|
||||
else:
|
||||
tb = traceback.format_exc()
|
||||
logger.exception("Error building Component")
|
||||
await logger.aexception("Error building Component")
|
||||
params = format_exception_message(exc)
|
||||
message = {"errorMessage": params, "stackTrace": tb}
|
||||
valid = False
|
||||
|
|
@ -408,7 +396,7 @@ async def build_vertex(
|
|||
component_error_message=str(exc),
|
||||
),
|
||||
)
|
||||
logger.exception("Error building Component")
|
||||
await logger.aexception("Error building Component")
|
||||
message = parse_exception(exc)
|
||||
raise HTTPException(status_code=500, detail=message) from exc
|
||||
|
||||
|
|
@ -421,14 +409,14 @@ async def _stream_vertex(flow_id: str, vertex_id: str, chat_service: ChatService
|
|||
try:
|
||||
cache = await chat_service.get_cache(flow_id)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
logger.exception("Error building Component")
|
||||
await logger.aexception("Error building Component")
|
||||
yield str(StreamData(event="error", data={"error": str(exc)}))
|
||||
return
|
||||
|
||||
if isinstance(cache, CacheMiss):
|
||||
# If there's no cache
|
||||
msg = f"No cache found for {flow_id}."
|
||||
logger.error(msg)
|
||||
await logger.aerror(msg)
|
||||
yield str(StreamData(event="error", data={"error": msg}))
|
||||
return
|
||||
else:
|
||||
|
|
@ -437,13 +425,13 @@ async def _stream_vertex(flow_id: str, vertex_id: str, chat_service: ChatService
|
|||
try:
|
||||
vertex: InterfaceVertex = graph.get_vertex(vertex_id)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
logger.exception("Error building Component")
|
||||
await logger.aexception("Error building Component")
|
||||
yield str(StreamData(event="error", data={"error": str(exc)}))
|
||||
return
|
||||
|
||||
if not hasattr(vertex, "stream"):
|
||||
msg = f"Vertex {vertex_id} does not support streaming"
|
||||
logger.error(msg)
|
||||
await logger.aerror(msg)
|
||||
yield str(StreamData(event="error", data={"error": msg}))
|
||||
return
|
||||
|
||||
|
|
@ -460,7 +448,7 @@ async def _stream_vertex(flow_id: str, vertex_id: str, chat_service: ChatService
|
|||
yield str(stream_data)
|
||||
|
||||
elif not vertex.frozen or not vertex.built:
|
||||
logger.debug(f"Streaming vertex {vertex_id}")
|
||||
await logger.adebug(f"Streaming vertex {vertex_id}")
|
||||
stream_data = StreamData(
|
||||
event="message",
|
||||
data={"message": f"Streaming vertex {vertex_id}"},
|
||||
|
|
@ -474,7 +462,7 @@ async def _stream_vertex(flow_id: str, vertex_id: str, chat_service: ChatService
|
|||
)
|
||||
yield str(stream_data)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
logger.exception("Error building Component")
|
||||
await logger.aexception("Error building Component")
|
||||
exc_message = parse_exception(exc)
|
||||
if exc_message == "The message must be an iterator or an async iterator.":
|
||||
exc_message = "This stream has already been closed."
|
||||
|
|
@ -487,11 +475,11 @@ async def _stream_vertex(flow_id: str, vertex_id: str, chat_service: ChatService
|
|||
yield str(stream_data)
|
||||
else:
|
||||
msg = f"No result found for vertex {vertex_id}"
|
||||
logger.error(msg)
|
||||
await logger.aerror(msg)
|
||||
yield str(StreamData(event="error", data={"error": msg}))
|
||||
return
|
||||
finally:
|
||||
logger.debug("Closing stream")
|
||||
await logger.adebug("Closing stream")
|
||||
if graph:
|
||||
await chat_service.set_cache(flow_id, graph)
|
||||
yield str(StreamData(event="close", data={"message": "Stream closed"}))
|
||||
|
|
@ -625,7 +613,7 @@ async def build_public_tmp(
|
|||
flow_name=flow_name or f"{client_id}_{flow_id}",
|
||||
)
|
||||
except Exception as exc:
|
||||
logger.exception("Error building public flow")
|
||||
await logger.aexception("Error building public flow")
|
||||
if isinstance(exc, HTTPException):
|
||||
raise
|
||||
raise HTTPException(status_code=500, detail=str(exc)) from exc
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import sqlalchemy as sa
|
|||
from fastapi import APIRouter, BackgroundTasks, Body, Depends, HTTPException, Request, UploadFile, status
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from fastapi.responses import StreamingResponse
|
||||
from loguru import logger
|
||||
from sqlmodel import select
|
||||
|
||||
from langflow.api.utils import CurrentActiveUser, DbSession, parse_value
|
||||
|
|
@ -41,6 +40,7 @@ from langflow.graph.schema import RunOutputs
|
|||
from langflow.helpers.flow import get_flow_by_id_or_endpoint_name
|
||||
from langflow.helpers.user import get_user_by_flow_id_or_endpoint_name
|
||||
from langflow.interface.initialize.loading import update_params_with_load_from_db_fields
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.processing.process import process_tweaks, run_graph_internal
|
||||
from langflow.schema.graph import Tweaks
|
||||
from langflow.services.auth.utils import api_key_security, get_current_active_user
|
||||
|
|
@ -184,7 +184,7 @@ async def simple_run_flow_task(
|
|||
)
|
||||
|
||||
except Exception: # noqa: BLE001
|
||||
logger.exception(f"Error running flow {flow.id} task")
|
||||
await logger.aexception(f"Error running flow {flow.id} task")
|
||||
|
||||
|
||||
async def consume_and_yield(queue: asyncio.Queue, client_consumed_queue: asyncio.Queue) -> AsyncGenerator:
|
||||
|
|
@ -215,7 +215,7 @@ async def consume_and_yield(queue: asyncio.Queue, client_consumed_queue: asyncio
|
|||
yield value
|
||||
get_time_yield = time.time()
|
||||
client_consumed_queue.put_nowait(event_id)
|
||||
logger.debug(
|
||||
await logger.adebug(
|
||||
f"consumed event {event_id} "
|
||||
f"(time in queue, {get_time - put_time:.4f}, "
|
||||
f"client {get_time_yield - get_time:.4f})"
|
||||
|
|
@ -264,7 +264,7 @@ async def run_flow_generator(
|
|||
event_manager.on_end(data={"result": result.model_dump()})
|
||||
await client_consumed_queue.get()
|
||||
except (ValueError, InvalidChatInputError, SerializationError) as e:
|
||||
logger.error(f"Error running flow: {e}")
|
||||
await logger.aerror(f"Error running flow: {e}")
|
||||
event_manager.on_error(data={"error": str(e)})
|
||||
finally:
|
||||
await event_manager.queue.put((None, None, time.time))
|
||||
|
|
@ -331,7 +331,7 @@ async def simplified_run_flow(
|
|||
)
|
||||
|
||||
async def on_disconnect() -> None:
|
||||
logger.debug("Client disconnected, closing tasks")
|
||||
await logger.adebug("Client disconnected, closing tasks")
|
||||
main_task.cancel()
|
||||
|
||||
return StreamingResponse(
|
||||
|
|
@ -414,7 +414,7 @@ async def webhook_run_flow(
|
|||
"""
|
||||
telemetry_service = get_telemetry_service()
|
||||
start_time = time.perf_counter()
|
||||
logger.debug("Received webhook request")
|
||||
await logger.adebug("Received webhook request")
|
||||
error_msg = ""
|
||||
try:
|
||||
try:
|
||||
|
|
@ -442,7 +442,7 @@ async def webhook_run_flow(
|
|||
session_id=None,
|
||||
)
|
||||
|
||||
logger.debug("Starting background task")
|
||||
await logger.adebug("Starting background task")
|
||||
background_tasks.add_task(
|
||||
simple_run_flow_task,
|
||||
flow=flow,
|
||||
|
|
@ -553,7 +553,7 @@ async def experimental_run_flow(
|
|||
except sa.exc.StatementError as exc:
|
||||
# StatementError('(builtins.ValueError) badly formed hexadecimal UUID string')
|
||||
if "badly formed hexadecimal UUID string" in str(exc):
|
||||
logger.error(f"Flow ID {flow_id_str} is not a valid UUID")
|
||||
await logger.aerror(f"Flow ID {flow_id_str} is not a valid UUID")
|
||||
# This means the Flow ID is not a valid UUID which means it can't find the flow
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc
|
||||
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(exc)) from exc
|
||||
|
|
@ -600,7 +600,7 @@ async def experimental_run_flow(
|
|||
async def process(_flow_id) -> None:
|
||||
"""Endpoint to process an input with a given flow_id."""
|
||||
# Raise a depreciation warning
|
||||
logger.warning(
|
||||
await logger.awarning(
|
||||
"The /process endpoint is deprecated and will be removed in a future version. Please use /run instead."
|
||||
)
|
||||
raise HTTPException(
|
||||
|
|
@ -643,7 +643,7 @@ async def create_upload_file(
|
|||
file_path=file_path,
|
||||
)
|
||||
except Exception as exc:
|
||||
logger.exception("Error saving file")
|
||||
await logger.aexception("Error saving file")
|
||||
raise HTTPException(status_code=500, detail=str(exc)) from exc
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ async def _save_flow_to_fs(flow: Flow) -> None:
|
|||
try:
|
||||
await f.write(flow.model_dump_json())
|
||||
except OSError:
|
||||
logger.exception("Failed to write flow %s to path %s", flow.name, flow.fs_path)
|
||||
await logger.aexception("Failed to write flow %s to path %s", flow.name, flow.fs_path)
|
||||
|
||||
|
||||
async def _new_flow(
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@ from pathlib import Path
|
|||
import pandas as pd
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from langchain_chroma import Chroma
|
||||
from loguru import logger
|
||||
from pydantic import BaseModel
|
||||
|
||||
from langflow.api.utils import CurrentActiveUser
|
||||
from langflow.logging import logger
|
||||
from langflow.services.deps import get_settings_service
|
||||
|
||||
router = APIRouter(tags=["Knowledge Bases"], prefix="/knowledge_bases")
|
||||
|
|
@ -330,7 +330,7 @@ async def list_knowledge_bases(current_user: CurrentActiveUser) -> list[Knowledg
|
|||
|
||||
except OSError as _:
|
||||
# Log the exception and skip directories that can't be read
|
||||
logger.exception("Error reading knowledge base directory '%s'", kb_dir)
|
||||
await logger.aexception("Error reading knowledge base directory '%s'", kb_dir)
|
||||
continue
|
||||
|
||||
# Sort by name alphabetically
|
||||
|
|
@ -422,7 +422,7 @@ async def delete_knowledge_bases_bulk(request: BulkDeleteRequest, current_user:
|
|||
shutil.rmtree(kb_path)
|
||||
deleted_count += 1
|
||||
except (OSError, PermissionError) as e:
|
||||
logger.exception("Error deleting knowledge base '%s': %s", kb_name, e)
|
||||
await logger.aexception("Error deleting knowledge base '%s': %s", kb_name, e)
|
||||
# Continue with other deletions even if one fails
|
||||
|
||||
if not_found_kbs and deleted_count == 0:
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import pydantic
|
|||
from anyio import BrokenResourceError
|
||||
from fastapi import APIRouter, HTTPException, Request, Response
|
||||
from fastapi.responses import HTMLResponse, StreamingResponse
|
||||
from loguru import logger
|
||||
from mcp import types
|
||||
from mcp.server import NotificationOptions, Server
|
||||
from mcp.server.sse import SseServerTransport
|
||||
|
|
@ -18,6 +17,7 @@ from langflow.api.v1.mcp_utils import (
|
|||
handle_mcp_errors,
|
||||
handle_read_resource,
|
||||
)
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.services.deps import get_settings_service
|
||||
|
||||
router = APIRouter(prefix="/mcp", tags=["mcp"])
|
||||
|
|
@ -83,22 +83,22 @@ async def im_alive():
|
|||
@router.get("/sse", response_class=StreamingResponse)
|
||||
async def handle_sse(request: Request, current_user: CurrentActiveMCPUser):
|
||||
msg = f"Starting SSE connection, server name: {server.name}"
|
||||
logger.info(msg)
|
||||
await logger.ainfo(msg)
|
||||
token = current_user_ctx.set(current_user)
|
||||
try:
|
||||
async with sse.connect_sse(request.scope, request.receive, request._send) as streams:
|
||||
try:
|
||||
msg = "Starting SSE connection"
|
||||
logger.debug(msg)
|
||||
await logger.adebug(msg)
|
||||
msg = f"Stream types: read={type(streams[0])}, write={type(streams[1])}"
|
||||
logger.debug(msg)
|
||||
await logger.adebug(msg)
|
||||
|
||||
notification_options = NotificationOptions(
|
||||
prompts_changed=True, resources_changed=True, tools_changed=True
|
||||
)
|
||||
init_options = server.create_initialization_options(notification_options)
|
||||
msg = f"Initialization options: {init_options}"
|
||||
logger.debug(msg)
|
||||
await logger.adebug(msg)
|
||||
|
||||
try:
|
||||
await server.run(streams[0], streams[1], init_options)
|
||||
|
|
@ -106,20 +106,20 @@ async def handle_sse(request: Request, current_user: CurrentActiveMCPUser):
|
|||
validation_error = find_validation_error(exc)
|
||||
if validation_error:
|
||||
msg = "Validation error in MCP:" + str(validation_error)
|
||||
logger.debug(msg)
|
||||
await logger.adebug(msg)
|
||||
else:
|
||||
msg = f"Error in MCP: {exc!s}"
|
||||
logger.debug(msg)
|
||||
await logger.adebug(msg)
|
||||
return
|
||||
except BrokenResourceError:
|
||||
# Handle gracefully when client disconnects
|
||||
logger.info("Client disconnected from SSE connection")
|
||||
await logger.ainfo("Client disconnected from SSE connection")
|
||||
except asyncio.CancelledError:
|
||||
logger.info("SSE connection was cancelled")
|
||||
await logger.ainfo("SSE connection was cancelled")
|
||||
raise
|
||||
except Exception as e:
|
||||
msg = f"Error in MCP: {e!s}"
|
||||
logger.exception(msg)
|
||||
await logger.aexception(msg)
|
||||
raise
|
||||
finally:
|
||||
current_user_ctx.reset(token)
|
||||
|
|
@ -130,8 +130,8 @@ async def handle_messages(request: Request):
|
|||
try:
|
||||
await sse.handle_post_message(request.scope, request.receive, request._send)
|
||||
except (BrokenResourceError, BrokenPipeError) as e:
|
||||
logger.info("MCP Server disconnected")
|
||||
await logger.ainfo("MCP Server disconnected")
|
||||
raise HTTPException(status_code=404, detail=f"MCP Server disconnected, error: {e}") from e
|
||||
except Exception as e:
|
||||
logger.error(f"Internal server error: {e}")
|
||||
await logger.aerror(f"Internal server error: {e}")
|
||||
raise HTTPException(status_code=500, detail=f"Internal server error: {e}") from e
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import asyncio
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import platform
|
||||
from asyncio.subprocess import create_subprocess_exec
|
||||
|
|
@ -29,19 +28,13 @@ from langflow.api.v1.mcp_utils import (
|
|||
handle_mcp_errors,
|
||||
handle_read_resource,
|
||||
)
|
||||
from langflow.api.v1.schemas import (
|
||||
MCPInstallRequest,
|
||||
MCPProjectResponse,
|
||||
MCPProjectUpdateRequest,
|
||||
MCPSettings,
|
||||
)
|
||||
from langflow.api.v1.schemas import MCPInstallRequest, MCPProjectResponse, MCPProjectUpdateRequest, MCPSettings
|
||||
from langflow.base.mcp.constants import MAX_MCP_SERVER_NAME_LENGTH
|
||||
from langflow.base.mcp.util import sanitize_mcp_name
|
||||
from langflow.logging import logger
|
||||
from langflow.services.database.models import Flow, Folder
|
||||
from langflow.services.deps import get_settings_service, session_scope
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
router = APIRouter(prefix="/mcp/project", tags=["mcp_projects"])
|
||||
|
||||
# Create project-specific context variable
|
||||
|
|
@ -116,7 +109,7 @@ async def list_project_tools(
|
|||
tools.append(tool)
|
||||
except Exception as e: # noqa: BLE001
|
||||
msg = f"Error in listing project tools: {e!s} from flow: {name}"
|
||||
logger.warning(msg)
|
||||
await logger.awarning(msg)
|
||||
continue
|
||||
|
||||
# Get project-level auth settings
|
||||
|
|
@ -128,14 +121,14 @@ async def list_project_tools(
|
|||
|
||||
except Exception as e:
|
||||
msg = f"Error listing project tools: {e!s}"
|
||||
logger.exception(msg)
|
||||
await logger.aexception(msg)
|
||||
raise HTTPException(status_code=500, detail=str(e)) from e
|
||||
|
||||
return MCPProjectResponse(tools=tools, auth_settings=auth_settings)
|
||||
|
||||
|
||||
@router.head("/{project_id}/sse", response_class=HTMLResponse, include_in_schema=False)
|
||||
async def im_alive():
|
||||
async def im_alive(project_id: str): # noqa: ARG001
|
||||
return Response()
|
||||
|
||||
|
||||
|
|
@ -158,7 +151,7 @@ async def handle_project_sse(
|
|||
# Get project-specific SSE transport and MCP server
|
||||
sse = get_project_sse(project_id)
|
||||
project_server = get_project_mcp_server(project_id)
|
||||
logger.debug("Project MCP server name: %s", project_server.server.name)
|
||||
await logger.adebug("Project MCP server name: %s", project_server.server.name)
|
||||
|
||||
# Set context variables
|
||||
user_token = current_user_ctx.set(current_user)
|
||||
|
|
@ -167,7 +160,7 @@ async def handle_project_sse(
|
|||
try:
|
||||
async with sse.connect_sse(request.scope, request.receive, request._send) as streams:
|
||||
try:
|
||||
logger.debug("Starting SSE connection for project %s", project_id)
|
||||
await logger.adebug("Starting SSE connection for project %s", project_id)
|
||||
|
||||
notification_options = NotificationOptions(
|
||||
prompts_changed=True, resources_changed=True, tools_changed=True
|
||||
|
|
@ -176,15 +169,15 @@ async def handle_project_sse(
|
|||
|
||||
try:
|
||||
await project_server.server.run(streams[0], streams[1], init_options)
|
||||
except Exception:
|
||||
logger.exception("Error in project MCP")
|
||||
except Exception: # noqa: BLE001
|
||||
await logger.aexception("Error in project MCP")
|
||||
except BrokenResourceError:
|
||||
logger.info("Client disconnected from project SSE connection")
|
||||
await logger.ainfo("Client disconnected from project SSE connection")
|
||||
except asyncio.CancelledError:
|
||||
logger.info("Project SSE connection was cancelled")
|
||||
await logger.ainfo("Project SSE connection was cancelled")
|
||||
raise
|
||||
except Exception:
|
||||
logger.exception("Error in project MCP")
|
||||
await logger.aexception("Error in project MCP")
|
||||
raise
|
||||
finally:
|
||||
current_user_ctx.reset(user_token)
|
||||
|
|
@ -213,7 +206,7 @@ async def handle_project_messages(project_id: UUID, request: Request, current_us
|
|||
sse = get_project_sse(project_id)
|
||||
await sse.handle_post_message(request.scope, request.receive, request._send)
|
||||
except BrokenResourceError as e:
|
||||
logger.info("Project MCP Server disconnected for project %s", project_id)
|
||||
await logger.ainfo("Project MCP Server disconnected for project %s", project_id)
|
||||
raise HTTPException(status_code=404, detail=f"Project MCP Server disconnected, error: {e}") from e
|
||||
finally:
|
||||
current_user_ctx.reset(user_token)
|
||||
|
|
@ -279,7 +272,7 @@ async def update_project_mcp_settings(
|
|||
|
||||
except Exception as e:
|
||||
msg = f"Error updating project MCP settings: {e!s}"
|
||||
logger.exception(msg)
|
||||
await logger.aexception(msg)
|
||||
raise HTTPException(status_code=500, detail=str(e)) from e
|
||||
|
||||
|
||||
|
|
@ -372,7 +365,7 @@ async def install_mcp_config(
|
|||
is_wsl = os_type == "Linux" and "microsoft" in platform.uname().release.lower()
|
||||
|
||||
if is_wsl:
|
||||
logger.debug("WSL detected, using Windows-specific configuration")
|
||||
await logger.adebug("WSL detected, using Windows-specific configuration")
|
||||
|
||||
# If we're in WSL and the host is localhost, we might need to adjust the URL
|
||||
# so Windows applications can reach the WSL service
|
||||
|
|
@ -391,18 +384,18 @@ async def install_mcp_config(
|
|||
|
||||
if proc.returncode == 0 and stdout.strip():
|
||||
wsl_ip = stdout.decode().strip().split()[0] # Get first IP address
|
||||
logger.debug("Using WSL IP for external access: %s", wsl_ip)
|
||||
await logger.adebug("Using WSL IP for external access: %s", wsl_ip)
|
||||
# Replace the localhost with the WSL IP in the URL
|
||||
sse_url = sse_url.replace(f"http://{host}:{port}", f"http://{wsl_ip}:{port}")
|
||||
except OSError as e:
|
||||
logger.warning("Failed to get WSL IP address: %s. Using default URL.", str(e))
|
||||
await logger.awarning("Failed to get WSL IP address: %s. Using default URL.", str(e))
|
||||
else:
|
||||
args = ["mcp-proxy", sse_url]
|
||||
|
||||
if os_type == "Windows":
|
||||
command = "cmd"
|
||||
args = ["/c", "uvx", *args]
|
||||
logger.debug("Windows detected, using cmd command")
|
||||
await logger.adebug("Windows detected, using cmd command")
|
||||
|
||||
name = project.name
|
||||
|
||||
|
|
@ -417,7 +410,7 @@ async def install_mcp_config(
|
|||
}
|
||||
|
||||
server_name = f"lf-{sanitize_mcp_name(name)[: (MAX_MCP_SERVER_NAME_LENGTH - 4)]}"
|
||||
logger.debug("Installing MCP config for project: %s (server name: %s)", project.name, server_name)
|
||||
await logger.adebug("Installing MCP config for project: %s (server name: %s)", project.name, server_name)
|
||||
|
||||
# Determine the config file path based on the client and OS
|
||||
if body.client.lower() == "cursor":
|
||||
|
|
@ -469,7 +462,7 @@ async def install_mcp_config(
|
|||
status_code=400, detail="Windows C: drive not mounted at /mnt/c in WSL"
|
||||
)
|
||||
except (OSError, CalledProcessError) as e:
|
||||
logger.warning("Failed to determine Windows user path in WSL: %s", str(e))
|
||||
await logger.awarning("Failed to determine Windows user path in WSL: %s", str(e))
|
||||
raise HTTPException(
|
||||
status_code=400, detail=f"Could not determine Windows Claude config path in WSL: {e!s}"
|
||||
) from e
|
||||
|
|
@ -505,11 +498,11 @@ async def install_mcp_config(
|
|||
|
||||
except Exception as e:
|
||||
msg = f"Error installing MCP configuration: {e!s}"
|
||||
logger.exception(msg)
|
||||
await logger.aexception(msg)
|
||||
raise HTTPException(status_code=500, detail=str(e)) from e
|
||||
else:
|
||||
message = f"Successfully installed MCP configuration for {body.client}"
|
||||
logger.info(message)
|
||||
await logger.ainfo(message)
|
||||
return {"message": message}
|
||||
|
||||
|
||||
|
|
@ -533,7 +526,7 @@ async def check_installed_mcp_servers(
|
|||
name = project.name
|
||||
project_server_name = f"lf-{sanitize_mcp_name(name)[: (MAX_MCP_SERVER_NAME_LENGTH - 4)]}"
|
||||
|
||||
logger.debug(
|
||||
await logger.adebug(
|
||||
"Checking for installed MCP servers for project: %s (server name: %s)", project.name, project_server_name
|
||||
)
|
||||
|
||||
|
|
@ -542,26 +535,28 @@ async def check_installed_mcp_servers(
|
|||
|
||||
# Check Cursor configuration
|
||||
cursor_config_path = Path.home() / ".cursor" / "mcp.json"
|
||||
logger.debug("Checking Cursor config at: %s (exists: %s)", cursor_config_path, cursor_config_path.exists())
|
||||
await logger.adebug(
|
||||
"Checking Cursor config at: %s (exists: %s)", cursor_config_path, cursor_config_path.exists()
|
||||
)
|
||||
if cursor_config_path.exists():
|
||||
try:
|
||||
with cursor_config_path.open("r") as f:
|
||||
cursor_config = json.load(f)
|
||||
if "mcpServers" in cursor_config and project_server_name in cursor_config["mcpServers"]:
|
||||
logger.debug("Found Cursor config for project server: %s", project_server_name)
|
||||
await logger.adebug("Found Cursor config for project server: %s", project_server_name)
|
||||
results.append("cursor")
|
||||
else:
|
||||
logger.debug(
|
||||
await logger.adebug(
|
||||
"Cursor config exists but no entry for server: %s (available servers: %s)",
|
||||
project_server_name,
|
||||
list(cursor_config.get("mcpServers", {}).keys()),
|
||||
)
|
||||
except json.JSONDecodeError:
|
||||
logger.warning("Failed to parse Cursor config JSON at: %s", cursor_config_path)
|
||||
await logger.awarning("Failed to parse Cursor config JSON at: %s", cursor_config_path)
|
||||
|
||||
# Check Windsurf configuration
|
||||
windsurf_config_path = Path.home() / ".codeium" / "windsurf" / "mcp_config.json"
|
||||
logger.debug(
|
||||
await logger.adebug(
|
||||
"Checking Windsurf config at: %s (exists: %s)", windsurf_config_path, windsurf_config_path.exists()
|
||||
)
|
||||
if windsurf_config_path.exists():
|
||||
|
|
@ -569,16 +564,16 @@ async def check_installed_mcp_servers(
|
|||
with windsurf_config_path.open("r") as f:
|
||||
windsurf_config = json.load(f)
|
||||
if "mcpServers" in windsurf_config and project_server_name in windsurf_config["mcpServers"]:
|
||||
logger.debug("Found Windsurf config for project server: %s", project_server_name)
|
||||
await logger.adebug("Found Windsurf config for project server: %s", project_server_name)
|
||||
results.append("windsurf")
|
||||
else:
|
||||
logger.debug(
|
||||
await logger.adebug(
|
||||
"Windsurf config exists but no entry for server: %s (available servers: %s)",
|
||||
project_server_name,
|
||||
list(windsurf_config.get("mcpServers", {}).keys()),
|
||||
)
|
||||
except json.JSONDecodeError:
|
||||
logger.warning("Failed to parse Windsurf config JSON at: %s", windsurf_config_path)
|
||||
await logger.awarning("Failed to parse Windsurf config JSON at: %s", windsurf_config_path)
|
||||
|
||||
# Check Claude configuration
|
||||
claude_config_path = None
|
||||
|
|
@ -623,7 +618,7 @@ async def check_installed_mcp_servers(
|
|||
user_dirs[0] / "AppData" / "Roaming" / "Claude" / "claude_desktop_config.json"
|
||||
)
|
||||
except (OSError, CalledProcessError) as e:
|
||||
logger.warning(
|
||||
await logger.awarning(
|
||||
"Failed to determine Windows user path in WSL for checking Claude config: %s", str(e)
|
||||
)
|
||||
# Don't set claude_config_path, so it will be skipped
|
||||
|
|
@ -632,27 +627,27 @@ async def check_installed_mcp_servers(
|
|||
claude_config_path = Path(os.environ["APPDATA"]) / "Claude" / "claude_desktop_config.json"
|
||||
|
||||
if claude_config_path and claude_config_path.exists():
|
||||
logger.debug("Checking Claude config at: %s", claude_config_path)
|
||||
await logger.adebug("Checking Claude config at: %s", claude_config_path)
|
||||
try:
|
||||
with claude_config_path.open("r") as f:
|
||||
claude_config = json.load(f)
|
||||
if "mcpServers" in claude_config and project_server_name in claude_config["mcpServers"]:
|
||||
logger.debug("Found Claude config for project server: %s", project_server_name)
|
||||
await logger.adebug("Found Claude config for project server: %s", project_server_name)
|
||||
results.append("claude")
|
||||
else:
|
||||
logger.debug(
|
||||
await logger.adebug(
|
||||
"Claude config exists but no entry for server: %s (available servers: %s)",
|
||||
project_server_name,
|
||||
list(claude_config.get("mcpServers", {}).keys()),
|
||||
)
|
||||
except json.JSONDecodeError:
|
||||
logger.warning("Failed to parse Claude config JSON at: %s", claude_config_path)
|
||||
await logger.awarning("Failed to parse Claude config JSON at: %s", claude_config_path)
|
||||
else:
|
||||
logger.debug("Claude config path not found or doesn't exist: %s", claude_config_path)
|
||||
await logger.adebug("Claude config path not found or doesn't exist: %s", claude_config_path)
|
||||
|
||||
except Exception as e:
|
||||
msg = f"Error checking MCP configuration: {e!s}"
|
||||
logger.exception(msg)
|
||||
await logger.aexception(msg)
|
||||
raise HTTPException(status_code=500, detail=str(e)) from e
|
||||
return results
|
||||
|
||||
|
|
@ -719,11 +714,11 @@ async def init_mcp_servers():
|
|||
try:
|
||||
get_project_sse(project.id)
|
||||
get_project_mcp_server(project.id)
|
||||
except Exception as e:
|
||||
except Exception as e: # noqa: BLE001
|
||||
msg = f"Failed to initialize MCP server for project {project.id}: {e}"
|
||||
logger.exception(msg)
|
||||
await logger.aexception(msg)
|
||||
# Continue to next project even if this one fails
|
||||
|
||||
except Exception as e:
|
||||
except Exception as e: # noqa: BLE001
|
||||
msg = f"Failed to initialize MCP servers: {e}"
|
||||
logger.exception(msg)
|
||||
await logger.aexception(msg)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ from typing import Any, ParamSpec, TypeVar
|
|||
from urllib.parse import quote, unquote, urlparse
|
||||
from uuid import uuid4
|
||||
|
||||
from loguru import logger
|
||||
from mcp import types
|
||||
from sqlmodel import select
|
||||
|
||||
|
|
@ -21,6 +20,7 @@ from langflow.api.v1.schemas import SimplifiedAPIRequest
|
|||
from langflow.base.mcp.constants import MAX_MCP_TOOL_NAME_LENGTH
|
||||
from langflow.base.mcp.util import get_flow_snake_case, get_unique_name, sanitize_mcp_name
|
||||
from langflow.helpers.flow import json_schema_from_flow
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.message import Message
|
||||
from langflow.services.database.models import Flow
|
||||
from langflow.services.database.models.user.model import User
|
||||
|
|
@ -43,7 +43,7 @@ def handle_mcp_errors(func: Callable[P, Awaitable[T]]) -> Callable[P, Awaitable[
|
|||
return await func(*args, **kwargs)
|
||||
except Exception as e:
|
||||
msg = f"Error in {func.__name__}: {e!s}"
|
||||
logger.exception(msg)
|
||||
await logger.aexception(msg)
|
||||
raise
|
||||
|
||||
return wrapper
|
||||
|
|
@ -108,11 +108,11 @@ async def handle_list_resources(project_id=None):
|
|||
resources.append(resource)
|
||||
except FileNotFoundError as e:
|
||||
msg = f"Error listing files for flow {flow.id}: {e}"
|
||||
logger.debug(msg)
|
||||
await logger.adebug(msg)
|
||||
continue
|
||||
except Exception as e:
|
||||
msg = f"Error in listing resources: {e!s}"
|
||||
logger.exception(msg)
|
||||
await logger.aexception(msg)
|
||||
raise
|
||||
return resources
|
||||
|
||||
|
|
@ -150,7 +150,7 @@ async def handle_read_resource(uri: str) -> bytes:
|
|||
return base64.b64encode(content)
|
||||
except Exception as e:
|
||||
msg = f"Error reading resource {uri}: {e!s}"
|
||||
logger.exception(msg)
|
||||
await logger.aexception(msg)
|
||||
raise
|
||||
|
||||
|
||||
|
|
@ -271,7 +271,7 @@ async def handle_call_tool(
|
|||
return await with_db_session(execute_tool)
|
||||
except Exception as e:
|
||||
msg = f"Error executing tool {name}: {e!s}"
|
||||
logger.exception(msg)
|
||||
await logger.aexception(msg)
|
||||
raise
|
||||
|
||||
|
||||
|
|
@ -339,10 +339,10 @@ async def handle_list_tools(project_id=None, *, mcp_enabled_only=False):
|
|||
existing_names.add(name)
|
||||
except Exception as e: # noqa: BLE001
|
||||
msg = f"Error in listing tools: {e!s} from flow: {base_name}"
|
||||
logger.warning(msg)
|
||||
await logger.awarning(msg)
|
||||
continue
|
||||
except Exception as e:
|
||||
msg = f"Error in listing tools: {e!s}"
|
||||
logger.exception(msg)
|
||||
await logger.aexception(msg)
|
||||
raise
|
||||
return tools
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ from typing import Annotated
|
|||
from uuid import UUID
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from loguru import logger
|
||||
|
||||
from langflow.api.utils import CurrentActiveUser, check_langflow_version
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.services.auth import utils as auth_utils
|
||||
from langflow.services.deps import get_settings_service, get_store_service
|
||||
from langflow.services.store.exceptions import CustomError
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
from fastapi import APIRouter, HTTPException
|
||||
from loguru import logger
|
||||
|
||||
from langflow.api.utils import CurrentActiveUser
|
||||
from langflow.api.v1.base import Code, CodeValidationResponse, PromptValidationResponse, ValidatePromptRequest
|
||||
from langflow.base.prompts.api_utils import process_prompt_template
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.utils.validate import validate_code
|
||||
|
||||
# build router
|
||||
|
|
@ -19,7 +19,7 @@ async def post_validate_code(code: Code, _current_user: CurrentActiveUser) -> Co
|
|||
function=errors.get("function", {}),
|
||||
)
|
||||
except Exception as e:
|
||||
logger.opt(exception=True).debug("Error validating code")
|
||||
logger.debug("Error validating code", exc_info=True)
|
||||
raise HTTPException(status_code=500, detail=str(e)) from e
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -33,11 +33,7 @@ from langflow.services.database.models.flow.model import Flow
|
|||
from langflow.services.database.models.message.model import MessageTable
|
||||
from langflow.services.database.models.user.model import User
|
||||
from langflow.services.deps import get_variable_service, session_scope
|
||||
from langflow.utils.voice_utils import (
|
||||
BYTES_PER_24K_FRAME,
|
||||
VAD_SAMPLE_RATE_16K,
|
||||
resample_24k_to_16k,
|
||||
)
|
||||
from langflow.utils.voice_utils import BYTES_PER_24K_FRAME, VAD_SAMPLE_RATE_16K, resample_24k_to_16k
|
||||
|
||||
router = APIRouter(prefix="/voice", tags=["Voice"])
|
||||
|
||||
|
|
@ -121,8 +117,8 @@ async def authenticate_and_get_openai_key(session: DbSession, user: User, websoc
|
|||
)
|
||||
return None, None
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.error(f"Error with API key: {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
await logger.aerror(f"Error with API key: {e}")
|
||||
await logger.aerror(traceback.format_exc())
|
||||
return None, None
|
||||
return user, openai_key
|
||||
|
||||
|
|
@ -185,13 +181,13 @@ class ElevenLabsClientManager:
|
|||
session=session,
|
||||
)
|
||||
except (InvalidToken, ValueError) as e:
|
||||
logger.error(f"Error with ElevenLabs API key: {e}")
|
||||
await logger.aerror(f"Error with ElevenLabs API key: {e}")
|
||||
cls._api_key = os.getenv("ELEVENLABS_API_KEY", "")
|
||||
if not cls._api_key:
|
||||
logger.error("ElevenLabs API key not found")
|
||||
await logger.aerror("ElevenLabs API key not found")
|
||||
return None
|
||||
except (KeyError, AttributeError, sqlalchemy.exc.SQLAlchemyError) as e:
|
||||
logger.error(f"Exception getting ElevenLabs API key: {e}")
|
||||
await logger.aerror(f"Exception getting ElevenLabs API key: {e}")
|
||||
return None
|
||||
|
||||
if cls._api_key:
|
||||
|
|
@ -310,25 +306,25 @@ async def process_message_queue(queue_key, session):
|
|||
|
||||
try:
|
||||
await aadd_messagetables([message], session)
|
||||
logger.debug(f"Added message to DB: {message.text[:30]}...")
|
||||
await logger.adebug(f"Added message to DB: {message.text[:30]}...")
|
||||
except ValueError as e:
|
||||
logger.error(f"Error saving message to database (ValueError): {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
await logger.aerror(f"Error saving message to database (ValueError): {e}")
|
||||
await logger.aerror(traceback.format_exc())
|
||||
except sqlalchemy.exc.SQLAlchemyError as e:
|
||||
logger.error(f"Error saving message to database (SQLAlchemyError): {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
await logger.aerror(f"Error saving message to database (SQLAlchemyError): {e}")
|
||||
await logger.aerror(traceback.format_exc())
|
||||
except (KeyError, AttributeError, TypeError) as e:
|
||||
# More specific exceptions instead of blind Exception
|
||||
logger.error(f"Error saving message to database: {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
await logger.aerror(f"Error saving message to database: {e}")
|
||||
await logger.aerror(traceback.format_exc())
|
||||
finally:
|
||||
message_queues[queue_key].task_done()
|
||||
|
||||
if message_queues[queue_key].empty():
|
||||
break
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.debug(f"Message queue processor for {queue_key} was cancelled: {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
await logger.adebug(f"Message queue processor for {queue_key} was cancelled: {e}")
|
||||
await logger.aerror(traceback.format_exc())
|
||||
|
||||
|
||||
class SendQueues:
|
||||
|
|
@ -369,7 +365,7 @@ class SendQueues:
|
|||
logger.trace("OPENAI BLOCKING")
|
||||
# log_event(msg, DIRECTION_TO_OPENAI)
|
||||
except Exception: # noqa: BLE001
|
||||
logger.error(traceback.format_exc())
|
||||
await logger.aerror(traceback.format_exc())
|
||||
|
||||
def client_send(self, payload):
|
||||
try:
|
||||
|
|
@ -387,7 +383,7 @@ class SendQueues:
|
|||
self.log_event(msg, LF_TO_CLIENT)
|
||||
await self.client_ws.send_text(json.dumps(msg))
|
||||
except Exception: # noqa: BLE001
|
||||
logger.error(traceback.format_exc())
|
||||
await logger.aerror(traceback.format_exc())
|
||||
|
||||
async def close(self):
|
||||
self.openai_send_q.put_nowait(None)
|
||||
|
|
@ -462,7 +458,7 @@ async def handle_function_call(
|
|||
create_response()
|
||||
except json.JSONDecodeError as e:
|
||||
trace = traceback.format_exc()
|
||||
logger.error(f"JSON decode error: {e!s}\ntrace: {trace}")
|
||||
await logger.aerror(f"JSON decode error: {e!s}\ntrace: {trace}")
|
||||
function_output = {
|
||||
"type": "conversation.item.create",
|
||||
"item": {
|
||||
|
|
@ -474,7 +470,7 @@ async def handle_function_call(
|
|||
msg_handler.openai_send(function_output)
|
||||
except ValueError as e:
|
||||
trace = traceback.format_exc()
|
||||
logger.error(f"Value error: {e!s}\ntrace: {trace}")
|
||||
await logger.aerror(f"Value error: {e!s}\ntrace: {trace}")
|
||||
function_output = {
|
||||
"type": "conversation.item.create",
|
||||
"item": {
|
||||
|
|
@ -486,7 +482,7 @@ async def handle_function_call(
|
|||
msg_handler.openai_send(function_output)
|
||||
except (ConnectionError, websockets.exceptions.WebSocketException) as e:
|
||||
trace = traceback.format_exc()
|
||||
logger.error(f"Connection error: {e!s}\ntrace: {trace}")
|
||||
await logger.aerror(f"Connection error: {e!s}\ntrace: {trace}")
|
||||
function_output = {
|
||||
"type": "conversation.item.create",
|
||||
"item": {
|
||||
|
|
@ -497,8 +493,8 @@ async def handle_function_call(
|
|||
}
|
||||
msg_handler.openai_send(function_output)
|
||||
except (KeyError, AttributeError, TypeError) as e:
|
||||
logger.error(f"Error executing flow: {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
await logger.aerror(f"Error executing flow: {e}")
|
||||
await logger.aerror(traceback.format_exc())
|
||||
function_output = {
|
||||
"type": "conversation.item.create",
|
||||
"item": {
|
||||
|
|
@ -751,7 +747,7 @@ async def flow_as_tool_websocket(
|
|||
except Exception as e: # noqa: BLE001
|
||||
err_msg = {"error": f"Failed to load flow: {e!s}"}
|
||||
await client_websocket.send_json(err_msg)
|
||||
logger.error(f"Failed to load flow: {e}")
|
||||
await logger.aerror(f"Failed to load flow: {e}")
|
||||
return
|
||||
|
||||
url = "wss://api.openai.com/v1/realtime?model=gpt-4o-mini-realtime-preview"
|
||||
|
|
@ -800,7 +796,7 @@ async def flow_as_tool_websocket(
|
|||
msg_handler.openai_send({"type": "response.cancel"})
|
||||
bot_speaking_flag[0] = False
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.error(f"[ERROR] VAD processing failed (ValueError): {e}")
|
||||
await logger.aerror(f"[ERROR] VAD processing failed (ValueError): {e}")
|
||||
continue
|
||||
if has_speech:
|
||||
last_speech_time = datetime.now(tz=timezone.utc)
|
||||
|
|
@ -856,7 +852,7 @@ async def flow_as_tool_websocket(
|
|||
return new_session
|
||||
|
||||
class Response:
|
||||
def __init__(self, response_id: str, use_elevenlabs: bool | None = None):
|
||||
def __init__(self, response_id: str, *, use_elevenlabs: bool | None = None):
|
||||
if use_elevenlabs is None:
|
||||
use_elevenlabs = False
|
||||
self.response_id = response_id
|
||||
|
|
@ -925,7 +921,7 @@ async def flow_as_tool_websocket(
|
|||
# client_send_event_from_thread(event, main_loop)
|
||||
msg_handler.client_send(event)
|
||||
except Exception: # noqa: BLE001
|
||||
logger.error(traceback.format_exc())
|
||||
await logger.aerror(traceback.format_exc())
|
||||
|
||||
async def forward_to_openai() -> None:
|
||||
nonlocal openai_realtime_session
|
||||
|
|
@ -954,10 +950,10 @@ async def flow_as_tool_websocket(
|
|||
msg_handler.openai_send(msg)
|
||||
num_audio_samples = 0
|
||||
elif msg.get("type") == "langflow.voice_mode.config":
|
||||
logger.info(f"langflow.voice_mode.config {msg}")
|
||||
await logger.ainfo(f"langflow.voice_mode.config {msg}")
|
||||
voice_config.progress_enabled = msg.get("progress_enabled", True)
|
||||
elif msg.get("type") == "langflow.elevenlabs.config":
|
||||
logger.info(f"langflow.elevenlabs.config {msg}")
|
||||
await logger.ainfo(f"langflow.elevenlabs.config {msg}")
|
||||
voice_config.use_elevenlabs = msg["enabled"]
|
||||
voice_config.elevenlabs_voice = msg.get("voice_id", voice_config.elevenlabs_voice)
|
||||
|
||||
|
|
@ -997,7 +993,7 @@ async def flow_as_tool_websocket(
|
|||
if do_forward:
|
||||
msg_handler.client_send(event)
|
||||
if event_type == "response.created":
|
||||
responses[response_id] = Response(response_id, voice_config.use_elevenlabs)
|
||||
responses[response_id] = Response(response_id, use_elevenlabs=voice_config.use_elevenlabs)
|
||||
if function_call:
|
||||
if function_call.is_prog_enabled and not function_call.prog_rsp_id:
|
||||
function_call.prog_rsp_id = response_id
|
||||
|
|
@ -1021,12 +1017,12 @@ async def flow_as_tool_websocket(
|
|||
message_text = event.get("text", "")
|
||||
await add_message_to_db(message_text, session, flow_id, session_id, "Machine", "AI")
|
||||
except ValueError as err:
|
||||
logger.error(f"Error saving message to database (ValueError): {err}")
|
||||
logger.error(traceback.format_exc())
|
||||
await logger.aerror(f"Error saving message to database (ValueError): {err}")
|
||||
await logger.aerror(traceback.format_exc())
|
||||
except (KeyError, AttributeError, TypeError) as err:
|
||||
# Replace blind Exception with specific exceptions
|
||||
logger.error(f"Error saving message to database: {err}")
|
||||
logger.error(traceback.format_exc())
|
||||
await logger.aerror(f"Error saving message to database: {err}")
|
||||
await logger.aerror(traceback.format_exc())
|
||||
|
||||
elif event_type == "response.output_item.added":
|
||||
bot_speaking_flag[0] = True
|
||||
|
|
@ -1050,12 +1046,12 @@ async def flow_as_tool_websocket(
|
|||
if transcript and transcript.strip():
|
||||
await add_message_to_db(transcript, session, flow_id, session_id, "Machine", "AI")
|
||||
except ValueError as err:
|
||||
logger.error(f"Error saving message to database (ValueError): {err}")
|
||||
logger.error(traceback.format_exc())
|
||||
await logger.aerror(f"Error saving message to database (ValueError): {err}")
|
||||
await logger.aerror(traceback.format_exc())
|
||||
except (KeyError, AttributeError, TypeError) as err:
|
||||
# Replace blind Exception with specific exceptions
|
||||
logger.error(f"Error saving message to database: {err}")
|
||||
logger.error(traceback.format_exc())
|
||||
await logger.aerror(f"Error saving message to database: {err}")
|
||||
await logger.aerror(traceback.format_exc())
|
||||
bot_speaking_flag[0] = False
|
||||
elif event_type == "response.done":
|
||||
msg_handler.openai_unblock()
|
||||
|
|
@ -1080,12 +1076,12 @@ async def flow_as_tool_websocket(
|
|||
if message_text and message_text.strip():
|
||||
await add_message_to_db(message_text, session, flow_id, session_id, "User", "User")
|
||||
except ValueError as e:
|
||||
logger.error(f"Error saving message to database (ValueError): {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
await logger.aerror(f"Error saving message to database (ValueError): {e}")
|
||||
await logger.aerror(traceback.format_exc())
|
||||
except (KeyError, AttributeError, TypeError) as e:
|
||||
# Replace blind Exception with specific exceptions
|
||||
logger.error(f"Error saving message to database: {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
await logger.aerror(f"Error saving message to database: {e}")
|
||||
await logger.aerror(traceback.format_exc())
|
||||
elif event_type == "error":
|
||||
pass
|
||||
|
||||
|
|
@ -1104,12 +1100,12 @@ async def flow_as_tool_websocket(
|
|||
# Check for exceptions in results
|
||||
for result in results:
|
||||
if isinstance(result, Exception):
|
||||
logger.error("WS loop failed:", exc_info=result)
|
||||
logger.error(traceback.format_exc())
|
||||
await logger.aerror("WS loop failed:", exc_info=result)
|
||||
await logger.aerror(traceback.format_exc())
|
||||
except Exception as e: # noqa: BLE001
|
||||
# Handle any other exceptions
|
||||
logger.error(f"WS loop failed: {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
await logger.aerror(f"WS loop failed: {e}")
|
||||
await logger.aerror(traceback.format_exc())
|
||||
finally:
|
||||
# shared cleanup for writers & sockets
|
||||
async def close():
|
||||
|
|
@ -1119,8 +1115,8 @@ async def flow_as_tool_websocket(
|
|||
|
||||
await close()
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.error(f"Unexpected error: {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
await logger.aerror(f"Unexpected error: {e}")
|
||||
await logger.aerror(traceback.format_exc())
|
||||
finally:
|
||||
# Make sure to clean up the task
|
||||
if vad_task and not vad_task.done():
|
||||
|
|
@ -1232,16 +1228,16 @@ async def flow_tts_websocket(
|
|||
elif event.get("type") == "input_audio_buffer.commit":
|
||||
openai_send(event)
|
||||
elif event.get("type") == "langflow.elevenlabs.config":
|
||||
logger.info(f"langflow.elevenlabs.config {event}")
|
||||
await logger.ainfo(f"langflow.elevenlabs.config {event}")
|
||||
tts_config.use_elevenlabs = event["enabled"]
|
||||
tts_config.elevenlabs_voice = event.get("voice_id", tts_config.elevenlabs_voice)
|
||||
elif event.get("type") == "voice.settings":
|
||||
# Store the voice setting
|
||||
if event.get("voice"):
|
||||
tts_config.openai_voice = event.get("voice")
|
||||
logger.info(f"Updated OpenAI voice to: {tts_config.openai_voice}")
|
||||
await logger.ainfo(f"Updated OpenAI voice to: {tts_config.openai_voice}")
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.error(f"Error in WebSocket communication: {e}")
|
||||
await logger.aerror(f"Error in WebSocket communication: {e}")
|
||||
|
||||
async def forward_to_client() -> None:
|
||||
try:
|
||||
|
|
@ -1312,7 +1308,7 @@ async def flow_tts_websocket(
|
|||
audio_event = {"type": "response.audio.delta", "delta": base64_audio}
|
||||
client_send(audio_event)
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.error(f"Error in WebSocket communication: {e}")
|
||||
await logger.aerror(f"Error in WebSocket communication: {e}")
|
||||
|
||||
try:
|
||||
# Create tasks and gather them for concurrent execution
|
||||
|
|
@ -1321,13 +1317,13 @@ async def flow_tts_websocket(
|
|||
await asyncio.gather(task1, task2)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
# handle any exceptions from any task
|
||||
logger.error("WS loop failed:", exc_info=exc)
|
||||
await logger.aerror("WS loop failed:", exc_info=exc)
|
||||
finally:
|
||||
# shared cleanup for writers & sockets
|
||||
await close()
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.error(f"Unexpected error: {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
await logger.aerror(f"Unexpected error: {e}")
|
||||
await logger.aerror(traceback.format_exc())
|
||||
|
||||
|
||||
def extract_transcript(json_data):
|
||||
|
|
@ -1367,13 +1363,13 @@ async def get_elevenlabs_voice_ids(
|
|||
for voice in voices
|
||||
]
|
||||
except ValueError as e:
|
||||
logger.error(f"Error fetching ElevenLabs voices (ValueError): {e}")
|
||||
await logger.aerror(f"Error fetching ElevenLabs voices (ValueError): {e}")
|
||||
return {"error": str(e)}
|
||||
except requests.RequestException as e:
|
||||
logger.error(f"Error fetching ElevenLabs voices (RequestException): {e}")
|
||||
await logger.aerror(f"Error fetching ElevenLabs voices (RequestException): {e}")
|
||||
return {"error": str(e)}
|
||||
except (KeyError, AttributeError, TypeError) as e:
|
||||
# More specific exceptions instead of blind Exception
|
||||
logger.error(f"Error fetching ElevenLabs voices: {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
await logger.aerror(f"Error fetching ElevenLabs voices: {e}")
|
||||
await logger.aerror(traceback.format_exc())
|
||||
return {"error": str(e)}
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@ from zoneinfo import ZoneInfo
|
|||
|
||||
from fastapi import APIRouter, Depends, File, HTTPException, UploadFile
|
||||
from fastapi.responses import StreamingResponse
|
||||
from loguru import logger
|
||||
from sqlmodel import col, select
|
||||
|
||||
from langflow.api.schemas import UploadFileResponse
|
||||
from langflow.api.utils import CurrentActiveUser, DbSession
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.services.database.models.file.model import File as UserFile
|
||||
from langflow.services.deps import get_settings_service, get_storage_service
|
||||
from langflow.services.storage.service import StorageService
|
||||
|
|
@ -488,7 +488,7 @@ async def delete_file(
|
|||
raise
|
||||
except Exception as e:
|
||||
# Log and return a generic server error
|
||||
logger.error("Error deleting file %s: %s", file_id, e)
|
||||
await logger.aerror("Error deleting file %s: %s", file_id, e)
|
||||
raise HTTPException(status_code=500, detail=f"Error deleting file: {e}") from e
|
||||
return {"detail": f"File {file_to_delete.name} deleted successfully"}
|
||||
|
||||
|
|
|
|||
|
|
@ -115,6 +115,7 @@ async def get_servers(
|
|||
session: DbSession,
|
||||
storage_service=Depends(get_storage_service),
|
||||
settings_service=Depends(get_settings_service),
|
||||
*,
|
||||
action_count: bool | None = None,
|
||||
):
|
||||
"""Get the list of available servers."""
|
||||
|
|
@ -140,27 +141,27 @@ async def get_servers(
|
|||
server_info["error"] = "No tools found"
|
||||
except ValueError as e:
|
||||
# Configuration validation errors, invalid URLs, etc.
|
||||
logger.error(f"Configuration error for server {server_name}: {e}")
|
||||
await logger.aerror(f"Configuration error for server {server_name}: {e}")
|
||||
server_info["error"] = f"Configuration error: {e}"
|
||||
except ConnectionError as e:
|
||||
# Network connection and timeout issues
|
||||
logger.error(f"Connection error for server {server_name}: {e}")
|
||||
await logger.aerror(f"Connection error for server {server_name}: {e}")
|
||||
server_info["error"] = f"Connection failed: {e}"
|
||||
except (TimeoutError, asyncio.TimeoutError) as e:
|
||||
# Timeout errors
|
||||
logger.error(f"Timeout error for server {server_name}: {e}")
|
||||
await logger.aerror(f"Timeout error for server {server_name}: {e}")
|
||||
server_info["error"] = "Timeout when checking server tools"
|
||||
except OSError as e:
|
||||
# System-level errors (process execution, file access)
|
||||
logger.error(f"System error for server {server_name}: {e}")
|
||||
await logger.aerror(f"System error for server {server_name}: {e}")
|
||||
server_info["error"] = f"System error: {e}"
|
||||
except (KeyError, TypeError) as e:
|
||||
# Data parsing and access errors
|
||||
logger.error(f"Data error for server {server_name}: {e}")
|
||||
await logger.aerror(f"Data error for server {server_name}: {e}")
|
||||
server_info["error"] = f"Configuration data error: {e}"
|
||||
except (RuntimeError, ProcessLookupError, PermissionError) as e:
|
||||
# Runtime and process-related errors
|
||||
logger.error(f"Runtime error for server {server_name}: {e}")
|
||||
await logger.aerror(f"Runtime error for server {server_name}: {e}")
|
||||
server_info["error"] = f"Runtime error: {e}"
|
||||
except Exception as e: # noqa: BLE001
|
||||
# Generic catch-all for other exceptions (including ExceptionGroup)
|
||||
|
|
@ -168,15 +169,15 @@ async def get_servers(
|
|||
# Extract the first underlying exception for a more meaningful error message
|
||||
underlying_error = e.exceptions[0]
|
||||
if hasattr(underlying_error, "exceptions"):
|
||||
logger.error(
|
||||
await logger.aerror(
|
||||
f"Error checking server {server_name}: {underlying_error}, {underlying_error.exceptions}"
|
||||
)
|
||||
underlying_error = underlying_error.exceptions[0]
|
||||
else:
|
||||
logger.exception(f"Error checking server {server_name}: {underlying_error}")
|
||||
await logger.aexception(f"Error checking server {server_name}: {underlying_error}")
|
||||
server_info["error"] = f"Error loading server: {underlying_error}"
|
||||
else:
|
||||
logger.exception(f"Error checking server {server_name}: {e}")
|
||||
await logger.aexception(f"Error checking server {server_name}: {e}")
|
||||
server_info["error"] = f"Error loading server: {e}"
|
||||
return server_info
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ import concurrent.futures
|
|||
import json
|
||||
|
||||
import httpx
|
||||
from loguru import logger
|
||||
from pydantic import BaseModel, SecretStr
|
||||
|
||||
from langflow.field_typing import Embeddings
|
||||
from langflow.logging.logger import logger
|
||||
|
||||
|
||||
class AIMLEmbeddingsImpl(BaseModel, Embeddings):
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
from loguru import logger
|
||||
|
||||
from langflow.graph.schema import ResultData, RunOutputs
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
from langflow.schema.message import Message
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
# noqa: A005
|
||||
|
|
@ -2,7 +2,8 @@ from functools import lru_cache
|
|||
from typing import Any
|
||||
|
||||
import httpx
|
||||
from loguru import logger
|
||||
|
||||
from langflow.logging.logger import logger
|
||||
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
|
|
|
|||
|
|
@ -15,12 +15,12 @@ import httpx
|
|||
from anyio import ClosedResourceError
|
||||
from httpx import codes as httpx_codes
|
||||
from langchain_core.tools import StructuredTool
|
||||
from loguru import logger
|
||||
from mcp import ClientSession
|
||||
from mcp.shared.exceptions import McpError
|
||||
from pydantic import BaseModel, Field, create_model
|
||||
from sqlmodel import select
|
||||
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.services.database.models.flow.model import Flow
|
||||
from langflow.services.deps import get_settings_service
|
||||
|
||||
|
|
@ -214,7 +214,7 @@ def create_tool_coroutine(tool_name: str, arg_schema: type[BaseModel], client) -
|
|||
try:
|
||||
return await client.run_tool(tool_name, arguments=validated.model_dump())
|
||||
except Exception as e:
|
||||
logger.error(f"Tool '{tool_name}' execution failed: {e}")
|
||||
await logger.aerror(f"Tool '{tool_name}' execution failed: {e}")
|
||||
# Re-raise with more context
|
||||
msg = f"Tool '{tool_name}' execution failed: {e}"
|
||||
raise ValueError(msg) from e
|
||||
|
|
@ -264,7 +264,7 @@ def get_unique_name(base_name, max_length, existing_names):
|
|||
i += 1
|
||||
|
||||
|
||||
async def get_flow_snake_case(flow_name: str, user_id: str, session, is_action: bool | None = None) -> Flow | None:
|
||||
async def get_flow_snake_case(flow_name: str, user_id: str, session, *, is_action: bool | None = None) -> Flow | None:
|
||||
uuid_user_id = UUID(user_id) if isinstance(user_id, str) else user_id
|
||||
stmt = select(Flow).where(Flow.user_id == uuid_user_id).where(Flow.is_component == False) # noqa: E712
|
||||
flows = (await session.exec(stmt)).all()
|
||||
|
|
@ -506,7 +506,7 @@ class MCPSessionManager:
|
|||
break
|
||||
except (RuntimeError, KeyError, ClosedResourceError, ValueError, asyncio.TimeoutError) as e:
|
||||
# Handle common recoverable errors without stopping the cleanup loop
|
||||
logger.warning(f"Error in periodic cleanup: {e}")
|
||||
await logger.awarning(f"Error in periodic cleanup: {e}")
|
||||
|
||||
async def _cleanup_idle_sessions(self):
|
||||
"""Clean up sessions that have been idle for too long."""
|
||||
|
|
@ -523,7 +523,7 @@ class MCPSessionManager:
|
|||
|
||||
# Clean up idle sessions
|
||||
for session_id in sessions_to_remove:
|
||||
logger.info(f"Cleaning up idle session {session_id} for server {server_key}")
|
||||
await logger.ainfo(f"Cleaning up idle session {session_id} for server {server_key}")
|
||||
await self._cleanup_session_by_id(server_key, session_id)
|
||||
|
||||
# Remove server entry if no sessions left
|
||||
|
|
@ -561,7 +561,7 @@ class MCPSessionManager:
|
|||
# Use a shorter timeout for the connectivity test to fail fast
|
||||
response = await asyncio.wait_for(session.list_tools(), timeout=3.0)
|
||||
except (asyncio.TimeoutError, ConnectionError, OSError, ValueError) as e:
|
||||
logger.debug(f"Session connectivity test failed (standard error): {e}")
|
||||
await logger.adebug(f"Session connectivity test failed (standard error): {e}")
|
||||
return False
|
||||
except Exception as e:
|
||||
# Handle MCP-specific errors that might not be in the standard list
|
||||
|
|
@ -574,27 +574,27 @@ class MCPSessionManager:
|
|||
or "Transport closed" in error_str
|
||||
or "Stream closed" in error_str
|
||||
):
|
||||
logger.debug(f"Session connectivity test failed (MCP connection error): {e}")
|
||||
await logger.adebug(f"Session connectivity test failed (MCP connection error): {e}")
|
||||
return False
|
||||
# Re-raise unexpected errors
|
||||
logger.warning(f"Unexpected error in connectivity test: {e}")
|
||||
await logger.awarning(f"Unexpected error in connectivity test: {e}")
|
||||
raise
|
||||
else:
|
||||
# Validate that we got a meaningful response
|
||||
if response is None:
|
||||
logger.debug("Session connectivity test failed: received None response")
|
||||
await logger.adebug("Session connectivity test failed: received None response")
|
||||
return False
|
||||
try:
|
||||
# Check if we can access the tools list (even if empty)
|
||||
tools = getattr(response, "tools", None)
|
||||
if tools is None:
|
||||
logger.debug("Session connectivity test failed: no tools attribute in response")
|
||||
await logger.adebug("Session connectivity test failed: no tools attribute in response")
|
||||
return False
|
||||
except (AttributeError, TypeError) as e:
|
||||
logger.debug(f"Session connectivity test failed while validating response: {e}")
|
||||
await logger.adebug(f"Session connectivity test failed while validating response: {e}")
|
||||
return False
|
||||
else:
|
||||
logger.debug(f"Session connectivity test passed: found {len(tools)} tools")
|
||||
await logger.adebug(f"Session connectivity test passed: found {len(tools)} tools")
|
||||
return True
|
||||
|
||||
async def get_session(self, context_id: str, connection_params, transport_type: str):
|
||||
|
|
@ -625,32 +625,32 @@ class MCPSessionManager:
|
|||
|
||||
# Quick health check
|
||||
if await self._validate_session_connectivity(session):
|
||||
logger.debug(f"Reusing existing session {session_id} for server {server_key}")
|
||||
await logger.adebug(f"Reusing existing session {session_id} for server {server_key}")
|
||||
# record mapping & bump ref-count for backwards compatibility
|
||||
self._context_to_session[context_id] = (server_key, session_id)
|
||||
self._session_refcount[(server_key, session_id)] = (
|
||||
self._session_refcount.get((server_key, session_id), 0) + 1
|
||||
)
|
||||
return session
|
||||
logger.info(f"Session {session_id} for server {server_key} failed health check, cleaning up")
|
||||
await logger.ainfo(f"Session {session_id} for server {server_key} failed health check, cleaning up")
|
||||
await self._cleanup_session_by_id(server_key, session_id)
|
||||
else:
|
||||
# Task is done, clean up
|
||||
logger.info(f"Session {session_id} for server {server_key} task is done, cleaning up")
|
||||
await logger.ainfo(f"Session {session_id} for server {server_key} task is done, cleaning up")
|
||||
await self._cleanup_session_by_id(server_key, session_id)
|
||||
|
||||
# Check if we've reached the maximum number of sessions for this server
|
||||
if len(sessions) >= MAX_SESSIONS_PER_SERVER:
|
||||
# Remove the oldest session
|
||||
oldest_session_id = min(sessions.keys(), key=lambda x: sessions[x]["last_used"])
|
||||
logger.info(
|
||||
await logger.ainfo(
|
||||
f"Maximum sessions reached for server {server_key}, removing oldest session {oldest_session_id}"
|
||||
)
|
||||
await self._cleanup_session_by_id(server_key, oldest_session_id)
|
||||
|
||||
# Create new session
|
||||
session_id = f"{server_key}_{len(sessions)}"
|
||||
logger.info(f"Creating new session {session_id} for server {server_key}")
|
||||
await logger.ainfo(f"Creating new session {session_id} for server {server_key}")
|
||||
|
||||
if transport_type == "stdio":
|
||||
session, task = await self._create_stdio_session(session_id, connection_params)
|
||||
|
|
@ -700,7 +700,7 @@ class MCPSessionManager:
|
|||
try:
|
||||
await event.wait()
|
||||
except asyncio.CancelledError:
|
||||
logger.info(f"Session {session_id} is shutting down")
|
||||
await logger.ainfo(f"Session {session_id} is shutting down")
|
||||
except Exception as e: # noqa: BLE001
|
||||
if not session_future.done():
|
||||
session_future.set_exception(e)
|
||||
|
|
@ -723,7 +723,7 @@ class MCPSessionManager:
|
|||
await task
|
||||
self._background_tasks.discard(task)
|
||||
msg = f"Timeout waiting for STDIO session {session_id} to initialize"
|
||||
logger.error(msg)
|
||||
await logger.aerror(msg)
|
||||
raise ValueError(msg) from timeout_err
|
||||
|
||||
return session, task
|
||||
|
|
@ -759,7 +759,7 @@ class MCPSessionManager:
|
|||
try:
|
||||
await event.wait()
|
||||
except asyncio.CancelledError:
|
||||
logger.info(f"Session {session_id} is shutting down")
|
||||
await logger.ainfo(f"Session {session_id} is shutting down")
|
||||
except Exception as e: # noqa: BLE001
|
||||
if not session_future.done():
|
||||
session_future.set_exception(e)
|
||||
|
|
@ -782,7 +782,7 @@ class MCPSessionManager:
|
|||
await task
|
||||
self._background_tasks.discard(task)
|
||||
msg = f"Timeout waiting for SSE session {session_id} to initialize"
|
||||
logger.error(msg)
|
||||
await logger.aerror(msg)
|
||||
raise ValueError(msg) from timeout_err
|
||||
|
||||
return session, task
|
||||
|
|
@ -813,9 +813,9 @@ class MCPSessionManager:
|
|||
if hasattr(session, "aclose"):
|
||||
try:
|
||||
await session.aclose()
|
||||
logger.debug("Successfully closed session %s using aclose()", session_id)
|
||||
await logger.adebug("Successfully closed session %s using aclose()", session_id)
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.debug("Error closing session %s with aclose(): %s", session_id, e)
|
||||
await logger.adebug("Error closing session %s with aclose(): %s", session_id, e)
|
||||
|
||||
# If no aclose, try regular close method
|
||||
elif hasattr(session, "close"):
|
||||
|
|
@ -824,18 +824,20 @@ class MCPSessionManager:
|
|||
if inspect.iscoroutinefunction(session.close):
|
||||
# It's an async method
|
||||
await session.close()
|
||||
logger.debug("Successfully closed session %s using async close()", session_id)
|
||||
await logger.adebug("Successfully closed session %s using async close()", session_id)
|
||||
else:
|
||||
# Try calling it and check if result is awaitable
|
||||
close_result = session.close()
|
||||
if inspect.isawaitable(close_result):
|
||||
await close_result
|
||||
logger.debug("Successfully closed session %s using awaitable close()", session_id)
|
||||
await logger.adebug(
|
||||
"Successfully closed session %s using awaitable close()", session_id
|
||||
)
|
||||
else:
|
||||
# It's a synchronous close
|
||||
logger.debug("Successfully closed session %s using sync close()", session_id)
|
||||
await logger.adebug("Successfully closed session %s using sync close()", session_id)
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.debug("Error closing session %s with close(): %s", session_id, e)
|
||||
await logger.adebug("Error closing session %s with close(): %s", session_id, e)
|
||||
|
||||
# Cancel the background task which will properly close the session
|
||||
if "task" in session_info:
|
||||
|
|
@ -845,9 +847,9 @@ class MCPSessionManager:
|
|||
try:
|
||||
await task
|
||||
except asyncio.CancelledError:
|
||||
logger.info(f"Cancelled task for session {session_id}")
|
||||
await logger.ainfo(f"Cancelled task for session {session_id}")
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.warning(f"Error cleaning up session {session_id}: {e}")
|
||||
await logger.awarning(f"Error cleaning up session {session_id}: {e}")
|
||||
finally:
|
||||
# Remove from sessions dict
|
||||
del sessions[session_id]
|
||||
|
|
@ -900,7 +902,7 @@ class MCPSessionManager:
|
|||
"""
|
||||
mapping = self._context_to_session.get(context_id)
|
||||
if not mapping:
|
||||
logger.debug(f"No session mapping found for context_id {context_id}")
|
||||
await logger.adebug(f"No session mapping found for context_id {context_id}")
|
||||
return
|
||||
|
||||
server_key, session_id = mapping
|
||||
|
|
@ -1031,7 +1033,7 @@ class MCPStdioClient:
|
|||
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
logger.debug(f"Attempting to run tool '{tool_name}' (attempt {attempt + 1}/{max_retries})")
|
||||
await logger.adebug(f"Attempting to run tool '{tool_name}' (attempt {attempt + 1}/{max_retries})")
|
||||
# Get or create persistent session
|
||||
session = await self._get_or_create_session()
|
||||
|
||||
|
|
@ -1041,7 +1043,7 @@ class MCPStdioClient:
|
|||
)
|
||||
except Exception as e:
|
||||
current_error_type = type(e).__name__
|
||||
logger.warning(f"Tool '{tool_name}' failed on attempt {attempt + 1}: {current_error_type} - {e}")
|
||||
await logger.awarning(f"Tool '{tool_name}' failed on attempt {attempt + 1}: {current_error_type} - {e}")
|
||||
|
||||
# Import specific MCP error types for detection
|
||||
try:
|
||||
|
|
@ -1056,14 +1058,14 @@ class MCPStdioClient:
|
|||
|
||||
# If we're getting the same error type repeatedly, don't retry
|
||||
if last_error_type == current_error_type and attempt > 0:
|
||||
logger.error(f"Repeated {current_error_type} error for tool '{tool_name}', not retrying")
|
||||
await logger.aerror(f"Repeated {current_error_type} error for tool '{tool_name}', not retrying")
|
||||
break
|
||||
|
||||
last_error_type = current_error_type
|
||||
|
||||
# If it's a connection error (ClosedResourceError or MCP connection closed) and we have retries left
|
||||
if (is_closed_resource_error or is_mcp_connection_error) and attempt < max_retries - 1:
|
||||
logger.warning(
|
||||
await logger.awarning(
|
||||
f"MCP session connection issue for tool '{tool_name}', retrying with fresh session..."
|
||||
)
|
||||
# Clean up the dead session
|
||||
|
|
@ -1076,7 +1078,7 @@ class MCPStdioClient:
|
|||
|
||||
# If it's a timeout error and we have retries left, try once more
|
||||
if is_timeout_error and attempt < max_retries - 1:
|
||||
logger.warning(f"Tool '{tool_name}' timed out, retrying...")
|
||||
await logger.awarning(f"Tool '{tool_name}' timed out, retrying...")
|
||||
# Don't clean up session for timeouts, might just be a slow response
|
||||
await asyncio.sleep(1.0)
|
||||
continue
|
||||
|
|
@ -1089,7 +1091,7 @@ class MCPStdioClient:
|
|||
or is_timeout_error
|
||||
):
|
||||
msg = f"Failed to run tool '{tool_name}' after {attempt + 1} attempts: {e}"
|
||||
logger.error(msg)
|
||||
await logger.aerror(msg)
|
||||
# Clean up failed session from cache
|
||||
if self._session_context and self._component_cache:
|
||||
cache_key = f"mcp_session_stdio_{self._session_context}"
|
||||
|
|
@ -1099,12 +1101,12 @@ class MCPStdioClient:
|
|||
# Re-raise unexpected errors
|
||||
raise
|
||||
else:
|
||||
logger.debug(f"Tool '{tool_name}' completed successfully")
|
||||
await logger.adebug(f"Tool '{tool_name}' completed successfully")
|
||||
return result
|
||||
|
||||
# This should never be reached due to the exception handling above
|
||||
msg = f"Failed to run tool '{tool_name}': Maximum retries exceeded with repeated {last_error_type} errors"
|
||||
logger.error(msg)
|
||||
await logger.aerror(msg)
|
||||
raise ValueError(msg)
|
||||
|
||||
async def disconnect(self):
|
||||
|
|
@ -1213,7 +1215,7 @@ class MCPSseClient:
|
|||
return response.headers.get("Location", url)
|
||||
# Don't treat 404 as an error here - let the main connection handle it
|
||||
except (httpx.RequestError, httpx.HTTPError) as e:
|
||||
logger.warning(f"Error checking redirects: {e}")
|
||||
await logger.awarning(f"Error checking redirects: {e}")
|
||||
return url
|
||||
|
||||
async def _connect_to_server(
|
||||
|
|
@ -1336,7 +1338,7 @@ class MCPSseClient:
|
|||
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
logger.debug(f"Attempting to run tool '{tool_name}' (attempt {attempt + 1}/{max_retries})")
|
||||
await logger.adebug(f"Attempting to run tool '{tool_name}' (attempt {attempt + 1}/{max_retries})")
|
||||
# Get or create persistent session
|
||||
session = await self._get_or_create_session()
|
||||
|
||||
|
|
@ -1349,7 +1351,7 @@ class MCPSseClient:
|
|||
)
|
||||
except Exception as e:
|
||||
current_error_type = type(e).__name__
|
||||
logger.warning(f"Tool '{tool_name}' failed on attempt {attempt + 1}: {current_error_type} - {e}")
|
||||
await logger.awarning(f"Tool '{tool_name}' failed on attempt {attempt + 1}: {current_error_type} - {e}")
|
||||
|
||||
# Import specific MCP error types for detection
|
||||
try:
|
||||
|
|
@ -1367,14 +1369,14 @@ class MCPSseClient:
|
|||
|
||||
# If we're getting the same error type repeatedly, don't retry
|
||||
if last_error_type == current_error_type and attempt > 0:
|
||||
logger.error(f"Repeated {current_error_type} error for tool '{tool_name}', not retrying")
|
||||
await logger.aerror(f"Repeated {current_error_type} error for tool '{tool_name}', not retrying")
|
||||
break
|
||||
|
||||
last_error_type = current_error_type
|
||||
|
||||
# If it's a connection error (ClosedResourceError or MCP connection closed) and we have retries left
|
||||
if (is_closed_resource_error or is_mcp_connection_error) and attempt < max_retries - 1:
|
||||
logger.warning(
|
||||
await logger.awarning(
|
||||
f"MCP session connection issue for tool '{tool_name}', retrying with fresh session..."
|
||||
)
|
||||
# Clean up the dead session
|
||||
|
|
@ -1387,7 +1389,7 @@ class MCPSseClient:
|
|||
|
||||
# If it's a timeout error and we have retries left, try once more
|
||||
if is_timeout_error and attempt < max_retries - 1:
|
||||
logger.warning(f"Tool '{tool_name}' timed out, retrying...")
|
||||
await logger.awarning(f"Tool '{tool_name}' timed out, retrying...")
|
||||
# Don't clean up session for timeouts, might just be a slow response
|
||||
await asyncio.sleep(1.0)
|
||||
continue
|
||||
|
|
@ -1400,7 +1402,7 @@ class MCPSseClient:
|
|||
or is_timeout_error
|
||||
):
|
||||
msg = f"Failed to run tool '{tool_name}' after {attempt + 1} attempts: {e}"
|
||||
logger.error(msg)
|
||||
await logger.aerror(msg)
|
||||
# Clean up failed session from cache
|
||||
if self._session_context and self._component_cache:
|
||||
cache_key = f"mcp_session_sse_{self._session_context}"
|
||||
|
|
@ -1410,12 +1412,12 @@ class MCPSseClient:
|
|||
# Re-raise unexpected errors
|
||||
raise
|
||||
else:
|
||||
logger.debug(f"Tool '{tool_name}' completed successfully")
|
||||
await logger.adebug(f"Tool '{tool_name}' completed successfully")
|
||||
return result
|
||||
|
||||
# This should never be reached due to the exception handling above
|
||||
msg = f"Failed to run tool '{tool_name}': Maximum retries exceeded with repeated {last_error_type} errors"
|
||||
logger.error(msg)
|
||||
await logger.aerror(msg)
|
||||
raise ValueError(msg)
|
||||
|
||||
async def disconnect(self):
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@ from typing import Any
|
|||
|
||||
from fastapi import HTTPException
|
||||
from langchain_core.prompts import PromptTemplate
|
||||
from loguru import logger
|
||||
|
||||
from langflow.inputs.inputs import DefaultPromptField
|
||||
from langflow.interface.utils import extract_input_variables_from_prompt
|
||||
from langflow.logging.logger import logger
|
||||
|
||||
_INVALID_CHARACTERS = {
|
||||
" ",
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@ from __future__ import annotations
|
|||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from langchain_core.tools import BaseTool, ToolException
|
||||
from loguru import logger
|
||||
from typing_extensions import override
|
||||
|
||||
from langflow.base.flow_processing.utils import build_data_from_result_data, format_flow_output_data
|
||||
from langflow.graph.graph.base import Graph # cannot be a part of TYPE_CHECKING # noqa: TC001
|
||||
from langflow.graph.vertex.base import Vertex # cannot be a part of TYPE_CHECKING # noqa: TC001
|
||||
from langflow.helpers.flow import build_schema_from_inputs, get_arg_names, get_flow_inputs, run_flow
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.utils.async_helpers import run_until_complete
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
|
@ -109,7 +109,7 @@ class FlowTool(BaseTool):
|
|||
try:
|
||||
run_id = self.graph.run_id if hasattr(self, "graph") and self.graph else None
|
||||
except Exception: # noqa: BLE001
|
||||
logger.opt(exception=True).warning("Failed to set run_id")
|
||||
logger.warning("Failed to set run_id", exc_info=True)
|
||||
run_id = None
|
||||
run_outputs = await run_flow(
|
||||
tweaks={key: {"input_value": value} for key, value in tweaks.items()},
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
from abc import abstractmethod
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from loguru import logger
|
||||
from typing_extensions import override
|
||||
|
||||
from langflow.custom.custom_component.component import Component, _get_component_toolkit
|
||||
|
|
@ -9,11 +8,8 @@ from langflow.field_typing import Tool
|
|||
from langflow.graph.graph.base import Graph
|
||||
from langflow.graph.vertex.base import Vertex
|
||||
from langflow.helpers.flow import get_flow_inputs
|
||||
from langflow.inputs.inputs import (
|
||||
DropdownInput,
|
||||
InputTypes,
|
||||
MessageInput,
|
||||
)
|
||||
from langflow.inputs.inputs import DropdownInput, InputTypes, MessageInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
from langflow.schema.dataframe import DataFrame
|
||||
from langflow.schema.dotdict import dotdict
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ from typing import Any
|
|||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
from langchain.tools import StructuredTool
|
||||
from loguru import logger
|
||||
from markdown import markdown
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from langflow.base.langchain_utilities.model import LCToolComponent
|
||||
from langflow.field_typing import Tool
|
||||
from langflow.inputs.inputs import MultilineInput, SecretStrInput, StrInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
|
||||
MIN_ROWS_IN_TABLE = 3
|
||||
|
|
@ -84,7 +84,7 @@ class AddContentToPage(LCToolComponent):
|
|||
error_message += f" Status code: {e.response.status_code}, Response: {e.response.text}"
|
||||
return error_message
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.opt(exception=True).debug("Error adding content to Notion page")
|
||||
logger.debug("Error adding content to Notion page", exc_info=True)
|
||||
return f"Error: An unexpected error occurred while adding content to Notion page. {e}"
|
||||
|
||||
def process_node(self, node):
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import requests
|
||||
from langchain.tools import StructuredTool
|
||||
from loguru import logger
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from langflow.base.langchain_utilities.model import LCToolComponent
|
||||
from langflow.field_typing import Tool
|
||||
from langflow.inputs.inputs import SecretStrInput, StrInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
|
||||
|
||||
|
|
@ -64,5 +64,5 @@ class NotionDatabaseProperties(LCToolComponent):
|
|||
except ValueError as e:
|
||||
return f"Error parsing Notion API response: {e}"
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.opt(exception=True).debug("Error fetching Notion database properties")
|
||||
logger.debug("Error fetching Notion database properties", exc_info=True)
|
||||
return f"An unexpected error occurred: {e}"
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@ from typing import Any
|
|||
|
||||
import requests
|
||||
from langchain.tools import StructuredTool
|
||||
from loguru import logger
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from langflow.base.langchain_utilities.model import LCToolComponent
|
||||
from langflow.field_typing import Tool
|
||||
from langflow.inputs.inputs import MultilineInput, SecretStrInput, StrInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
|
||||
|
||||
|
|
@ -118,5 +118,5 @@ class NotionListPages(LCToolComponent):
|
|||
except KeyError:
|
||||
return "Unexpected response format from Notion API"
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.opt(exception=True).debug("Error querying Notion database")
|
||||
logger.debug("Error querying Notion database", exc_info=True)
|
||||
return f"An unexpected error occurred: {e}"
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import requests
|
||||
from langchain.tools import StructuredTool
|
||||
from loguru import logger
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from langflow.base.langchain_utilities.model import LCToolComponent
|
||||
from langflow.field_typing import Tool
|
||||
from langflow.inputs.inputs import SecretStrInput, StrInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
|
||||
|
||||
|
|
@ -65,7 +65,7 @@ class NotionPageContent(LCToolComponent):
|
|||
error_message += f" Status code: {e.response.status_code}, Response: {e.response.text}"
|
||||
return error_message
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.opt(exception=True).debug("Error retrieving Notion page content")
|
||||
logger.debug("Error retrieving Notion page content", exc_info=True)
|
||||
return f"Error: An unexpected error occurred while retrieving Notion page content. {e}"
|
||||
|
||||
def parse_blocks(self, blocks: list) -> str:
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@ from typing import Any
|
|||
|
||||
import requests
|
||||
from langchain.tools import StructuredTool
|
||||
from loguru import logger
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from langflow.base.langchain_utilities.model import LCToolComponent
|
||||
from langflow.field_typing import Tool
|
||||
from langflow.inputs.inputs import MultilineInput, SecretStrInput, StrInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,9 @@
|
|||
import httpx
|
||||
from loguru import logger
|
||||
|
||||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.field_typing.range_spec import RangeSpec
|
||||
from langflow.io import (
|
||||
BoolInput,
|
||||
DropdownInput,
|
||||
IntInput,
|
||||
MessageTextInput,
|
||||
MultilineInput,
|
||||
Output,
|
||||
SecretStrInput,
|
||||
)
|
||||
from langflow.io import BoolInput, DropdownInput, IntInput, MessageTextInput, MultilineInput, Output, SecretStrInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -135,13 +135,13 @@ class AgentComponent(ToolCallingAgentComponent):
|
|||
# return result
|
||||
|
||||
except (ValueError, TypeError, KeyError) as e:
|
||||
logger.error(f"{type(e).__name__}: {e!s}")
|
||||
await logger.aerror(f"{type(e).__name__}: {e!s}")
|
||||
raise
|
||||
except ExceptionWithMessageError as e:
|
||||
logger.error(f"ExceptionWithMessageError occurred: {e}")
|
||||
await logger.aerror(f"ExceptionWithMessageError occurred: {e}")
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Unexpected error: {e!s}")
|
||||
await logger.aerror(f"Unexpected error: {e!s}")
|
||||
raise
|
||||
else:
|
||||
return result
|
||||
|
|
|
|||
|
|
@ -117,12 +117,12 @@ class MCPToolsComponent(ComponentWithCache):
|
|||
schema_inputs = schema_to_langflow_inputs(input_schema)
|
||||
if not schema_inputs:
|
||||
msg = f"No input parameters defined for tool '{tool_obj.name}'"
|
||||
logger.warning(msg)
|
||||
await logger.awarning(msg)
|
||||
return []
|
||||
|
||||
except Exception as e:
|
||||
msg = f"Error validating schema inputs: {e!s}"
|
||||
logger.exception(msg)
|
||||
await logger.aexception(msg)
|
||||
raise ValueError(msg) from e
|
||||
else:
|
||||
return schema_inputs
|
||||
|
|
@ -202,11 +202,11 @@ class MCPToolsComponent(ComponentWithCache):
|
|||
|
||||
except (TimeoutError, asyncio.TimeoutError) as e:
|
||||
msg = f"Timeout updating tool list: {e!s}"
|
||||
logger.exception(msg)
|
||||
await logger.aexception(msg)
|
||||
raise TimeoutError(msg) from e
|
||||
except Exception as e:
|
||||
msg = f"Error updating tool list: {e!s}"
|
||||
logger.exception(msg)
|
||||
await logger.aexception(msg)
|
||||
raise ValueError(msg) from e
|
||||
else:
|
||||
return tool_list, {"name": server_name, "config": server_config}
|
||||
|
|
@ -223,7 +223,7 @@ class MCPToolsComponent(ComponentWithCache):
|
|||
build_config["tool"]["placeholder"] = "Select a tool"
|
||||
except (TimeoutError, asyncio.TimeoutError) as e:
|
||||
msg = f"Timeout updating tool list: {e!s}"
|
||||
logger.exception(msg)
|
||||
await logger.aexception(msg)
|
||||
if not build_config["tools_metadata"]["show"]:
|
||||
build_config["tool"]["show"] = True
|
||||
build_config["tool"]["options"] = []
|
||||
|
|
@ -249,7 +249,7 @@ class MCPToolsComponent(ComponentWithCache):
|
|||
break
|
||||
if tool_obj is None:
|
||||
msg = f"Tool {field_value} not found in available tools: {self.tools}"
|
||||
logger.warning(msg)
|
||||
await logger.awarning(msg)
|
||||
return build_config
|
||||
await self._update_tool_config(build_config, field_value)
|
||||
except Exception as e:
|
||||
|
|
@ -333,7 +333,7 @@ class MCPToolsComponent(ComponentWithCache):
|
|||
|
||||
except Exception as e:
|
||||
msg = f"Error in update_build_config: {e!s}"
|
||||
logger.exception(msg)
|
||||
await logger.aexception(msg)
|
||||
raise ValueError(msg) from e
|
||||
else:
|
||||
return build_config
|
||||
|
|
@ -386,7 +386,7 @@ class MCPToolsComponent(ComponentWithCache):
|
|||
msg = f"Tool {tool_name} not found in available tools: {self.tools}"
|
||||
self.remove_non_default_keys(build_config)
|
||||
build_config["tool"]["value"] = ""
|
||||
logger.warning(msg)
|
||||
await logger.awarning(msg)
|
||||
return
|
||||
|
||||
try:
|
||||
|
|
@ -404,14 +404,14 @@ class MCPToolsComponent(ComponentWithCache):
|
|||
self.schema_inputs = await self._validate_schema_inputs(tool_obj)
|
||||
if not self.schema_inputs:
|
||||
msg = f"No input parameters to configure for tool '{tool_name}'"
|
||||
logger.info(msg)
|
||||
await logger.ainfo(msg)
|
||||
return
|
||||
|
||||
# Add new inputs to build config
|
||||
for schema_input in self.schema_inputs:
|
||||
if not schema_input or not hasattr(schema_input, "name"):
|
||||
msg = "Invalid schema input detected, skipping"
|
||||
logger.warning(msg)
|
||||
await logger.awarning(msg)
|
||||
continue
|
||||
|
||||
try:
|
||||
|
|
@ -428,16 +428,16 @@ class MCPToolsComponent(ComponentWithCache):
|
|||
|
||||
except (AttributeError, KeyError, TypeError) as e:
|
||||
msg = f"Error processing schema input {schema_input}: {e!s}"
|
||||
logger.exception(msg)
|
||||
await logger.aexception(msg)
|
||||
continue
|
||||
except ValueError as e:
|
||||
msg = f"Schema validation error for tool {tool_name}: {e!s}"
|
||||
logger.exception(msg)
|
||||
await logger.aexception(msg)
|
||||
self.schema_inputs = []
|
||||
return
|
||||
except (AttributeError, KeyError, TypeError) as e:
|
||||
msg = f"Error updating tool config: {e!s}"
|
||||
logger.exception(msg)
|
||||
await logger.aexception(msg)
|
||||
raise ValueError(msg) from e
|
||||
|
||||
async def build_output(self) -> DataFrame:
|
||||
|
|
@ -474,7 +474,7 @@ class MCPToolsComponent(ComponentWithCache):
|
|||
return DataFrame(data=[{"error": "You must select a tool"}])
|
||||
except Exception as e:
|
||||
msg = f"Error in build_output: {e!s}"
|
||||
logger.exception(msg)
|
||||
await logger.aexception(msg)
|
||||
raise ValueError(msg) from e
|
||||
|
||||
def _get_session_context(self) -> str | None:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
from typing import Any, cast
|
||||
|
||||
import requests
|
||||
from loguru import logger
|
||||
from pydantic import ValidationError
|
||||
|
||||
from langflow.base.models.anthropic_constants import (
|
||||
|
|
@ -14,6 +13,7 @@ from langflow.base.models.model import LCModelComponent
|
|||
from langflow.field_typing import LanguageModel
|
||||
from langflow.field_typing.range_spec import RangeSpec
|
||||
from langflow.io import BoolInput, DropdownInput, IntInput, MessageTextInput, SecretStrInput, SliderInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.dotdict import dotdict
|
||||
|
||||
|
||||
|
|
@ -101,7 +101,7 @@ class AnthropicModelComponent(LCModelComponent):
|
|||
|
||||
return output
|
||||
|
||||
def get_models(self, tool_model_enabled: bool | None = None) -> list[str]:
|
||||
def get_models(self, *, tool_model_enabled: bool | None = None) -> list[str]:
|
||||
try:
|
||||
import anthropic
|
||||
|
||||
|
|
@ -129,7 +129,7 @@ class AnthropicModelComponent(LCModelComponent):
|
|||
model_with_tool = ChatAnthropic(
|
||||
model=model, # Use the current model being checked
|
||||
anthropic_api_key=self.api_key,
|
||||
anthropic_api_url=cast(str, self.base_url) or DEFAULT_ANTHROPIC_API_URL,
|
||||
anthropic_api_url=cast("str", self.base_url) or DEFAULT_ANTHROPIC_API_URL,
|
||||
)
|
||||
|
||||
if (
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import assemblyai as aai
|
||||
from loguru import logger
|
||||
|
||||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.io import DataInput, DropdownInput, IntInput, Output, SecretStrInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ class AssemblyAIGetSubtitles(Component):
|
|||
transcript = aai.Transcript.get_by_id(transcript_id)
|
||||
except Exception as e: # noqa: BLE001
|
||||
error = f"Getting transcription failed: {e}"
|
||||
logger.opt(exception=True).debug(error)
|
||||
logger.debug(error, exc_info=True)
|
||||
self.status = error
|
||||
return Data(data={"error": error})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import assemblyai as aai
|
||||
from loguru import logger
|
||||
|
||||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.io import DataInput, DropdownInput, FloatInput, IntInput, MultilineInput, Output, SecretStrInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
|
||||
|
||||
|
|
@ -131,7 +131,7 @@ class AssemblyAILeMUR(Component):
|
|||
try:
|
||||
response = self.perform_lemur_action(transcript_group, self.endpoint)
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.opt(exception=True).debug("Error running LeMUR")
|
||||
logger.debug("Error running LeMUR", exc_info=True)
|
||||
error = f"An Error happened: {e}"
|
||||
self.status = error
|
||||
return Data(data={"error": error})
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import assemblyai as aai
|
||||
from loguru import logger
|
||||
|
||||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.io import BoolInput, DropdownInput, IntInput, MessageTextInput, Output, SecretStrInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
|
||||
|
||||
|
|
@ -86,7 +86,7 @@ class AssemblyAIListTranscripts(Component):
|
|||
transcripts = convert_page_to_data_list(page)
|
||||
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.opt(exception=True).debug("Error listing transcripts")
|
||||
logger.debug("Error listing transcripts", exc_info=True)
|
||||
error_data = Data(data={"error": f"An error occurred: {e}"})
|
||||
self.status = [error_data]
|
||||
return [error_data]
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import assemblyai as aai
|
||||
from loguru import logger
|
||||
|
||||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.field_typing.range_spec import RangeSpec
|
||||
from langflow.io import DataInput, FloatInput, Output, SecretStrInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ class AssemblyAITranscriptionJobPoller(Component):
|
|||
transcript = aai.Transcript.get_by_id(self.transcript_id.data["transcript_id"])
|
||||
except Exception as e: # noqa: BLE001
|
||||
error = f"Getting transcription failed: {e}"
|
||||
logger.opt(exception=True).debug(error)
|
||||
logger.debug(error, exc_info=True)
|
||||
self.status = error
|
||||
return Data(data={"error": error})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
from pathlib import Path
|
||||
|
||||
import assemblyai as aai
|
||||
from loguru import logger
|
||||
|
||||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.io import BoolInput, DropdownInput, FileInput, MessageTextInput, Output, SecretStrInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
|
||||
|
||||
|
|
@ -176,7 +176,7 @@ class AssemblyAITranscriptionJobCreator(Component):
|
|||
try:
|
||||
transcript = aai.Transcriber().submit(audio, config=config)
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.opt(exception=True).debug("Error submitting transcription job")
|
||||
logger.debug("Error submitting transcription job", exc_info=True)
|
||||
self.status = f"An error occurred: {e}"
|
||||
return Data(data={"error": f"An error occurred: {e}"})
|
||||
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@ import re
|
|||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
from langchain_community.document_loaders import RecursiveUrlLoader
|
||||
from loguru import logger
|
||||
|
||||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.field_typing.range_spec import RangeSpec
|
||||
from langflow.helpers.data import safe_convert
|
||||
from langflow.io import BoolInput, DropdownInput, IntInput, MessageTextInput, Output, SliderInput, TableInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.dataframe import DataFrame
|
||||
from langflow.schema.message import Message
|
||||
from langflow.services.deps import get_settings_service
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ from typing import TYPE_CHECKING, Any, cast
|
|||
|
||||
from astra_assistants.astra_assistants_manager import AssistantManager
|
||||
from langchain_core.agents import AgentFinish
|
||||
from loguru import logger
|
||||
|
||||
from langflow.base.agents.events import ExceptionWithMessageError, process_agent_events
|
||||
from langflow.base.astra_assistants.util import (
|
||||
|
|
@ -15,6 +14,7 @@ from langflow.base.astra_assistants.util import (
|
|||
)
|
||||
from langflow.custom.custom_component.component_with_cache import ComponentWithCache
|
||||
from langflow.inputs.inputs import DropdownInput, FileInput, HandleInput, MultilineInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.memory import delete_message
|
||||
from langflow.schema.content_block import ContentBlock
|
||||
from langflow.schema.message import Message
|
||||
|
|
@ -186,8 +186,8 @@ class AstraAssistantManager(ComponentWithCache):
|
|||
self.initialized = True
|
||||
|
||||
async def process_inputs(self) -> None:
|
||||
logger.info(f"env_set is {self.env_set}")
|
||||
logger.info(self.input_tools)
|
||||
await logger.ainfo(f"env_set is {self.env_set}")
|
||||
await logger.ainfo(self.input_tools)
|
||||
tools = []
|
||||
tool_obj = None
|
||||
if self.input_tools is None:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
from loguru import logger
|
||||
|
||||
from langflow.base.astra_assistants.util import get_patched_openai_client
|
||||
from langflow.custom.custom_component.component_with_cache import ComponentWithCache
|
||||
from langflow.inputs.inputs import MultilineInput, StrInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.message import Message
|
||||
from langflow.template.field.base import Output
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
from loguru import logger
|
||||
|
||||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.io import DataInput, Output
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from langflow.base.flow_processing.utils import build_data_from_result_data
|
||||
from langflow.custom.custom_component.custom_component import CustomComponent
|
||||
from langflow.graph.graph.base import Graph
|
||||
from langflow.graph.vertex.base import Vertex
|
||||
from langflow.helpers.flow import get_flow_inputs
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
from langflow.schema.dotdict import dotdict
|
||||
from langflow.template.field.base import Input
|
||||
|
|
@ -36,7 +35,7 @@ class SubFlowComponent(CustomComponent):
|
|||
return None
|
||||
|
||||
async def update_build_config(self, build_config: dotdict, field_value: Any, field_name: str | None = None):
|
||||
logger.debug(f"Updating build config with field value {field_value} and field name {field_name}")
|
||||
await logger.adebug(f"Updating build config with field value {field_value} and field name {field_name}")
|
||||
if field_name == "flow_name":
|
||||
build_config["flow_name"]["options"] = await self.get_flow_names()
|
||||
# Clean up the build config
|
||||
|
|
@ -47,11 +46,11 @@ class SubFlowComponent(CustomComponent):
|
|||
try:
|
||||
flow_data = await self.get_flow(field_value)
|
||||
except Exception: # noqa: BLE001
|
||||
logger.exception(f"Error getting flow {field_value}")
|
||||
await logger.aexception(f"Error getting flow {field_value}")
|
||||
else:
|
||||
if not flow_data:
|
||||
msg = f"Flow {field_value} not found."
|
||||
logger.error(msg)
|
||||
await logger.aerror(msg)
|
||||
else:
|
||||
try:
|
||||
graph = Graph.from_payload(flow_data.data["data"])
|
||||
|
|
@ -60,7 +59,7 @@ class SubFlowComponent(CustomComponent):
|
|||
# Add inputs to the build config
|
||||
build_config = self.add_inputs_to_build_config(inputs, build_config)
|
||||
except Exception: # noqa: BLE001
|
||||
logger.exception(f"Error building graph for flow {field_value}")
|
||||
await logger.aexception(f"Error building graph for flow {field_value}")
|
||||
|
||||
return build_config
|
||||
|
||||
|
|
@ -121,5 +120,5 @@ class SubFlowComponent(CustomComponent):
|
|||
data.extend(build_data_from_result_data(output))
|
||||
|
||||
self.status = data
|
||||
logger.debug(data)
|
||||
await logger.adebug(data)
|
||||
return data
|
||||
|
|
|
|||
|
|
@ -68,9 +68,9 @@ class VectaraSelfQueryRetriverComponent(CustomComponent):
|
|||
metadata_field_obj.append(attribute_info)
|
||||
|
||||
return SelfQueryRetriever.from_llm(
|
||||
self.llm, # noqa: ignore[attr-defined]
|
||||
self.vectorstore, # noqa: ignore[attr-defined]
|
||||
self.document_content_description, # noqa: ignore[attr-defined]
|
||||
self.llm, # type: ignore[attr-defined]
|
||||
self.vectorstore, # type: ignore[attr-defined]
|
||||
self.document_content_description, # type: ignore[attr-defined]
|
||||
metadata_field_obj,
|
||||
verbose=True,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import logging
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.io import HandleInput, MessageInput, Output
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
|
@ -57,8 +57,8 @@ class TextEmbedderComponent(Component):
|
|||
embedding_vector = embeddings[0]
|
||||
self.status = {"text": text_content, "embeddings": embedding_vector}
|
||||
return Data(data={"text": text_content, "embeddings": embedding_vector})
|
||||
except Exception as e:
|
||||
logging.exception("Error generating embeddings")
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.exception("Error generating embeddings")
|
||||
error_data = Data(data={"text": "", "embeddings": [], "error": str(e)})
|
||||
self.status = {"error": str(e)}
|
||||
return error_data
|
||||
|
|
|
|||
|
|
@ -1,13 +1,6 @@
|
|||
from loguru import logger
|
||||
|
||||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.io import (
|
||||
BoolInput,
|
||||
DataInput,
|
||||
MultilineInput,
|
||||
Output,
|
||||
SecretStrInput,
|
||||
)
|
||||
from langflow.io import BoolInput, DataInput, MultilineInput, Output, SecretStrInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@ from googleapiclient.discovery import build
|
|||
from langchain_core.chat_sessions import ChatSession
|
||||
from langchain_core.messages import HumanMessage
|
||||
from langchain_google_community.gmail.loader import GMailLoader
|
||||
from loguru import logger
|
||||
|
||||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.inputs.inputs import MessageTextInput
|
||||
from langflow.io import SecretStrInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
from langflow.template.field.base import Output
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +1,14 @@
|
|||
from typing import Any
|
||||
|
||||
import requests
|
||||
from loguru import logger
|
||||
from pydantic.v1 import SecretStr
|
||||
|
||||
from langflow.base.models.google_generative_ai_constants import GOOGLE_GENERATIVE_AI_MODELS
|
||||
from langflow.base.models.model import LCModelComponent
|
||||
from langflow.field_typing import LanguageModel
|
||||
from langflow.field_typing.range_spec import RangeSpec
|
||||
from langflow.inputs.inputs import (
|
||||
BoolInput,
|
||||
DropdownInput,
|
||||
FloatInput,
|
||||
IntInput,
|
||||
SecretStrInput,
|
||||
SliderInput,
|
||||
)
|
||||
from langflow.inputs.inputs import BoolInput, DropdownInput, FloatInput, IntInput, SecretStrInput, SliderInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.dotdict import dotdict
|
||||
|
||||
|
||||
|
|
@ -105,7 +98,7 @@ class GoogleGenerativeAIComponent(LCModelComponent):
|
|||
google_api_key=SecretStr(google_api_key).get_secret_value(),
|
||||
)
|
||||
|
||||
def get_models(self, tool_model_enabled: bool | None = None) -> list[str]:
|
||||
def get_models(self, *, tool_model_enabled: bool | None = None) -> list[str]:
|
||||
try:
|
||||
import google.generativeai as genai
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import requests
|
||||
from loguru import logger
|
||||
from pydantic.v1 import SecretStr
|
||||
|
||||
from langflow.base.models.groq_constants import (
|
||||
|
|
@ -11,6 +10,7 @@ from langflow.base.models.model import LCModelComponent
|
|||
from langflow.field_typing import LanguageModel
|
||||
from langflow.field_typing.range_spec import RangeSpec
|
||||
from langflow.io import BoolInput, DropdownInput, IntInput, MessageTextInput, SecretStrInput, SliderInput
|
||||
from langflow.logging.logger import logger
|
||||
|
||||
|
||||
class GroqModel(LCModelComponent):
|
||||
|
|
@ -74,7 +74,7 @@ class GroqModel(LCModelComponent):
|
|||
),
|
||||
]
|
||||
|
||||
def get_models(self, tool_model_enabled: bool | None = None) -> list[str]:
|
||||
def get_models(self, *, tool_model_enabled: bool | None = None) -> list[str]:
|
||||
try:
|
||||
url = f"{self.base_url}/openai/v1/models"
|
||||
headers = {"Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json"}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
from datetime import datetime
|
||||
from zoneinfo import ZoneInfo, available_timezones
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.io import DropdownInput, Output
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.message import Message
|
||||
|
||||
|
||||
|
|
@ -37,7 +36,7 @@ class CurrentDateComponent(Component):
|
|||
self.status = result
|
||||
return Message(text=result)
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.opt(exception=True).debug("Error getting current date")
|
||||
logger.debug("Error getting current date", exc_info=True)
|
||||
error_message = f"Error: {e}"
|
||||
self.status = error_message
|
||||
return Message(text=error_message)
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ class MemoryComponent(Component):
|
|||
stored = stored[-n_messages:] if order == "ASC" else stored[:n_messages]
|
||||
|
||||
# self.status = stored
|
||||
return cast(Data, stored)
|
||||
return cast("Data", stored)
|
||||
|
||||
async def retrieve_messages_as_text(self) -> Message:
|
||||
stored_text = data_to_text(self.template, await self.retrieve_messages())
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@ from typing import Any
|
|||
|
||||
import requests
|
||||
from langchain_ibm import ChatWatsonx
|
||||
from loguru import logger
|
||||
from pydantic.v1 import SecretStr
|
||||
|
||||
from langflow.base.models.model import LCModelComponent
|
||||
from langflow.field_typing import LanguageModel
|
||||
from langflow.field_typing.range_spec import RangeSpec
|
||||
from langflow.inputs.inputs import BoolInput, DropdownInput, IntInput, SecretStrInput, SliderInput, StrInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.dotdict import dotdict
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ import requests
|
|||
from ibm_watsonx_ai import APIClient, Credentials
|
||||
from ibm_watsonx_ai.metanames import EmbedTextParamsMetaNames
|
||||
from langchain_ibm import WatsonxEmbeddings
|
||||
from loguru import logger
|
||||
from pydantic.v1 import SecretStr
|
||||
|
||||
from langflow.base.embeddings.model import LCEmbeddingsModel
|
||||
from langflow.field_typing import Embeddings
|
||||
from langflow.io import BoolInput, DropdownInput, IntInput, SecretStrInput, StrInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.dotdict import dotdict
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import os
|
|||
from typing import Any
|
||||
|
||||
import httpx
|
||||
from loguru import logger
|
||||
|
||||
from langflow.base.langwatch.utils import get_cached_evaluators
|
||||
from langflow.custom.custom_component.component import Component
|
||||
|
|
@ -18,6 +17,7 @@ from langflow.io import (
|
|||
Output,
|
||||
SecretStrInput,
|
||||
)
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
from langflow.schema.dotdict import dotdict
|
||||
|
||||
|
|
@ -226,7 +226,7 @@ class LangWatchComponent(Component):
|
|||
if not evaluator_name:
|
||||
if self.evaluators:
|
||||
evaluator_name = next(iter(self.evaluators))
|
||||
logger.info(f"No evaluator was selected. Using default: {evaluator_name}")
|
||||
await logger.ainfo(f"No evaluator was selected. Using default: {evaluator_name}")
|
||||
else:
|
||||
return Data(
|
||||
data={"error": "No evaluator selected and no evaluators available. Please choose an evaluator."}
|
||||
|
|
@ -237,7 +237,7 @@ class LangWatchComponent(Component):
|
|||
if not evaluator:
|
||||
return Data(data={"error": f"Selected evaluator '{evaluator_name}' not found."})
|
||||
|
||||
logger.info(f"Evaluating with evaluator: {evaluator_name}")
|
||||
await logger.ainfo(f"Evaluating with evaluator: {evaluator_name}")
|
||||
|
||||
endpoint = f"/api/evaluations/{evaluator_name}/evaluate"
|
||||
url = f"{os.getenv('LANGWATCH_ENDPOINT', 'https://app.langwatch.ai')}{endpoint}"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
from typing import Any
|
||||
|
||||
from loguru import logger
|
||||
from typing_extensions import override
|
||||
|
||||
from langflow.base.langchain_utilities.model import LCToolComponent
|
||||
|
|
@ -9,6 +8,7 @@ from langflow.field_typing import Tool
|
|||
from langflow.graph.graph.base import Graph
|
||||
from langflow.helpers.flow import get_flow_inputs
|
||||
from langflow.io import BoolInput, DropdownInput, Output, StrInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
from langflow.schema.dotdict import dotdict
|
||||
|
||||
|
|
@ -91,7 +91,7 @@ class FlowToolComponent(LCToolComponent):
|
|||
try:
|
||||
graph.set_run_id(self.graph.run_id)
|
||||
except Exception: # noqa: BLE001
|
||||
logger.opt(exception=True).warning("Failed to set run_id")
|
||||
logger.warning("Failed to set run_id", exc_info=True)
|
||||
inputs = get_flow_inputs(graph)
|
||||
tool_description = self.tool_description.strip() or flow_data.description
|
||||
tool = FlowTool(
|
||||
|
|
|
|||
|
|
@ -85,4 +85,4 @@ class NotifyComponent(Component):
|
|||
self.status = "No record provided."
|
||||
self._vertex.is_state = True
|
||||
self.graph.activate_state_vertices(name=self.context_key, caller=self._id)
|
||||
return cast(Data, input_value)
|
||||
return cast("Data", input_value)
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
from typing import Any
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from langflow.base.tools.run_flow import RunFlowBaseComponent
|
||||
from langflow.helpers.flow import run_flow
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.dotdict import dotdict
|
||||
|
||||
|
||||
|
|
@ -34,7 +33,7 @@ class RunFlowComponent(RunFlowBaseComponent):
|
|||
build_config = self.update_build_config_from_graph(build_config, graph)
|
||||
except Exception as e:
|
||||
msg = f"Error building graph for flow {field_value}"
|
||||
logger.exception(msg)
|
||||
await logger.aexception(msg)
|
||||
raise RuntimeError(msg) from e
|
||||
return build_config
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
from typing import Any
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from langflow.base.flow_processing.utils import build_data_from_result_data
|
||||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.graph.graph.base import Graph
|
||||
from langflow.graph.vertex.base import Vertex
|
||||
from langflow.helpers.flow import get_flow_inputs
|
||||
from langflow.io import DropdownInput, Output
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
from langflow.schema.dotdict import dotdict
|
||||
|
||||
|
|
@ -41,11 +40,11 @@ class SubFlowComponent(Component):
|
|||
try:
|
||||
flow_data = await self.get_flow(field_value)
|
||||
except Exception: # noqa: BLE001
|
||||
logger.exception(f"Error getting flow {field_value}")
|
||||
await logger.aexception(f"Error getting flow {field_value}")
|
||||
else:
|
||||
if not flow_data:
|
||||
msg = f"Flow {field_value} not found."
|
||||
logger.error(msg)
|
||||
await logger.aerror(msg)
|
||||
else:
|
||||
try:
|
||||
graph = Graph.from_payload(flow_data.data["data"])
|
||||
|
|
@ -54,7 +53,7 @@ class SubFlowComponent(Component):
|
|||
# Add inputs to the build config
|
||||
build_config = self.add_inputs_to_build_config(inputs, build_config)
|
||||
except Exception: # noqa: BLE001
|
||||
logger.exception(f"Error building graph for flow {field_value}")
|
||||
await logger.aexception(f"Error building graph for flow {field_value}")
|
||||
|
||||
return build_config
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,11 @@
|
|||
import os
|
||||
|
||||
from loguru import logger
|
||||
from mem0 import Memory, MemoryClient
|
||||
|
||||
from langflow.base.memory.model import LCChatMemoryComponent
|
||||
from langflow.inputs.inputs import (
|
||||
DictInput,
|
||||
HandleInput,
|
||||
MessageTextInput,
|
||||
NestedDictInput,
|
||||
SecretStrInput,
|
||||
)
|
||||
from langflow.inputs.inputs import DictInput, HandleInput, MessageTextInput, NestedDictInput, SecretStrInput
|
||||
from langflow.io import Output
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
from typing import Any
|
||||
|
||||
from loguru import logger
|
||||
from requests.exceptions import ConnectionError # noqa: A004
|
||||
from urllib3.exceptions import MaxRetryError, NameResolutionError
|
||||
|
||||
|
|
@ -8,6 +7,7 @@ from langflow.base.models.model import LCModelComponent
|
|||
from langflow.field_typing import LanguageModel
|
||||
from langflow.field_typing.range_spec import RangeSpec
|
||||
from langflow.inputs.inputs import BoolInput, DropdownInput, IntInput, MessageTextInput, SecretStrInput, SliderInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.dotdict import dotdict
|
||||
|
||||
|
||||
|
|
@ -97,7 +97,7 @@ class NVIDIAModelComponent(LCModelComponent):
|
|||
),
|
||||
]
|
||||
|
||||
def get_models(self, tool_model_enabled: bool | None = None) -> list[str]:
|
||||
def get_models(self, *, tool_model_enabled: bool | None = None) -> list[str]:
|
||||
try:
|
||||
from langchain_nvidia_ai_endpoints import ChatNVIDIA
|
||||
except ImportError as e:
|
||||
|
|
@ -114,7 +114,7 @@ class NVIDIAModelComponent(LCModelComponent):
|
|||
def update_build_config(self, build_config: dotdict, _field_value: Any, field_name: str | None = None):
|
||||
if field_name in {"model_name", "tool_model_enabled", "base_url", "api_key"}:
|
||||
try:
|
||||
ids = self.get_models(self.tool_model_enabled)
|
||||
ids = self.get_models(tool_model_enabled=self.tool_model_enabled)
|
||||
build_config["model_name"]["options"] = ids
|
||||
|
||||
if "value" not in build_config["model_name"] or build_config["model_name"]["value"] is None:
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import json
|
||||
|
||||
import httpx
|
||||
from loguru import logger
|
||||
|
||||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.io import MessageTextInput, Output
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
|
||||
|
||||
|
|
@ -83,7 +83,7 @@ class OlivyaComponent(Component):
|
|||
"Content-Type": "application/json",
|
||||
}
|
||||
|
||||
logger.info("Sending POST request with payload: %s", payload)
|
||||
await logger.ainfo("Sending POST request with payload: %s", payload)
|
||||
|
||||
# Send the POST request with a timeout
|
||||
async with httpx.AsyncClient() as client:
|
||||
|
|
@ -97,19 +97,19 @@ class OlivyaComponent(Component):
|
|||
|
||||
# Parse and return the successful response
|
||||
response_data = response.json()
|
||||
logger.info("Request successful: %s", response_data)
|
||||
await logger.ainfo("Request successful: %s", response_data)
|
||||
|
||||
except httpx.HTTPStatusError as http_err:
|
||||
logger.exception("HTTP error occurred")
|
||||
await logger.aexception("HTTP error occurred")
|
||||
response_data = {"error": f"HTTP error occurred: {http_err}", "response_text": response.text}
|
||||
except httpx.RequestError as req_err:
|
||||
logger.exception("Request failed")
|
||||
await logger.aexception("Request failed")
|
||||
response_data = {"error": f"Request failed: {req_err}"}
|
||||
except json.JSONDecodeError as json_err:
|
||||
logger.exception("Response parsing failed")
|
||||
await logger.aexception("Response parsing failed")
|
||||
response_data = {"error": f"Response parsing failed: {json_err}", "raw_response": response.text}
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.exception("An unexpected error occurred")
|
||||
await logger.aexception("An unexpected error occurred")
|
||||
response_data = {"error": f"An unexpected error occurred: {e!s}"}
|
||||
|
||||
# Return the response as part of the output
|
||||
|
|
|
|||
|
|
@ -245,11 +245,13 @@ class ChatOllamaComponent(LCModelComponent):
|
|||
if field_name in {"model_name", "base_url", "tool_model_enabled"}:
|
||||
if await self.is_valid_ollama_url(self.base_url):
|
||||
tool_model_enabled = build_config["tool_model_enabled"].get("value", False) or self.tool_model_enabled
|
||||
build_config["model_name"]["options"] = await self.get_models(self.base_url, tool_model_enabled)
|
||||
build_config["model_name"]["options"] = await self.get_models(
|
||||
self.base_url, tool_model_enabled=tool_model_enabled
|
||||
)
|
||||
elif await self.is_valid_ollama_url(build_config["base_url"].get("value", "")):
|
||||
tool_model_enabled = build_config["tool_model_enabled"].get("value", False) or self.tool_model_enabled
|
||||
build_config["model_name"]["options"] = await self.get_models(
|
||||
build_config["base_url"].get("value", ""), tool_model_enabled
|
||||
build_config["base_url"].get("value", ""), tool_model_enabled=tool_model_enabled
|
||||
)
|
||||
else:
|
||||
build_config["model_name"]["options"] = []
|
||||
|
|
@ -265,7 +267,7 @@ class ChatOllamaComponent(LCModelComponent):
|
|||
|
||||
return build_config
|
||||
|
||||
async def get_models(self, base_url_value: str, tool_model_enabled: bool | None = None) -> list[str]:
|
||||
async def get_models(self, base_url_value: str, *, tool_model_enabled: bool | None = None) -> list[str]:
|
||||
"""Fetches a list of models from the Ollama API that do not have the "embedding" capability.
|
||||
|
||||
Args:
|
||||
|
|
@ -298,13 +300,13 @@ class ChatOllamaComponent(LCModelComponent):
|
|||
models = tags_response.json()
|
||||
if asyncio.iscoroutine(models):
|
||||
models = await models
|
||||
logger.debug(f"Available models: {models}")
|
||||
await logger.adebug(f"Available models: {models}")
|
||||
|
||||
# Filter models that are NOT embedding models
|
||||
model_ids = []
|
||||
for model in models[self.JSON_MODELS_KEY]:
|
||||
model_name = model[self.JSON_NAME_KEY]
|
||||
logger.debug(f"Checking model: {model_name}")
|
||||
await logger.adebug(f"Checking model: {model_name}")
|
||||
|
||||
payload = {"model": model_name}
|
||||
show_response = await client.post(show_url, json=payload)
|
||||
|
|
@ -313,7 +315,7 @@ class ChatOllamaComponent(LCModelComponent):
|
|||
if asyncio.iscoroutine(json_data):
|
||||
json_data = await json_data
|
||||
capabilities = json_data.get(self.JSON_CAPABILITIES_KEY, [])
|
||||
logger.debug(f"Model: {model_name}, Capabilities: {capabilities}")
|
||||
await logger.adebug(f"Model: {model_name}, Capabilities: {capabilities}")
|
||||
|
||||
if self.DESIRED_CAPABILITY in capabilities and (
|
||||
not tool_model_enabled or self.TOOL_CALLING_CAPABILITY in capabilities
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@ from __future__ import annotations
|
|||
from typing import TYPE_CHECKING, Any, cast
|
||||
|
||||
import toml # type: ignore[import-untyped]
|
||||
from loguru import logger
|
||||
|
||||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.io import BoolInput, DataFrameInput, HandleInput, MessageTextInput, MultilineInput, Output
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.dataframe import DataFrame
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
|
@ -144,11 +144,11 @@ class BatchRunComponent(Component):
|
|||
user_texts = df[col_name].astype(str).tolist()
|
||||
else:
|
||||
user_texts = [
|
||||
self._format_row_as_toml(cast(dict[str, Any], row)) for row in df.to_dict(orient="records")
|
||||
self._format_row_as_toml(cast("dict[str, Any]", row)) for row in df.to_dict(orient="records")
|
||||
]
|
||||
|
||||
total_rows = len(user_texts)
|
||||
logger.info(f"Processing {total_rows} rows with batch run")
|
||||
await logger.ainfo(f"Processing {total_rows} rows with batch run")
|
||||
|
||||
# Prepare the batch of conversations
|
||||
conversations = [
|
||||
|
|
@ -185,21 +185,21 @@ class BatchRunComponent(Component):
|
|||
):
|
||||
response_text = response[1].content if hasattr(response[1], "content") else str(response[1])
|
||||
row = self._create_base_row(
|
||||
cast(dict[str, Any], original_row), model_response=response_text, batch_index=idx
|
||||
cast("dict[str, Any]", original_row), model_response=response_text, batch_index=idx
|
||||
)
|
||||
self._add_metadata(row, success=True, system_msg=system_msg)
|
||||
rows.append(row)
|
||||
|
||||
# Log progress
|
||||
if (idx + 1) % max(1, total_rows // 10) == 0:
|
||||
logger.info(f"Processed {idx + 1}/{total_rows} rows")
|
||||
await logger.ainfo(f"Processed {idx + 1}/{total_rows} rows")
|
||||
|
||||
logger.info("Batch processing completed successfully")
|
||||
await logger.ainfo("Batch processing completed successfully")
|
||||
return DataFrame(rows)
|
||||
|
||||
except (KeyError, AttributeError) as e:
|
||||
# Handle data structure and attribute access errors
|
||||
logger.error(f"Data processing error: {e!s}")
|
||||
error_row = self._create_base_row({col: "" for col in df.columns}, model_response="", batch_index=-1)
|
||||
await logger.aerror(f"Data processing error: {e!s}")
|
||||
error_row = self._create_base_row(dict.fromkeys(df.columns, ""), model_response="", batch_index=-1)
|
||||
self._add_metadata(error_row, success=False, error=str(e))
|
||||
return DataFrame([error_row])
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ class DataOperationsComponent(Component):
|
|||
raise ValueError(msg)
|
||||
|
||||
# Data transformation operations
|
||||
def select_keys(self, evaluate: bool | None = None) -> Data:
|
||||
def select_keys(self, *, evaluate: bool | None = None) -> Data:
|
||||
"""Select specific keys from the data dictionary."""
|
||||
self.validate_single_data("Select Keys")
|
||||
data_dict = self.get_normalized_data()
|
||||
|
|
@ -266,7 +266,7 @@ class DataOperationsComponent(Component):
|
|||
logger.info("evaluating data")
|
||||
return Data(**self.recursive_eval(self.get_data_dict()))
|
||||
|
||||
def combine_data(self, evaluate: bool | None = None) -> Data:
|
||||
def combine_data(self, *, evaluate: bool | None = None) -> Data:
|
||||
"""Combine multiple data objects into one."""
|
||||
logger.info("combining data")
|
||||
if not self.data_is_list():
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
from enum import Enum
|
||||
from typing import cast
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.io import DataInput, DropdownInput, Output
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.dataframe import DataFrame
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
from loguru import logger
|
||||
|
||||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.io import MessageInput, Output
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
from langflow.schema.message import Message
|
||||
|
||||
|
|
@ -32,6 +31,6 @@ class MessageToDataComponent(Component):
|
|||
return Data(data=self.message.data)
|
||||
|
||||
msg = "Error converting Message to Data: Input must be a Message object"
|
||||
logger.opt(exception=True).debug(msg)
|
||||
logger.debug(msg, exc_info=True)
|
||||
self.status = msg
|
||||
return Data(data={"error": msg})
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ from json import JSONDecodeError
|
|||
|
||||
import jq
|
||||
from json_repair import repair_json
|
||||
from loguru import logger
|
||||
|
||||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.inputs.inputs import HandleInput, MessageTextInput
|
||||
from langflow.io import Output
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
from langflow.schema.message import Message
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
from collections.abc import Callable
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.custom.utils import get_function
|
||||
from langflow.io import CodeInput, Output
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
from langflow.schema.dotdict import dotdict
|
||||
from langflow.schema.message import Message
|
||||
|
|
@ -58,7 +57,7 @@ class PythonFunctionComponent(Component):
|
|||
func = get_function(function_code)
|
||||
return func()
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.opt(exception=True).debug("Error executing function")
|
||||
logger.debug("Error executing function", exc_info=True)
|
||||
return f"Error executing function: {e}"
|
||||
|
||||
def execute_function_data(self) -> list[Data]:
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@ from typing import Any
|
|||
|
||||
from langchain_community.utilities.serpapi import SerpAPIWrapper
|
||||
from langchain_core.tools import ToolException
|
||||
from loguru import logger
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.inputs.inputs import DictInput, IntInput, MultilineInput, SecretStrInput
|
||||
from langflow.io import Output
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
from langflow.schema.message import Message
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import httpx
|
||||
from loguru import logger
|
||||
|
||||
from langflow.custom import Component
|
||||
from langflow.io import BoolInput, DropdownInput, MessageTextInput, Output, SecretStrInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema import Data
|
||||
from langflow.schema.dataframe import DataFrame
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import httpx
|
||||
from loguru import logger
|
||||
|
||||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.inputs.inputs import BoolInput, DropdownInput, IntInput, MessageTextInput, SecretStrInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
from langflow.schema.dataframe import DataFrame
|
||||
from langflow.template.field.base import Output
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@ import operator
|
|||
|
||||
from langchain.tools import StructuredTool
|
||||
from langchain_core.tools import ToolException
|
||||
from loguru import logger
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from langflow.base.langchain_utilities.model import LCToolComponent
|
||||
from langflow.field_typing import Tool
|
||||
from langflow.inputs.inputs import MessageTextInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
|
||||
|
||||
|
|
@ -87,7 +87,7 @@ class CalculatorToolComponent(LCToolComponent):
|
|||
self.status = error_message
|
||||
return [Data(data={"error": error_message, "input": expression})]
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.opt(exception=True).debug("Error evaluating expression")
|
||||
logger.debug("Error evaluating expression", exc_info=True)
|
||||
error_message = f"Error: {e}"
|
||||
self.status = error_message
|
||||
return [Data(data={"error": error_message, "input": expression})]
|
||||
|
|
|
|||
|
|
@ -4,21 +4,14 @@ from typing import Any
|
|||
|
||||
from langchain.agents import Tool
|
||||
from langchain_core.tools import StructuredTool
|
||||
from loguru import logger
|
||||
from pydantic.v1 import Field, create_model
|
||||
from pydantic.v1.fields import Undefined
|
||||
from typing_extensions import override
|
||||
|
||||
from langflow.base.langchain_utilities.model import LCToolComponent
|
||||
from langflow.inputs.inputs import (
|
||||
BoolInput,
|
||||
DropdownInput,
|
||||
FieldTypes,
|
||||
HandleInput,
|
||||
MessageTextInput,
|
||||
MultilineInput,
|
||||
)
|
||||
from langflow.inputs.inputs import BoolInput, DropdownInput, FieldTypes, HandleInput, MessageTextInput, MultilineInput
|
||||
from langflow.io import Output
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
from langflow.schema.dotdict import dotdict
|
||||
|
||||
|
|
@ -139,7 +132,7 @@ class PythonCodeStructuredTool(LCToolComponent):
|
|||
build_config["tool_function"]["options"] = names
|
||||
except Exception as e: # noqa: BLE001
|
||||
self.status = f"Failed to extract names: {e}"
|
||||
logger.opt(exception=True).debug(self.status)
|
||||
logger.debug(self.status, exc_info=True)
|
||||
build_config["tool_function"]["options"] = ["Failed to parse", str(e)]
|
||||
return build_config
|
||||
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@ import importlib
|
|||
from langchain.tools import StructuredTool
|
||||
from langchain_core.tools import ToolException
|
||||
from langchain_experimental.utilities import PythonREPL
|
||||
from loguru import logger
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from langflow.base.langchain_utilities.model import LCToolComponent
|
||||
from langflow.field_typing import Tool
|
||||
from langflow.inputs.inputs import StrInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ class PythonREPLToolComponent(LCToolComponent):
|
|||
try:
|
||||
return python_repl.run(code)
|
||||
except Exception as e:
|
||||
logger.opt(exception=True).debug("Error running Python code")
|
||||
logger.debug("Error running Python code", exc_info=True)
|
||||
raise ToolException(str(e)) from e
|
||||
|
||||
tool = StructuredTool.from_function(
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@ from typing import Any
|
|||
import requests
|
||||
from langchain.agents import Tool
|
||||
from langchain_core.tools import StructuredTool
|
||||
from loguru import logger
|
||||
from pydantic.v1 import Field, create_model
|
||||
|
||||
from langflow.base.langchain_utilities.model import LCToolComponent
|
||||
from langflow.inputs.inputs import DropdownInput, IntInput, MessageTextInput, MultiselectInput
|
||||
from langflow.io import Output
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.dotdict import dotdict
|
||||
|
||||
|
||||
|
|
@ -76,7 +76,7 @@ class SearXNGToolComponent(LCToolComponent):
|
|||
build_config["language"]["options"] = languages.copy()
|
||||
except Exception as e: # noqa: BLE001
|
||||
self.status = f"Failed to extract names: {e}"
|
||||
logger.opt(exception=True).debug(self.status)
|
||||
logger.debug(self.status, exc_info=True)
|
||||
build_config["categories"]["options"] = ["Failed to parse", str(e)]
|
||||
return build_config
|
||||
|
||||
|
|
@ -112,7 +112,7 @@ class SearXNGToolComponent(LCToolComponent):
|
|||
num_results = min(SearxSearch._max_results, len(response["results"]))
|
||||
return [response["results"][i] for i in range(num_results)]
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.opt(exception=True).debug("Error running SearXNG Search")
|
||||
logger.debug("Error running SearXNG Search", exc_info=True)
|
||||
return [f"Failed to search: {e}"]
|
||||
|
||||
SearxSearch._url = self.url
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@ from typing import Any
|
|||
from langchain.tools import StructuredTool
|
||||
from langchain_community.utilities.serpapi import SerpAPIWrapper
|
||||
from langchain_core.tools import ToolException
|
||||
from loguru import logger
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from langflow.base.langchain_utilities.model import LCToolComponent
|
||||
from langflow.field_typing import Tool
|
||||
from langflow.inputs.inputs import DictInput, IntInput, MultilineInput, SecretStrInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
|
||||
|
||||
|
|
@ -111,7 +111,7 @@ class SerpAPIComponent(LCToolComponent):
|
|||
data_list = [Data(data=result, text=result.get("snippet", "")) for result in results]
|
||||
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.opt(exception=True).debug("Error running SerpAPI")
|
||||
logger.debug("Error running SerpAPI", exc_info=True)
|
||||
self.status = f"Error: {e}"
|
||||
return [Data(data={"error": str(e)}, text=str(e))]
|
||||
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@ from enum import Enum
|
|||
import httpx
|
||||
from langchain.tools import StructuredTool
|
||||
from langchain_core.tools import ToolException
|
||||
from loguru import logger
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from langflow.base.langchain_utilities.model import LCToolComponent
|
||||
from langflow.field_typing import Tool
|
||||
from langflow.inputs.inputs import BoolInput, DropdownInput, IntInput, MessageTextInput, SecretStrInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
|
||||
# Add at the top with other constants
|
||||
|
|
@ -338,7 +338,7 @@ Note: Check 'Advanced' for all options.
|
|||
raise ToolException(error_message) from e
|
||||
except Exception as e:
|
||||
error_message = f"Unexpected error: {e}"
|
||||
logger.opt(exception=True).debug("Error running Tavily Search")
|
||||
logger.debug("Error running Tavily Search", exc_info=True)
|
||||
self.status = error_message
|
||||
raise ToolException(error_message) from e
|
||||
return data_results
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@ from enum import Enum
|
|||
import yfinance as yf
|
||||
from langchain.tools import StructuredTool
|
||||
from langchain_core.tools import ToolException
|
||||
from loguru import logger
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from langflow.base.langchain_utilities.model import LCToolComponent
|
||||
from langflow.field_typing import Tool
|
||||
from langflow.inputs.inputs import DropdownInput, IntInput, MessageTextInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -29,9 +29,9 @@ class TwelveLabsVideoEmbeddings(Embeddings):
|
|||
|
||||
# First try to use video embedding, then fall back to clip embedding if available
|
||||
if result["video_embedding"] is not None:
|
||||
embeddings.append(cast(list[float], result["video_embedding"]))
|
||||
embeddings.append(cast("list[float]", result["video_embedding"]))
|
||||
elif result["clip_embeddings"] and len(result["clip_embeddings"]) > 0:
|
||||
embeddings.append(cast(list[float], result["clip_embeddings"][0]))
|
||||
embeddings.append(cast("list[float]", result["clip_embeddings"][0]))
|
||||
else:
|
||||
# If neither is available, raise an error
|
||||
error_msg = "No embeddings were generated for the video"
|
||||
|
|
@ -45,9 +45,9 @@ class TwelveLabsVideoEmbeddings(Embeddings):
|
|||
|
||||
# First try to use video embedding, then fall back to clip embedding if available
|
||||
if result["video_embedding"] is not None:
|
||||
return cast(list[float], result["video_embedding"])
|
||||
return cast("list[float]", result["video_embedding"])
|
||||
if result["clip_embeddings"] and len(result["clip_embeddings"]) > 0:
|
||||
return cast(list[float], result["clip_embeddings"][0])
|
||||
return cast("list[float]", result["clip_embeddings"][0])
|
||||
# If neither is available, raise an error
|
||||
error_msg = "No embeddings were generated for the video"
|
||||
raise ValueError(error_msg)
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@ from copy import deepcopy
|
|||
from pathlib import Path
|
||||
|
||||
from langchain_chroma import Chroma
|
||||
from loguru import logger
|
||||
from typing_extensions import override
|
||||
|
||||
from langflow.base.vectorstores.model import LCVectorStoreComponent, check_cached_vector_store
|
||||
from langflow.base.vectorstores.utils import chroma_collection_to_data
|
||||
from langflow.inputs.inputs import MultilineInput
|
||||
from langflow.io import BoolInput, DropdownInput, HandleInput, IntInput, MessageTextInput, TabInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
from langflow.schema.dataframe import DataFrame
|
||||
from langflow.template.field.base import Output
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ from enum import Enum
|
|||
|
||||
import yfinance as yf
|
||||
from langchain_core.tools import ToolException
|
||||
from loguru import logger
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.inputs.inputs import DropdownInput, IntInput, MessageTextInput
|
||||
from langflow.io import Output
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
from langflow.schema.dataframe import DataFrame
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ from googleapiclient.errors import HttpError
|
|||
|
||||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.inputs.inputs import BoolInput, DropdownInput, IntInput, SecretStrInput
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.dataframe import DataFrame
|
||||
from langflow.template.field.base import Output
|
||||
|
||||
|
|
@ -279,8 +280,6 @@ class YouTubeTrendingComponent(Component):
|
|||
|
||||
return DataFrame(pd.DataFrame({"error": [error_message]}))
|
||||
|
||||
except Exception as e:
|
||||
import logging
|
||||
|
||||
logging.exception("An unexpected error occurred:")
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.exception("An unexpected error occurred:")
|
||||
return DataFrame(pd.DataFrame({"error": [str(e)]}))
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
from collections.abc import Callable
|
||||
|
||||
import emoji
|
||||
from loguru import logger
|
||||
|
||||
from langflow.logging.logger import logger
|
||||
|
||||
|
||||
def validate_icon(value: str):
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@ from typing import Any
|
|||
|
||||
from cachetools import TTLCache, keys
|
||||
from fastapi import HTTPException
|
||||
from loguru import logger
|
||||
|
||||
from langflow.custom.eval import eval_custom_component_code
|
||||
from langflow.custom.schema import CallableCodeDetails, ClassCodeDetails, MissingDefault
|
||||
from langflow.logging.logger import logger
|
||||
|
||||
|
||||
class CodeSyntaxError(HTTPException):
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@ from typing import TYPE_CHECKING, Any, ClassVar
|
|||
|
||||
from cachetools import TTLCache, cachedmethod
|
||||
from fastapi import HTTPException
|
||||
from loguru import logger
|
||||
|
||||
from langflow.custom.attributes import ATTR_FUNC_MAPPING
|
||||
from langflow.custom.code_parser.code_parser import CodeParser
|
||||
from langflow.custom.eval import eval_custom_component_code
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.utils import validate
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ from pathlib import Path
|
|||
|
||||
import anyio
|
||||
from aiofile import async_open
|
||||
from loguru import logger
|
||||
|
||||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.logging.logger import logger
|
||||
|
||||
MAX_DEPTH = 2
|
||||
|
||||
|
|
@ -255,7 +255,7 @@ class DirectoryReader:
|
|||
try:
|
||||
output_types = self.get_output_types_from_code(result_content)
|
||||
except Exception: # noqa: BLE001
|
||||
logger.opt(exception=True).debug("Error while getting output types from code")
|
||||
logger.debug("Error while getting output types from code", exc_info=True)
|
||||
output_types = [component_name_camelcase]
|
||||
else:
|
||||
output_types = [component_name_camelcase]
|
||||
|
|
@ -278,7 +278,7 @@ class DirectoryReader:
|
|||
try:
|
||||
file_content = await self.aread_file_content(file_path)
|
||||
except Exception: # noqa: BLE001
|
||||
logger.exception(f"Error while reading file {file_path}")
|
||||
await logger.aexception(f"Error while reading file {file_path}")
|
||||
return False, f"Could not read {file_path}"
|
||||
|
||||
if file_content is None:
|
||||
|
|
@ -300,7 +300,7 @@ class DirectoryReader:
|
|||
|
||||
async def abuild_component_menu_list(self, file_paths):
|
||||
response = {"menu": []}
|
||||
logger.debug("-------------------- Async Building component menu list --------------------")
|
||||
await logger.adebug("-------------------- Async Building component menu list --------------------")
|
||||
|
||||
tasks = [self.process_file_async(file_path) for file_path in file_paths]
|
||||
results = await asyncio.gather(*tasks)
|
||||
|
|
@ -311,7 +311,7 @@ class DirectoryReader:
|
|||
filename = file_path_.name
|
||||
|
||||
if not validation_result:
|
||||
logger.error(f"Error while processing file {file_path}")
|
||||
await logger.aerror(f"Error while processing file {file_path}")
|
||||
|
||||
menu_result = self.find_menu(response, menu_name) or {
|
||||
"name": menu_name,
|
||||
|
|
@ -329,7 +329,7 @@ class DirectoryReader:
|
|||
try:
|
||||
output_types = await asyncio.to_thread(self.get_output_types_from_code, result_content)
|
||||
except Exception: # noqa: BLE001
|
||||
logger.exception("Error while getting output types from code")
|
||||
await logger.aexception("Error while getting output types from code")
|
||||
output_types = [component_name_camelcase]
|
||||
else:
|
||||
output_types = [component_name_camelcase]
|
||||
|
|
@ -346,7 +346,7 @@ class DirectoryReader:
|
|||
if menu_result not in response["menu"]:
|
||||
response["menu"].append(menu_result)
|
||||
|
||||
logger.debug("-------------------- Component menu list built --------------------")
|
||||
await logger.adebug("-------------------- Component menu list built --------------------")
|
||||
return response
|
||||
|
||||
@staticmethod
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import asyncio
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from langflow.custom.directory_reader.directory_reader import DirectoryReader
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.template.frontend_node.custom_components import CustomComponentFrontendNode
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ from typing import Any
|
|||
from uuid import UUID
|
||||
|
||||
from fastapi import HTTPException
|
||||
from loguru import logger
|
||||
from pydantic import BaseModel
|
||||
|
||||
from langflow.custom.custom_component.component import Component
|
||||
|
|
@ -25,6 +24,7 @@ from langflow.custom.eval import eval_custom_component_code
|
|||
from langflow.custom.schema import MissingDefault
|
||||
from langflow.field_typing.range_spec import RangeSpec
|
||||
from langflow.helpers.custom import format_type
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.dotdict import dotdict
|
||||
from langflow.template.field.base import Input
|
||||
from langflow.template.frontend_node.custom_components import ComponentFrontendNode, CustomComponentFrontendNode
|
||||
|
|
@ -500,7 +500,7 @@ def build_custom_component_template_from_inputs(
|
|||
if code_hash:
|
||||
frontend_node.metadata["code_hash"] = code_hash
|
||||
except Exception as exc: # noqa: BLE001
|
||||
logger.opt(exception=exc).debug(f"Error generating code hash for {custom_component.__class__.__name__}")
|
||||
logger.debug(f"Error generating code hash for {custom_component.__class__.__name__}", exc_info=exc)
|
||||
|
||||
return frontend_node.to_dict(keep_name=False), cc_instance
|
||||
|
||||
|
|
@ -573,7 +573,7 @@ def build_custom_component_template(
|
|||
if code_hash:
|
||||
frontend_node.metadata["code_hash"] = code_hash
|
||||
except Exception as exc: # noqa: BLE001
|
||||
logger.opt(exception=exc).debug(f"Error generating code hash for {custom_component.__class__.__name__}")
|
||||
logger.debug(f"Error generating code hash for {custom_component.__class__.__name__}", exc_info=exc)
|
||||
|
||||
return frontend_node.to_dict(keep_name=False), custom_instance
|
||||
except Exception as exc:
|
||||
|
|
@ -646,7 +646,7 @@ async def abuild_custom_components(components_paths: list[str]):
|
|||
if not components_paths:
|
||||
return {}
|
||||
|
||||
logger.debug(f"Building custom components from {components_paths}")
|
||||
await logger.adebug(f"Building custom components from {components_paths}")
|
||||
custom_components_from_file: dict = {}
|
||||
processed_paths = set()
|
||||
for path in components_paths:
|
||||
|
|
@ -657,7 +657,7 @@ async def abuild_custom_components(components_paths: list[str]):
|
|||
custom_component_dict = await abuild_custom_component_list_from_path(path_str)
|
||||
if custom_component_dict:
|
||||
category = next(iter(custom_component_dict))
|
||||
logger.debug(f"Loading {len(custom_component_dict[category])} component(s) from category {category}")
|
||||
await logger.adebug(f"Loading {len(custom_component_dict[category])} component(s) from category {category}")
|
||||
custom_components_from_file = merge_nested_dicts_with_renaming(
|
||||
custom_components_from_file, custom_component_dict
|
||||
)
|
||||
|
|
@ -745,18 +745,18 @@ async def get_single_component_dict(component_type: str, component_name: str, co
|
|||
if hasattr(module, "template"):
|
||||
return module.template
|
||||
except ImportError as e:
|
||||
logger.error(f"Import error loading component {module_path}: {e!s}")
|
||||
await logger.aerror(f"Import error loading component {module_path}: {e!s}")
|
||||
except AttributeError as e:
|
||||
logger.error(f"Attribute error loading component {module_path}: {e!s}")
|
||||
await logger.aerror(f"Attribute error loading component {module_path}: {e!s}")
|
||||
except ValueError as e:
|
||||
logger.error(f"Value error loading component {module_path}: {e!s}")
|
||||
await logger.aerror(f"Value error loading component {module_path}: {e!s}")
|
||||
except (KeyError, IndexError) as e:
|
||||
logger.error(f"Data structure error loading component {module_path}: {e!s}")
|
||||
await logger.aerror(f"Data structure error loading component {module_path}: {e!s}")
|
||||
except RuntimeError as e:
|
||||
logger.error(f"Runtime error loading component {module_path}: {e!s}")
|
||||
logger.debug("Full traceback for runtime error", exc_info=True)
|
||||
await logger.aerror(f"Runtime error loading component {module_path}: {e!s}")
|
||||
await logger.adebug("Full traceback for runtime error", exc_info=True)
|
||||
except OSError as e:
|
||||
logger.error(f"OS error loading component {module_path}: {e!s}")
|
||||
await logger.aerror(f"OS error loading component {module_path}: {e!s}")
|
||||
|
||||
# If we get here, the component wasn't found or couldn't be loaded
|
||||
return None
|
||||
|
|
@ -811,43 +811,43 @@ async def load_custom_component(component_name: str, components_paths: list[str]
|
|||
if hasattr(module, "get_template"):
|
||||
return module.get_template()
|
||||
except ImportError as e:
|
||||
logger.error(f"Import error loading component {component_file}: {e!s}")
|
||||
logger.debug("Import error traceback", exc_info=True)
|
||||
await logger.aerror(f"Import error loading component {component_file}: {e!s}")
|
||||
await logger.adebug("Import error traceback", exc_info=True)
|
||||
except AttributeError as e:
|
||||
logger.error(f"Attribute error loading component {component_file}: {e!s}")
|
||||
logger.debug("Attribute error traceback", exc_info=True)
|
||||
await logger.aerror(f"Attribute error loading component {component_file}: {e!s}")
|
||||
await logger.adebug("Attribute error traceback", exc_info=True)
|
||||
except (ValueError, TypeError) as e:
|
||||
logger.error(f"Value/Type error loading component {component_file}: {e!s}")
|
||||
logger.debug("Value/Type error traceback", exc_info=True)
|
||||
await logger.aerror(f"Value/Type error loading component {component_file}: {e!s}")
|
||||
await logger.adebug("Value/Type error traceback", exc_info=True)
|
||||
except (KeyError, IndexError) as e:
|
||||
logger.error(f"Data structure error loading component {component_file}: {e!s}")
|
||||
logger.debug("Data structure error traceback", exc_info=True)
|
||||
await logger.aerror(f"Data structure error loading component {component_file}: {e!s}")
|
||||
await logger.adebug("Data structure error traceback", exc_info=True)
|
||||
except RuntimeError as e:
|
||||
logger.error(f"Runtime error loading component {component_file}: {e!s}")
|
||||
logger.debug("Runtime error traceback", exc_info=True)
|
||||
await logger.aerror(f"Runtime error loading component {component_file}: {e!s}")
|
||||
await logger.adebug("Runtime error traceback", exc_info=True)
|
||||
except OSError as e:
|
||||
logger.error(f"OS error loading component {component_file}: {e!s}")
|
||||
logger.debug("OS error traceback", exc_info=True)
|
||||
await logger.aerror(f"OS error loading component {component_file}: {e!s}")
|
||||
await logger.adebug("OS error traceback", exc_info=True)
|
||||
|
||||
except ImportError as e:
|
||||
logger.error(f"Import error loading custom component {component_name}: {e!s}")
|
||||
await logger.aerror(f"Import error loading custom component {component_name}: {e!s}")
|
||||
return None
|
||||
except AttributeError as e:
|
||||
logger.error(f"Attribute error loading custom component {component_name}: {e!s}")
|
||||
await logger.aerror(f"Attribute error loading custom component {component_name}: {e!s}")
|
||||
return None
|
||||
except ValueError as e:
|
||||
logger.error(f"Value error loading custom component {component_name}: {e!s}")
|
||||
await logger.aerror(f"Value error loading custom component {component_name}: {e!s}")
|
||||
return None
|
||||
except (KeyError, IndexError) as e:
|
||||
logger.error(f"Data structure error loading custom component {component_name}: {e!s}")
|
||||
await logger.aerror(f"Data structure error loading custom component {component_name}: {e!s}")
|
||||
return None
|
||||
except RuntimeError as e:
|
||||
logger.error(f"Runtime error loading custom component {component_name}: {e!s}")
|
||||
await logger.aerror(f"Runtime error loading custom component {component_name}: {e!s}")
|
||||
logger.debug("Full traceback for runtime error", exc_info=True)
|
||||
return None
|
||||
|
||||
# If we get here, the component wasn't found in any of the paths
|
||||
logger.warning(f"Component {component_name} not found in any of the provided paths")
|
||||
await logger.awarning(f"Component {component_name} not found in any of the provided paths")
|
||||
return None
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ from functools import partial
|
|||
from typing import TYPE_CHECKING
|
||||
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from loguru import logger
|
||||
from typing_extensions import Protocol
|
||||
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.playground_events import create_event_by_type
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
|
|
|||
|
|
@ -2,9 +2,8 @@ from __future__ import annotations
|
|||
|
||||
from typing import TYPE_CHECKING, Any, cast
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from langflow.graph.edge.schema import EdgeData, LoopTargetHandleDict, SourceHandle, TargetHandle, TargetHandleDict
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.schema import INPUT_FIELD_NAME
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
|
@ -28,7 +27,7 @@ class Edge:
|
|||
try:
|
||||
if "name" in self._target_handle:
|
||||
self.target_handle: TargetHandle = TargetHandle.from_loop_target_handle(
|
||||
cast(LoopTargetHandleDict, self._target_handle)
|
||||
cast("LoopTargetHandleDict", self._target_handle)
|
||||
)
|
||||
else:
|
||||
self.target_handle = TargetHandle(**self._target_handle)
|
||||
|
|
|
|||
|
|
@ -15,8 +15,6 @@ from functools import partial
|
|||
from itertools import chain
|
||||
from typing import TYPE_CHECKING, Any, cast
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from langflow.exceptions.component import ComponentBuildError
|
||||
from langflow.graph.edge.base import CycleEdge, Edge
|
||||
from langflow.graph.graph.constants import Finish, lazy_load_vertex_dict
|
||||
|
|
@ -36,7 +34,7 @@ from langflow.graph.utils import log_vertex_build
|
|||
from langflow.graph.vertex.base import Vertex, VertexStates
|
||||
from langflow.graph.vertex.schema import NodeData, NodeTypeEnum
|
||||
from langflow.graph.vertex.vertex_types import ComponentVertex, InterfaceVertex, StateVertex
|
||||
from langflow.logging.logger import LogConfig, configure
|
||||
from langflow.logging.logger import LogConfig, configure, logger
|
||||
from langflow.schema.dotdict import dotdict
|
||||
from langflow.schema.schema import INPUT_FIELD_NAME, InputType, OutputValue
|
||||
from langflow.services.cache.utils import CacheMiss
|
||||
|
|
@ -848,7 +846,7 @@ class Graph:
|
|||
event_manager=event_manager,
|
||||
)
|
||||
run_output_object = RunOutputs(inputs=run_inputs, outputs=run_outputs)
|
||||
logger.debug(f"Run outputs: {run_output_object}")
|
||||
await logger.adebug(f"Run outputs: {run_output_object}")
|
||||
vertex_outputs.append(run_output_object)
|
||||
return vertex_outputs
|
||||
|
||||
|
|
@ -1449,7 +1447,7 @@ class Graph:
|
|||
if vertex.result is not None:
|
||||
vertex.result.used_frozen_result = True
|
||||
except Exception: # noqa: BLE001
|
||||
logger.opt(exception=True).debug("Error finalizing build")
|
||||
logger.debug("Error finalizing build", exc_info=True)
|
||||
should_build = True
|
||||
except KeyError:
|
||||
should_build = True
|
||||
|
|
@ -1476,7 +1474,7 @@ class Graph:
|
|||
|
||||
except Exception as exc:
|
||||
if not isinstance(exc, ComponentBuildError):
|
||||
logger.exception("Error building Component")
|
||||
await logger.aexception("Error building Component")
|
||||
raise
|
||||
|
||||
if vertex.result is not None:
|
||||
|
|
@ -1557,20 +1555,20 @@ class Graph:
|
|||
tasks.append(task)
|
||||
vertex_task_run_count[vertex_id] = vertex_task_run_count.get(vertex_id, 0) + 1
|
||||
|
||||
logger.debug(f"Running layer {layer_index} with {len(tasks)} tasks, {current_batch}")
|
||||
await logger.adebug(f"Running layer {layer_index} with {len(tasks)} tasks, {current_batch}")
|
||||
try:
|
||||
next_runnable_vertices = await self._execute_tasks(
|
||||
tasks, lock=lock, has_webhook_component=has_webhook_component
|
||||
)
|
||||
except Exception:
|
||||
logger.exception(f"Error executing tasks in layer {layer_index}")
|
||||
await logger.aexception(f"Error executing tasks in layer {layer_index}")
|
||||
raise
|
||||
if not next_runnable_vertices:
|
||||
break
|
||||
to_process.extend(next_runnable_vertices)
|
||||
layer_index += 1
|
||||
|
||||
logger.debug("Graph processing complete")
|
||||
await logger.adebug("Graph processing complete")
|
||||
return self
|
||||
|
||||
def find_next_runnable_vertices(self, vertex_successors_ids: list[str]) -> list[str]:
|
||||
|
|
@ -1634,7 +1632,7 @@ class Graph:
|
|||
from langflow.api.utils import format_exception_message
|
||||
|
||||
tb = traceback.format_exc()
|
||||
logger.exception("Error building Component")
|
||||
await logger.aexception("Error building Component")
|
||||
|
||||
params = format_exception_message(result)
|
||||
message = {"errorMessage": params, "stackTrace": tb}
|
||||
|
|
@ -1680,7 +1678,7 @@ class Graph:
|
|||
vertex_id = tasks[i].get_name().split(" ")[0]
|
||||
|
||||
if isinstance(result, Exception):
|
||||
logger.error(f"Task {task_name} failed with exception: {result}")
|
||||
await logger.aerror(f"Task {task_name} failed with exception: {result}")
|
||||
if has_webhook_component:
|
||||
await self._log_vertex_build_from_exception(vertex_id, result)
|
||||
|
||||
|
|
@ -1710,7 +1708,7 @@ class Graph:
|
|||
# This could usually happen with input vertices like ChatInput
|
||||
self.run_manager.remove_vertex_from_runnables(v.id)
|
||||
|
||||
logger.debug(f"Vertex {v.id}, result: {v.built_result}, object: {v.built_object}")
|
||||
await logger.adebug(f"Vertex {v.id}, result: {v.built_result}, object: {v.built_object}")
|
||||
|
||||
for v in vertices:
|
||||
next_runnable_vertices = await self.get_next_runnable_vertices(lock, vertex=v, cache=False)
|
||||
|
|
@ -1996,6 +1994,10 @@ class Graph:
|
|||
f"{edges_repr}"
|
||||
)
|
||||
|
||||
def __hash__(self) -> int:
|
||||
"""Return hash of the graph based on its string representation."""
|
||||
return hash(self.__repr__())
|
||||
|
||||
def get_vertex_predecessors_ids(self, vertex_id: str) -> list[str]:
|
||||
"""Get the predecessor IDs of a vertex."""
|
||||
return [v.id for v in self.get_predecessors(self.get_vertex(vertex_id))]
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@ class Finish:
|
|||
def __eq__(self, /, other):
|
||||
return isinstance(other, Finish)
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return hash(type(self))
|
||||
|
||||
|
||||
def _import_vertex_types():
|
||||
from langflow.graph.vertex import vertex_types
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ from typing import TYPE_CHECKING, Any
|
|||
from uuid import UUID
|
||||
|
||||
import pandas as pd
|
||||
from loguru import logger
|
||||
|
||||
from langflow.interface.utils import extract_input_variables_from_prompt
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.data import Data
|
||||
from langflow.schema.message import Message
|
||||
from langflow.serialization.serialization import get_max_items_length, get_max_text_length, serialize
|
||||
|
|
@ -141,7 +141,7 @@ async def log_transaction(
|
|||
result_dict[key] = value.to_dict()
|
||||
outputs = result_dict
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.warning(f"Error serializing result: {e!s}")
|
||||
await logger.awarning(f"Error serializing result: {e!s}")
|
||||
outputs = None
|
||||
else:
|
||||
outputs = None
|
||||
|
|
@ -159,9 +159,9 @@ async def log_transaction(
|
|||
with session.no_autoflush:
|
||||
inserted = await crud_log_transaction(session, transaction)
|
||||
if inserted:
|
||||
logger.debug(f"Logged transaction: {inserted.id}")
|
||||
await logger.adebug(f"Logged transaction: {inserted.id}")
|
||||
except Exception as exc: # noqa: BLE001
|
||||
logger.error(f"Error logging transaction: {exc!s}")
|
||||
await logger.aerror(f"Error logging transaction: {exc!s}")
|
||||
|
||||
|
||||
async def log_vertex_build(
|
||||
|
|
@ -198,9 +198,9 @@ async def log_vertex_build(
|
|||
)
|
||||
async with session_getter(get_db_service()) as session:
|
||||
inserted = await crud_log_vertex_build(session, vertex_build)
|
||||
logger.debug(f"Logged vertex build: {inserted.build_id}")
|
||||
await logger.adebug(f"Logged vertex build: {inserted.build_id}")
|
||||
except Exception: # noqa: BLE001
|
||||
logger.exception("Error logging vertex build")
|
||||
await logger.aexception("Error logging vertex build")
|
||||
|
||||
|
||||
def rewrite_file_path(file_path: str):
|
||||
|
|
|
|||
|
|
@ -8,14 +8,13 @@ from collections.abc import AsyncIterator, Callable, Iterator, Mapping
|
|||
from enum import Enum
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from langflow.exceptions.component import ComponentBuildError
|
||||
from langflow.graph.schema import INPUT_COMPONENTS, OUTPUT_COMPONENTS, InterfaceComponentTypes, ResultData
|
||||
from langflow.graph.utils import UnbuiltObject, UnbuiltResult, log_transaction
|
||||
from langflow.graph.vertex.param_handler import ParameterHandler
|
||||
from langflow.interface import initialize
|
||||
from langflow.interface.listing import lazy_load_dict
|
||||
from langflow.logging.logger import logger
|
||||
from langflow.schema.artifact import ArtifactType
|
||||
from langflow.schema.data import Data
|
||||
from langflow.schema.message import Message
|
||||
|
|
@ -378,7 +377,7 @@ class Vertex:
|
|||
event_manager: EventManager | None = None,
|
||||
) -> None:
|
||||
"""Initiate the build process."""
|
||||
logger.debug(f"Building {self.display_name}")
|
||||
await logger.adebug(f"Building {self.display_name}")
|
||||
await self._build_each_vertex_in_params_dict()
|
||||
|
||||
if self.base_type is None:
|
||||
|
|
@ -599,7 +598,7 @@ class Vertex:
|
|||
|
||||
self.params[key].append(result)
|
||||
except AttributeError as e:
|
||||
logger.exception(e)
|
||||
await logger.aexception(e)
|
||||
msg = (
|
||||
f"Params {key} ({self.params[key]}) is not a list and cannot be extended with {result}"
|
||||
f"Error building Component {self.display_name}: \n\n{e}"
|
||||
|
|
@ -646,7 +645,7 @@ class Vertex:
|
|||
self._update_built_object_and_artifacts(result)
|
||||
except Exception as exc:
|
||||
tb = traceback.format_exc()
|
||||
logger.exception(exc)
|
||||
await logger.aexception(exc)
|
||||
msg = f"Error building Component {self.display_name}: \n\n{exc}"
|
||||
raise ComponentBuildError(msg, tb) from exc
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue