refactor: replace hardcoded serialization constants with getter functions (#8616)

* refactor: move serialization length limits to settings and use cached getters

* refactor: replace hardcoded serialization limits with dynamic settings-based values

* refactor: replace hardcoded serialization constants with getter functions

* 📝 Add docstrings to `move-max-consts-to-settings` (#8617)

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* fix:  improve docstring formatting

* fix: ensure flow_id is UUID type when creating vertex build record

* docs: enhance docstrings for max_text_length and max_items_length in Settings class

Updated the docstrings for max_text_length and max_items_length to clarify their purpose and behavior regarding UI display and truncation.

* docs: add LANGFLOW_MAX_ITEMS_LENGTH and LANGFLOW_MAX_TEXT_LENGTH environment variables

Introduced new environment variables to configure the maximum number of items and text length displayed in the UI. Updated documentation to reflect these changes and their impact on UI truncation behavior.

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Gabriel Luiz Freitas Almeida 2025-06-18 13:34:25 -03:00 committed by GitHub
commit bd0af911d9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 123 additions and 27 deletions

View file

@ -75,6 +75,8 @@ If it detects a supported environment variable, then it automatically adopts the
LANGFLOW_HOST=localhost
LANGFLOW_LANGCHAIN_CACHE=InMemoryCache
LANGFLOW_MAX_FILE_SIZE_UPLOAD=10000
LANGFLOW_MAX_ITEMS_LENGTH=100
LANGFLOW_MAX_TEXT_LENGTH=1000
LANGFLOW_LOG_LEVEL=error
LANGFLOW_OPEN_BROWSER=false
LANGFLOW_PORT=7860
@ -202,6 +204,8 @@ The following table lists the environment variables supported by Langflow.
| <Link id="LANGFLOW_LOG_FILE"/><span class="env-prefix">LANGFLOW_</span>LOG_FILE | String | Not set | Path to the log file. If this option is not set, logs are written to stdout. |
| <Link id="LANGFLOW_LOG_RETRIEVER_BUFFER_SIZE"/><span class="env-prefix">LANGFLOW_</span>LOG_RETRIEVER_BUFFER_SIZE | Integer | `10000` | Set the buffer size for log retrieval. Only used if `LANGFLOW_ENABLE_LOG_RETRIEVAL` is enabled. |
| <Link id="LANGFLOW_MAX_FILE_SIZE_UPLOAD"/><span class="env-prefix">LANGFLOW_</span>MAX_FILE_SIZE_UPLOAD | Integer | `100` | Set the maximum file size for the upload in megabytes.<br/>See [`--max-file-size-upload` option](./configuration-cli.md#run-max-file-size-upload). |
| <Link id="LANGFLOW_MAX_ITEMS_LENGTH"/><span class="env-prefix">LANGFLOW_</span>MAX_ITEMS_LENGTH | Integer | `100` | Maximum number of items to store and display in the UI. Lists longer than this will be truncated when displayed in the UI. Does not affect data passed between components nor outputs. |
| <Link id="LANGFLOW_MAX_TEXT_LENGTH"/><span class="env-prefix">LANGFLOW_</span>MAX_TEXT_LENGTH | Integer | `1000` | Maximum number of characters to store and display in the UI. Responses longer than this will be truncated when displayed in the UI. Does not truncate responses between components nor outputs. |
| <Link id="LANGFLOW_MCP_SERVER_ENABLED"/><span class="env-prefix">LANGFLOW_</span>MCP_SERVER_ENABLED | Boolean | `true` | If this option is set to False, Langflow does not enable the MCP server. |
| <Link id="LANGFLOW_MCP_SERVER_ENABLE_PROGRESS_NOTIFICATIONS"/><span class="env-prefix">LANGFLOW_</span>MCP_SERVER_ENABLE_PROGRESS_NOTIFICATIONS | Boolean | `false` | If this option is set to True, Langflow sends progress notifications in the MCP server. |
| <Link id="LANGFLOW_NEW_USER_IS_ACTIVE"/><span class="env-prefix">LANGFLOW_</span>NEW_USER_IS_ACTIVE | Boolean | `false` | When enabled, new users are automatically activated and can log in without requiring explicit activation by the superuser. |
@ -259,6 +263,8 @@ LANGFLOW_HEALTH_CHECK_MAX_RETRIES=5
LANGFLOW_HOST=localhost
LANGFLOW_LANGCHAIN_CACHE=InMemoryCache
LANGFLOW_MAX_FILE_SIZE_UPLOAD=10000
LANGFLOW_MAX_ITEMS_LENGTH=100
LANGFLOW_MAX_TEXT_LENGTH=1000
LANGFLOW_LOG_LEVEL=error
LANGFLOW_OPEN_BROWSER=false
LANGFLOW_PORT=7860
@ -298,6 +304,8 @@ Environment="LANGFLOW_HEALTH_CHECK_MAX_RETRIES=5"
Environment="LANGFLOW_HOST=localhost"
Environment="LANGFLOW_LANGCHAIN_CACHE=InMemoryCache"
Environment="LANGFLOW_MAX_FILE_SIZE_UPLOAD=10000"
Environment="LANGFLOW_MAX_ITEMS_LENGTH=100"
Environment="LANGFLOW_MAX_TEXT_LENGTH=1000"
Environment="LANGFLOW_LOG_ENV=container_json"
Environment="LANGFLOW_LOG_FILE=logs/langflow.log"
Environment="LANGFLOW_LOG_LEVEL=error"
@ -344,6 +352,8 @@ Create or edit the `.vscode/tasks.json` file in your project root:
"LANGFLOW_HOST": "localhost",
"LANGFLOW_LANGCHAIN_CACHE": "InMemoryCache",
"LANGFLOW_MAX_FILE_SIZE_UPLOAD": "10000",
"LANGFLOW_MAX_ITEMS_LENGTH": "100",
"LANGFLOW_MAX_TEXT_LENGTH": "1000",
"LANGFLOW_LOG_ENV": "container_csv",
"LANGFLOW_LOG_FILE": "langflow.log",
"LANGFLOW_LOG_LEVEL": "error",

View file

@ -18,8 +18,7 @@ from langflow.schema.dotdict import dotdict
from langflow.schema.graph import Tweaks
from langflow.schema.schema import InputType, OutputType, OutputValue
from langflow.serialization import constants as serialization_constants
from langflow.serialization.constants import MAX_ITEMS_LENGTH, MAX_TEXT_LENGTH
from langflow.serialization.serialization import serialize
from langflow.serialization.serialization import get_max_items_length, get_max_text_length, serialize
from langflow.services.database.models.api_key.model import ApiKeyRead
from langflow.services.database.models.base import orjson_dumps
from langflow.services.database.models.flow.model import FlowCreate, FlowRead
@ -276,18 +275,28 @@ class ResultDataResponse(BaseModel):
@field_serializer("results")
@classmethod
def serialize_results(cls, v):
"""Serialize results with custom handling for special types and truncation."""
return serialize(v, max_length=MAX_TEXT_LENGTH, max_items=MAX_ITEMS_LENGTH)
"""Serializes the results value with custom handling for special types and applies truncation limits.
Returns:
The serialized representation of the input value, truncated according to configured
maximum text length and item count.
"""
return serialize(v, max_length=get_max_text_length(), max_items=get_max_items_length())
@model_serializer(mode="plain")
def serialize_model(self) -> dict:
"""Custom serializer for the entire model."""
"""Serialize the entire model into a dictionary with truncation applied to large fields.
Returns:
dict: A dictionary representation of the model with serialized and truncated
results, outputs, logs, message, and artifacts.
"""
return {
"results": self.serialize_results(self.results),
"outputs": serialize(self.outputs, max_length=MAX_TEXT_LENGTH, max_items=MAX_ITEMS_LENGTH),
"logs": serialize(self.logs, max_length=MAX_TEXT_LENGTH, max_items=MAX_ITEMS_LENGTH),
"message": serialize(self.message, max_length=MAX_TEXT_LENGTH, max_items=MAX_ITEMS_LENGTH),
"artifacts": serialize(self.artifacts, max_length=MAX_TEXT_LENGTH, max_items=MAX_ITEMS_LENGTH),
"outputs": serialize(self.outputs, max_length=get_max_text_length(), max_items=get_max_items_length()),
"logs": serialize(self.logs, max_length=get_max_text_length(), max_items=get_max_items_length()),
"message": serialize(self.message, max_length=get_max_text_length(), max_items=get_max_items_length()),
"artifacts": serialize(self.artifacts, max_length=get_max_text_length(), max_items=get_max_items_length()),
"timedelta": self.timedelta,
"duration": self.duration,
"used_frozen_result": self.used_frozen_result,
@ -309,7 +318,15 @@ class VertexBuildResponse(BaseModel):
@field_serializer("data")
def serialize_data(self, data: ResultDataResponse) -> dict:
return serialize(data, max_length=MAX_TEXT_LENGTH, max_items=MAX_ITEMS_LENGTH)
"""Serialize a ResultDataResponse object into a dictionary with enforced maximum text and item lengths.
Parameters:
data (ResultDataResponse): The data object to serialize.
Returns:
dict: The serialized representation of the data with truncation applied.
"""
return serialize(data, max_length=get_max_text_length(), max_items=get_max_items_length())
class VerticesBuiltResponse(BaseModel):

View file

@ -11,8 +11,7 @@ from loguru import logger
from langflow.interface.utils import extract_input_variables_from_prompt
from langflow.schema.data import Data
from langflow.schema.message import Message
from langflow.serialization.constants import MAX_ITEMS_LENGTH, MAX_TEXT_LENGTH
from langflow.serialization.serialization import serialize
from langflow.serialization.serialization import get_max_items_length, get_max_text_length, serialize
from langflow.services.database.models.transactions.crud import log_transaction as crud_log_transaction
from langflow.services.database.models.transactions.model import TransactionBase
from langflow.services.database.models.vertex_builds.crud import log_vertex_build as crud_log_vertex_build
@ -116,6 +115,13 @@ def _vertex_to_primitive_dict(target: Vertex) -> dict:
async def log_transaction(
flow_id: str | UUID, source: Vertex, status, target: Vertex | None = None, error=None
) -> None:
"""Asynchronously logs a transaction record for a vertex in a flow if transaction storage is enabled.
Serializes the source vertex's primitive parameters and result, handling pandas DataFrames as needed,
and records transaction details including inputs, outputs, status, error, and flow ID in the database.
If the flow ID is not provided, attempts to retrieve it from the source vertex's graph.
Logs warnings and errors on serialization or database failures.
"""
try:
if not get_settings_service().settings.transactions_storage_enabled:
return
@ -143,8 +149,8 @@ async def log_transaction(
transaction = TransactionBase(
vertex_id=source.id,
target_id=target.id if target else None,
inputs=serialize(inputs, max_length=MAX_TEXT_LENGTH, max_items=MAX_ITEMS_LENGTH),
outputs=serialize(outputs, max_length=MAX_TEXT_LENGTH, max_items=MAX_ITEMS_LENGTH),
inputs=serialize(inputs, max_length=get_max_text_length(), max_items=get_max_items_length()),
outputs=serialize(outputs, max_length=get_max_text_length(), max_items=get_max_items_length()),
status=status,
error=error,
flow_id=flow_id if isinstance(flow_id, UUID) else UUID(flow_id),
@ -167,17 +173,22 @@ async def log_vertex_build(
data: ResultDataResponse | dict,
artifacts: dict | None = None,
) -> None:
"""Asynchronously logs a vertex build record to the database if vertex build storage is enabled.
Serializes the provided data and artifacts with configurable length and item limits before storing.
Converts parameters to string if present. Handles exceptions by logging errors.
"""
try:
if not get_settings_service().settings.vertex_builds_storage_enabled:
return
vertex_build = VertexBuildBase(
flow_id=flow_id,
flow_id=flow_id if isinstance(flow_id, UUID) else UUID(flow_id),
id=vertex_id,
valid=valid,
params=str(params) if params else None,
data=serialize(data, max_length=MAX_TEXT_LENGTH, max_items=MAX_ITEMS_LENGTH),
artifacts=serialize(artifacts, max_length=MAX_TEXT_LENGTH, max_items=MAX_ITEMS_LENGTH),
data=serialize(data, max_length=get_max_text_length(), max_items=get_max_items_length()),
artifacts=serialize(artifacts, max_length=get_max_text_length(), max_items=get_max_items_length()),
)
async with session_getter(get_db_service()) as session:
inserted = await crud_log_vertex_build(session, vertex_build)

View file

@ -1,6 +1,7 @@
from collections.abc import AsyncIterator, Generator, Iterator
from datetime import datetime, timezone
from decimal import Decimal
from functools import lru_cache
from typing import Any, cast
from uuid import UUID
@ -12,6 +13,7 @@ from pydantic import BaseModel
from pydantic.v1 import BaseModel as BaseModelV1
from langflow.serialization.constants import MAX_ITEMS_LENGTH, MAX_TEXT_LENGTH
from langflow.services.deps import get_settings_service
# Sentinel variable to signal a failed serialization.
@ -25,8 +27,28 @@ class _UnserializableSentinel:
UNSERIALIZABLE_SENTINEL = _UnserializableSentinel()
@lru_cache(maxsize=1)
def get_max_text_length() -> int:
"""Return the maximum allowed text length for serialization from the current settings."""
return get_settings_service().settings.max_text_length
@lru_cache(maxsize=1)
def get_max_items_length() -> int:
"""Return the maximum allowed number of items for serialization, as defined in the current settings."""
return get_settings_service().settings.max_items_length
def _serialize_str(obj: str, max_length: int | None, _) -> str:
"""Truncate long strings with ellipsis if max_length provided."""
"""Truncates a string to the specified maximum length, appending an ellipsis if truncation occurs.
Parameters:
obj (str): The string to be truncated.
max_length (int | None): The maximum allowed length of the string. If None, no truncation is performed.
Returns:
str: The original or truncated string, with an ellipsis appended if truncated.
"""
if max_length is None or len(obj) <= max_length:
return obj
return obj[:max_length] + "..."

View file

@ -4,8 +4,7 @@ from uuid import UUID, uuid4
from pydantic import field_serializer, field_validator
from sqlmodel import JSON, Column, Field, SQLModel
from langflow.serialization.constants import MAX_ITEMS_LENGTH, MAX_TEXT_LENGTH
from langflow.serialization.serialization import serialize
from langflow.serialization.serialization import get_max_items_length, get_max_text_length, serialize
class TransactionBase(SQLModel):
@ -33,11 +32,27 @@ class TransactionBase(SQLModel):
@field_serializer("inputs")
def serialize_inputs(self, data) -> dict:
return serialize(data, max_length=MAX_TEXT_LENGTH, max_items=MAX_ITEMS_LENGTH)
"""Serialize the transaction's input data with enforced limits on text length and item count.
Parameters:
data (dict): The input data to be serialized.
Returns:
dict: The serialized input data with applied constraints.
"""
return serialize(data, max_length=get_max_text_length(), max_items=get_max_items_length())
@field_serializer("outputs")
def serialize_outputs(self, data) -> dict:
return serialize(data, max_length=MAX_TEXT_LENGTH, max_items=MAX_ITEMS_LENGTH)
"""Serialize the outputs dictionary with enforced limits on text length and item count.
Parameters:
data (dict): The outputs data to serialize.
Returns:
dict: The serialized outputs dictionary with applied constraints.
"""
return serialize(data, max_length=get_max_text_length(), max_items=get_max_items_length())
class TransactionTable(TransactionBase, table=True): # type: ignore[call-arg]

View file

@ -5,8 +5,7 @@ from pydantic import BaseModel, field_serializer, field_validator
from sqlalchemy import Text
from sqlmodel import JSON, Column, Field, SQLModel
from langflow.serialization.constants import MAX_ITEMS_LENGTH, MAX_TEXT_LENGTH
from langflow.serialization.serialization import serialize
from langflow.serialization.serialization import get_max_items_length, get_max_text_length, serialize
class VertexBuildBase(SQLModel):
@ -40,15 +39,30 @@ class VertexBuildBase(SQLModel):
@field_serializer("data")
def serialize_data(self, data) -> dict:
return serialize(data, max_length=MAX_TEXT_LENGTH, max_items=MAX_ITEMS_LENGTH)
"""Serializes the `data` field with enforced limits on text length and item count.
Returns:
dict: The serialized representation of the data field.
"""
return serialize(data, max_length=get_max_text_length(), max_items=get_max_items_length())
@field_serializer("artifacts")
def serialize_artifacts(self, data) -> dict:
return serialize(data, max_length=MAX_TEXT_LENGTH, max_items=MAX_ITEMS_LENGTH)
"""Serializes the artifacts field, applying limits on text length and item count.
Returns:
dict: The serialized artifacts dictionary with enforced size constraints.
"""
return serialize(data, max_length=get_max_text_length(), max_items=get_max_items_length())
@field_serializer("params")
def serialize_params(self, data) -> str:
return serialize(data, max_length=MAX_TEXT_LENGTH, max_items=MAX_ITEMS_LENGTH)
"""Serialize the `params` field to a string with enforced limits on text length and item count.
Returns:
str: The serialized representation of the `params` data.
"""
return serialize(data, max_length=get_max_text_length(), max_items=get_max_items_length())
class VertexBuildTable(VertexBuildBase, table=True): # type: ignore[call-arg]

View file

@ -20,6 +20,7 @@ from pydantic_settings import (
)
from typing_extensions import override
from langflow.serialization.constants import MAX_ITEMS_LENGTH, MAX_TEXT_LENGTH
from langflow.services.settings.constants import VARIABLES_TO_GET_FROM_ENVIRONMENT
from langflow.utils.util_strings import is_valid_database_url
@ -229,6 +230,12 @@ class Settings(BaseSettings):
"""Path to the SSL certificate file on the local system."""
ssl_key_file: str | None = None
"""Path to the SSL key file on the local system."""
max_text_length: int = MAX_TEXT_LENGTH
"""Maximum number of characters to store and display in the UI. Responses longer than this
will be truncated when displayed in the UI. Does not truncate responses between components nor outputs."""
max_items_length: int = MAX_ITEMS_LENGTH
"""Maximum number of items to store and display in the UI. Lists longer than this
will be truncated when displayed in the UI. Does not affect data passed between components nor outputs."""
# MCP Server
mcp_server_enabled: bool = True