Merge branch 'dev' into feature/profilePage
This commit is contained in:
commit
8119d5922b
60 changed files with 240 additions and 139 deletions
|
|
@ -356,7 +356,7 @@ def superuser(
|
|||
with session_getter(db_manager) as session:
|
||||
from langflow.services.auth.utils import create_super_user
|
||||
|
||||
if create_super_user(session, username, password):
|
||||
if create_super_user(db=session, username=username, password=password):
|
||||
# Verify that the superuser was created
|
||||
from langflow.services.database.models.user.user import User
|
||||
|
||||
|
|
|
|||
|
|
@ -30,10 +30,10 @@ def upgrade() -> None:
|
|||
# and other related indices
|
||||
if "flowstyle" in existing_tables:
|
||||
op.drop_table("flowstyle")
|
||||
if "ix_flowstyle_flow_id" in [
|
||||
index["name"] for index in inspector.get_indexes("flowstyle")
|
||||
]:
|
||||
op.drop_index("ix_flowstyle_flow_id", table_name="flowstyle")
|
||||
if "ix_flowstyle_flow_id" in [
|
||||
index["name"] for index in inspector.get_indexes("flowstyle")
|
||||
]:
|
||||
op.drop_index("ix_flowstyle_flow_id", table_name="flowstyle")
|
||||
|
||||
existing_indices_flow = []
|
||||
existing_fks_flow = []
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class ValidatePromptRequest(BaseModel):
|
|||
name: str
|
||||
template: str
|
||||
# optional for tweak call
|
||||
frontend_node: Optional[FrontendNodeRequest]
|
||||
frontend_node: Optional[FrontendNodeRequest] = None
|
||||
|
||||
|
||||
# Build ValidationResponse class for {"imports": {"errors": []}, "function": {"errors": []}}
|
||||
|
|
@ -42,7 +42,7 @@ class CodeValidationResponse(BaseModel):
|
|||
class PromptValidationResponse(BaseModel):
|
||||
input_variables: list
|
||||
# object return for tweak call
|
||||
frontend_node: FrontendNodeRequest | object
|
||||
frontend_node: Optional[FrontendNodeRequest] = None
|
||||
|
||||
|
||||
INVALID_CHARACTERS = {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ from fastapi import WebSocket
|
|||
|
||||
|
||||
from langchain.schema import AgentAction, LLMResult, AgentFinish
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
|
||||
|
||||
# https://github.com/hwchase17/chat-langchain/blob/master/callback.py
|
||||
|
|
|
|||
|
|
@ -11,17 +11,15 @@ from fastapi.responses import StreamingResponse
|
|||
from langflow.api.utils import build_input_keys_response
|
||||
from langflow.api.v1.schemas import BuildStatus, BuiltResponse, InitResponse, StreamData
|
||||
|
||||
from langflow.services import service_manager, ServiceType
|
||||
from langflow.graph.graph.base import Graph
|
||||
from langflow.services.auth.utils import get_current_active_user, get_current_user
|
||||
from langflow.services.utils import get_session
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
from langflow.services.utils import get_chat_manager, get_session
|
||||
from cachetools import LRUCache
|
||||
from sqlmodel import Session
|
||||
from typing import TYPE_CHECKING
|
||||
from langflow.services.chat.manager import ChatManager
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from langflow.services.chat.manager import ChatManager
|
||||
|
||||
router = APIRouter(tags=["Chat"])
|
||||
|
||||
|
|
@ -34,6 +32,7 @@ async def chat(
|
|||
websocket: WebSocket,
|
||||
token: str = Query(...),
|
||||
db: Session = Depends(get_session),
|
||||
chat_manager: "ChatManager" = Depends(get_chat_manager),
|
||||
):
|
||||
"""Websocket endpoint for chat."""
|
||||
try:
|
||||
|
|
@ -48,7 +47,6 @@ async def chat(
|
|||
code=status.WS_1008_POLICY_VIOLATION, reason="Unauthorized"
|
||||
)
|
||||
|
||||
chat_manager: "ChatManager" = service_manager.get(ServiceType.CHAT_MANAGER)
|
||||
if client_id in chat_manager.in_memory_cache:
|
||||
await chat_manager.handle_websocket(client_id, websocket)
|
||||
else:
|
||||
|
|
@ -61,19 +59,21 @@ async def chat(
|
|||
await websocket.close(code=status.WS_1011_INTERNAL_ERROR, reason=str(exc))
|
||||
except Exception as exc:
|
||||
logger.error(f"Error in chat websocket: {exc}")
|
||||
if isinstance(exc, HTTPException):
|
||||
exc = exc.detail
|
||||
messsage = exc.detail if isinstance(exc, HTTPException) else str(exc)
|
||||
if "Could not validate credentials" in str(exc):
|
||||
await websocket.close(
|
||||
code=status.WS_1008_POLICY_VIOLATION, reason="Unauthorized"
|
||||
)
|
||||
else:
|
||||
await websocket.close(code=status.WS_1011_INTERNAL_ERROR, reason=str(exc))
|
||||
await websocket.close(code=status.WS_1011_INTERNAL_ERROR, reason=messsage)
|
||||
|
||||
|
||||
@router.post("/build/init/{flow_id}", response_model=InitResponse, status_code=201)
|
||||
async def init_build(
|
||||
graph_data: dict, flow_id: str, current_user=Depends(get_current_active_user)
|
||||
graph_data: dict,
|
||||
flow_id: str,
|
||||
current_user=Depends(get_current_active_user),
|
||||
chat_manager: "ChatManager" = Depends(get_chat_manager),
|
||||
):
|
||||
"""Initialize the build by storing graph data and returning a unique session ID."""
|
||||
|
||||
|
|
@ -88,7 +88,6 @@ async def init_build(
|
|||
return InitResponse(flowId=flow_id)
|
||||
|
||||
# Delete from cache if already exists
|
||||
chat_manager = service_manager.get(ServiceType.CHAT_MANAGER)
|
||||
if flow_id in chat_manager.in_memory_cache:
|
||||
with chat_manager.in_memory_cache._lock:
|
||||
chat_manager.in_memory_cache.delete(flow_id)
|
||||
|
|
@ -124,7 +123,9 @@ async def build_status(flow_id: str):
|
|||
|
||||
|
||||
@router.get("/build/stream/{flow_id}", response_class=StreamingResponse)
|
||||
async def stream_build(flow_id: str):
|
||||
async def stream_build(
|
||||
flow_id: str, chat_manager: "ChatManager" = Depends(get_chat_manager)
|
||||
):
|
||||
"""Stream the build process based on stored flow data."""
|
||||
|
||||
async def event_stream(flow_id):
|
||||
|
|
@ -203,7 +204,6 @@ async def stream_build(flow_id: str):
|
|||
"handle_keys": [],
|
||||
}
|
||||
yield str(StreamData(event="message", data=input_keys_response))
|
||||
chat_manager = service_manager.get(ServiceType.CHAT_MANAGER)
|
||||
chat_manager.set_cache(flow_id, langchain_object)
|
||||
# We need to reset the chat history
|
||||
chat_manager.chat_history.empty_history(flow_id)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ from langflow.services.database.models.flow import Flow
|
|||
from langflow.processing.process import process_graph_cached, process_tweaks
|
||||
from langflow.services.database.models.user.user import User
|
||||
from langflow.services.utils import get_settings_manager
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
from fastapi import APIRouter, Depends, HTTPException, UploadFile, Body, status
|
||||
import sqlalchemy as sa
|
||||
from langflow.interface.custom.custom_component import CustomComponent
|
||||
|
|
@ -34,14 +34,15 @@ from sqlmodel import Session
|
|||
router = APIRouter(tags=["Base"])
|
||||
|
||||
|
||||
@router.get("/all")
|
||||
def get_all(current_user: User = Depends(get_current_active_user)):
|
||||
@router.get("/all", dependencies=[Depends(get_current_active_user)])
|
||||
def get_all(
|
||||
settings_manager=Depends(get_settings_manager),
|
||||
):
|
||||
logger.debug("Building langchain types dict")
|
||||
native_components = build_langchain_types_dict()
|
||||
# custom_components is a list of dicts
|
||||
# need to merge all the keys into one dict
|
||||
custom_components_from_file: dict[str, Any] = {}
|
||||
settings_manager = get_settings_manager()
|
||||
if settings_manager.settings.COMPONENTS_PATH:
|
||||
logger.info(
|
||||
f"Building custom components from {settings_manager.settings.COMPONENTS_PATH}"
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ def update_flow(
|
|||
flow_id: UUID,
|
||||
flow: FlowUpdate,
|
||||
current_user: User = Depends(get_current_active_user),
|
||||
settings_manager=Depends(get_settings_manager),
|
||||
):
|
||||
"""Update a flow."""
|
||||
|
||||
|
|
@ -90,7 +91,6 @@ def update_flow(
|
|||
if not db_flow:
|
||||
raise HTTPException(status_code=404, detail="Flow not found")
|
||||
flow_data = flow.dict(exclude_unset=True)
|
||||
settings_manager = get_settings_manager()
|
||||
if settings_manager.settings.REMOVE_API_KEYS:
|
||||
flow_data = remove_api_keys(flow_data)
|
||||
for key, value in flow_data.items():
|
||||
|
|
|
|||
|
|
@ -34,9 +34,9 @@ async def login_to_get_access_token(
|
|||
|
||||
|
||||
@router.get("/auto_login")
|
||||
async def auto_login(db: Session = Depends(get_session)):
|
||||
settings_manager = get_settings_manager()
|
||||
|
||||
async def auto_login(
|
||||
db: Session = Depends(get_session), settings_manager=Depends(get_settings_manager)
|
||||
):
|
||||
if settings_manager.auth_settings.AUTO_LOGIN:
|
||||
return create_user_longterm_token(db)
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ router = APIRouter(tags=["Users"])
|
|||
@router.post("/user", response_model=UserRead, status_code=201)
|
||||
def add_user(
|
||||
user: UserCreate,
|
||||
db: Session = Depends(get_session),
|
||||
session: Session = Depends(get_session),
|
||||
) -> User:
|
||||
"""
|
||||
Add a new user to the database.
|
||||
|
|
@ -38,11 +38,11 @@ def add_user(
|
|||
try:
|
||||
new_user.password = get_password_hash(user.password)
|
||||
|
||||
db.add(new_user)
|
||||
db.commit()
|
||||
db.refresh(new_user)
|
||||
session.add(new_user)
|
||||
session.commit()
|
||||
session.refresh(new_user)
|
||||
except IntegrityError as e:
|
||||
db.rollback()
|
||||
session.rollback()
|
||||
raise HTTPException(
|
||||
status_code=400, detail="This username is unavailable."
|
||||
) from e
|
||||
|
|
@ -65,16 +65,16 @@ def read_all_users(
|
|||
skip: int = 0,
|
||||
limit: int = 10,
|
||||
current_user: Session = Depends(get_current_active_superuser),
|
||||
db: Session = Depends(get_session),
|
||||
session: Session = Depends(get_session),
|
||||
) -> UsersResponse:
|
||||
"""
|
||||
Retrieve a list of users from the database with pagination.
|
||||
"""
|
||||
query = select(User).offset(skip).limit(limit)
|
||||
users = db.execute(query).fetchall()
|
||||
users = session.execute(query).fetchall()
|
||||
|
||||
count_query = select(func.count()).select_from(User) # type: ignore
|
||||
total_count = db.execute(count_query).scalar()
|
||||
total_count = session.execute(count_query).scalar()
|
||||
|
||||
return UsersResponse(
|
||||
total_count=total_count, # type: ignore
|
||||
|
|
@ -87,19 +87,19 @@ def patch_user(
|
|||
user_id: UUID,
|
||||
user: UserUpdate,
|
||||
_: Session = Depends(get_current_active_user),
|
||||
db: Session = Depends(get_session),
|
||||
session: Session = Depends(get_session),
|
||||
) -> User:
|
||||
"""
|
||||
Update an existing user's data.
|
||||
"""
|
||||
return update_user(user_id, user, db)
|
||||
return update_user(user_id, user, session)
|
||||
|
||||
|
||||
@router.delete("/user/{user_id}")
|
||||
def delete_user(
|
||||
user_id: UUID,
|
||||
current_user: User = Depends(get_current_active_superuser),
|
||||
db: Session = Depends(get_session),
|
||||
session: Session = Depends(get_session),
|
||||
) -> dict:
|
||||
"""
|
||||
Delete a user from the database.
|
||||
|
|
@ -113,12 +113,12 @@ def delete_user(
|
|||
status_code=403, detail="You don't have the permission to delete this user"
|
||||
)
|
||||
|
||||
user_db = db.query(User).filter(User.id == user_id).first()
|
||||
user_db = session.query(User).filter(User.id == user_id).first()
|
||||
if not user_db:
|
||||
raise HTTPException(status_code=404, detail="User not found")
|
||||
|
||||
db.delete(user_db)
|
||||
db.commit()
|
||||
session.delete(user_db)
|
||||
session.commit()
|
||||
|
||||
return {"detail": "User deleted"}
|
||||
|
||||
|
|
@ -126,7 +126,7 @@ def delete_user(
|
|||
# TODO: REMOVE - Just for testing purposes
|
||||
@router.post("/super_user", response_model=User)
|
||||
def add_super_user_for_testing_purposes_delete_me_before_merge_into_dev(
|
||||
db: Session = Depends(get_session),
|
||||
session: Session = Depends(get_session),
|
||||
) -> User:
|
||||
"""
|
||||
Add a superuser for testing purposes.
|
||||
|
|
@ -141,11 +141,11 @@ def add_super_user_for_testing_purposes_delete_me_before_merge_into_dev(
|
|||
)
|
||||
|
||||
try:
|
||||
db.add(new_user)
|
||||
db.commit()
|
||||
db.refresh(new_user)
|
||||
session.add(new_user)
|
||||
session.commit()
|
||||
session.refresh(new_user)
|
||||
except IntegrityError as e:
|
||||
db.rollback()
|
||||
session.rollback()
|
||||
raise HTTPException(status_code=400, detail="User exists") from e
|
||||
|
||||
return new_user
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ from langflow.api.v1.base import (
|
|||
validate_prompt,
|
||||
)
|
||||
from langflow.template.field.base import TemplateField
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
from langflow.utils.validate import validate_code
|
||||
|
||||
# build router
|
||||
|
|
@ -35,7 +35,7 @@ def post_validate_prompt(prompt_request: ValidatePromptRequest):
|
|||
if prompt_request.frontend_node is None:
|
||||
return PromptValidationResponse(
|
||||
input_variables=input_variables,
|
||||
frontend_node={},
|
||||
frontend_node=None,
|
||||
)
|
||||
old_custom_fields = get_old_custom_fields(prompt_request)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ from langflow.graph.vertex.types import (
|
|||
)
|
||||
from langflow.interface.tools.constants import FILE_TOOLS
|
||||
from langflow.utils import payload
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
from langchain.chains.base import Chain
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ from langflow.graph.utils import UnbuiltObject
|
|||
from langflow.interface.initialize import loading
|
||||
from langflow.interface.listing import lazy_load_dict
|
||||
from langflow.utils.constants import DIRECT_TYPES
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
from langflow.utils.util import sync_to_async
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ from langflow.interface.base import LangChainTypeCreator
|
|||
from langflow.services.utils import get_settings_manager
|
||||
|
||||
from langflow.template.frontend_node.agents import AgentFrontendNode
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
from langflow.utils.util import build_template_from_class, build_template_from_method
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ from pydantic import BaseModel
|
|||
from langflow.template.field.base import TemplateField
|
||||
from langflow.template.frontend_node.base import FrontendNode
|
||||
from langflow.template.template.base import Template
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
|
||||
|
||||
# Assuming necessary imports for Field, Template, and FrontendNode classes
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from langflow.interface.importing.utils import import_class
|
|||
from langflow.services.utils import get_settings_manager
|
||||
|
||||
from langflow.template.frontend_node.chains import ChainFrontendNode
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
from langflow.utils.util import build_template_from_class, build_template_from_method
|
||||
from langchain import chains
|
||||
from langchain_experimental.sql import SQLDatabaseChain # type: ignore
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ from langflow.interface.custom.custom_component import CustomComponent
|
|||
from langflow.template.frontend_node.custom_components import (
|
||||
CustomComponentFrontendNode,
|
||||
)
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
|
||||
# Assuming necessary imports for Field, Template, and FrontendNode classes
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import os
|
||||
import ast
|
||||
import zlib
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
|
||||
|
||||
class CustomComponentPathValueError(ValueError):
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ from langflow.services.utils import get_settings_manager
|
|||
from langflow.template.frontend_node.documentloaders import DocumentLoaderFrontNode
|
||||
from langflow.interface.custom_lists import documentloaders_type_to_cls_dict
|
||||
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
from langflow.utils.util import build_template_from_class
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from langflow.services.utils import get_settings_manager
|
|||
|
||||
from langflow.template.frontend_node.base import FrontendNode
|
||||
from langflow.template.frontend_node.embeddings import EmbeddingFrontendNode
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
from langflow.utils.util import build_template_from_class
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ from langflow.utils import validate
|
|||
from langchain.chains.base import Chain
|
||||
from langchain.vectorstores.base import VectorStore
|
||||
from langchain.document_loaders.base import BaseLoader
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from langflow import CustomComponent
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ from langflow.interface.custom_lists import llm_type_to_cls_dict
|
|||
from langflow.services.utils import get_settings_manager
|
||||
|
||||
from langflow.template.frontend_node.llms import LLMFrontendNode
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
from langflow.utils.util import build_template_from_class
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from langflow.services.utils import get_settings_manager
|
|||
|
||||
from langflow.template.frontend_node.base import FrontendNode
|
||||
from langflow.template.frontend_node.memories import MemoryFrontendNode
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
from langflow.utils.util import build_template_from_class, build_template_from_method
|
||||
from langflow.custom.customs import get_custom_nodes
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ from langflow.interface.importing.utils import import_class
|
|||
from langflow.services.utils import get_settings_manager
|
||||
|
||||
from langflow.template.frontend_node.output_parsers import OutputParserFrontendNode
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
from langflow.utils.util import build_template_from_class, build_template_from_method
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ from langflow.interface.importing.utils import import_class
|
|||
from langflow.services.utils import get_settings_manager
|
||||
|
||||
from langflow.template.frontend_node.prompts import PromptFrontendNode
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
from langflow.utils.util import build_template_from_class
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ from langflow.interface.importing.utils import import_class
|
|||
from langflow.services.utils import get_settings_manager
|
||||
|
||||
from langflow.template.frontend_node.retrievers import RetrieverFrontendNode
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
from langflow.utils.util import build_template_from_method, build_template_from_class
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from typing import Any, Dict, Tuple
|
||||
from langflow.services.cache.utils import memoize_dict
|
||||
from langflow.graph import Graph
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
|
||||
|
||||
@memoize_dict(maxsize=10)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ from langflow.services.utils import get_settings_manager
|
|||
from langflow.template.frontend_node.textsplitters import TextSplittersFrontendNode
|
||||
from langflow.interface.custom_lists import textsplitter_type_to_cls_dict
|
||||
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
from langflow.utils.util import build_template_from_class
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from langflow.interface.base import LangChainTypeCreator
|
|||
from langflow.interface.importing.utils import import_class, import_module
|
||||
from langflow.services.utils import get_settings_manager
|
||||
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
from langflow.utils.util import build_template_from_class
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import inspect
|
|||
from typing import Dict, Union
|
||||
|
||||
from langchain.agents.tools import Tool
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
|
||||
|
||||
def get_func_tool_params(func, **kwargs) -> Union[Dict, None]:
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ from langflow.template.frontend_node.custom_components import (
|
|||
from langflow.interface.retrievers.base import retriever_creator
|
||||
|
||||
from langflow.interface.custom.directory_reader import DirectoryReader
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
from langflow.utils.util import get_base_classes
|
||||
|
||||
import re
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ from langflow.interface.importing.utils import import_class
|
|||
from langflow.services.utils import get_settings_manager
|
||||
|
||||
from langflow.template.frontend_node.utilities import UtilitiesFrontendNode
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
from langflow.utils.util import build_template_from_class
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import re
|
|||
import yaml
|
||||
from langchain.base_language import BaseLanguageModel
|
||||
from PIL.Image import Image
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
from langflow.services.chat.config import ChatConfig
|
||||
from langflow.services.utils import get_settings_manager
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ from langflow.interface.importing.utils import import_class
|
|||
from langflow.services.utils import get_settings_manager
|
||||
|
||||
from langflow.template.frontend_node.vectorstores import VectorStoreFrontendNode
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
from langflow.utils.util import build_template_from_method
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ from typing import Dict, List, Optional
|
|||
from langchain import requests, sql_database
|
||||
|
||||
from langflow.interface.base import LangChainTypeCreator
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
from langflow.utils.util import build_template_from_class, build_template_from_method
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ from langflow.api import router
|
|||
|
||||
from langflow.interface.utils import setup_llm_caching
|
||||
from langflow.services.database.utils import initialize_database
|
||||
from langflow.services.manager import initialize_services
|
||||
from langflow.services.manager import initialize_services, teardown_services
|
||||
from langflow.utils.logger import configure
|
||||
|
||||
|
||||
|
|
@ -40,6 +40,7 @@ def create_app():
|
|||
app.on_event("startup")(initialize_services)
|
||||
app.on_event("startup")(initialize_database)
|
||||
app.on_event("startup")(setup_llm_caching)
|
||||
app.on_event("shutdown")(teardown_services)
|
||||
return app
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from langflow.api.v1.callback import (
|
|||
StreamingLLMCallbackHandler,
|
||||
)
|
||||
from langflow.processing.process import fix_memory_inputs, format_actions
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
from langchain.agents.agent import AgentExecutor
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from langflow.interface.run import (
|
|||
get_memory_key,
|
||||
update_memory_keys,
|
||||
)
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
from langflow.graph import Graph
|
||||
from langchain.chains.base import Chain
|
||||
from langchain.vectorstores.base import VectorStore
|
||||
|
|
|
|||
|
|
@ -37,7 +37,12 @@ async def api_key_security(
|
|||
result: Optional[Union[ApiKey, User]] = None
|
||||
if settings_manager.auth_settings.AUTO_LOGIN:
|
||||
# Get the first user
|
||||
settings_manager.auth_settings.FIRST_SUPERUSER
|
||||
if not settings_manager.auth_settings.FIRST_SUPERUSER:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Missing first superuser credentials",
|
||||
)
|
||||
|
||||
result = get_user_by_username(
|
||||
db, settings_manager.auth_settings.FIRST_SUPERUSER
|
||||
)
|
||||
|
|
@ -80,6 +85,9 @@ async def get_current_user(
|
|||
if isinstance(token, Coroutine):
|
||||
token = await token
|
||||
|
||||
if settings_manager.auth_settings.SECRET_KEY is None:
|
||||
raise credentials_exception
|
||||
|
||||
try:
|
||||
payload = jwt.decode(
|
||||
token,
|
||||
|
|
@ -150,22 +158,16 @@ def create_token(data: dict, expires_delta: timedelta):
|
|||
|
||||
|
||||
def create_super_user(
|
||||
username: str,
|
||||
password: str,
|
||||
db: Session = Depends(get_session),
|
||||
username: Optional[str] = None,
|
||||
password: Optional[str] = None,
|
||||
) -> User:
|
||||
settings_manager = get_settings_manager()
|
||||
|
||||
super_user = get_user_by_username(
|
||||
db, username or settings_manager.auth_settings.FIRST_SUPERUSER
|
||||
)
|
||||
super_user = get_user_by_username(db, username)
|
||||
|
||||
if not super_user:
|
||||
super_user = User(
|
||||
username=username or settings_manager.auth_settings.FIRST_SUPERUSER,
|
||||
password=get_password_hash(
|
||||
password or settings_manager.auth_settings.FIRST_SUPERUSER_PASSWORD
|
||||
),
|
||||
username=username,
|
||||
password=get_password_hash(password),
|
||||
is_superuser=True,
|
||||
is_active=True,
|
||||
last_login_at=None,
|
||||
|
|
@ -179,7 +181,15 @@ def create_super_user(
|
|||
|
||||
|
||||
def create_user_longterm_token(db: Session = Depends(get_session)) -> dict:
|
||||
super_user = create_super_user(db)
|
||||
settings_manager = get_settings_manager()
|
||||
username = settings_manager.auth_settings.FIRST_SUPERUSER
|
||||
password = settings_manager.auth_settings.FIRST_SUPERUSER_PASSWORD
|
||||
if not username or not password:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Missing first superuser credentials",
|
||||
)
|
||||
super_user = create_super_user(db=db, username=username, password=password)
|
||||
|
||||
access_token_expires_longterm = timedelta(days=365)
|
||||
access_token = create_token(
|
||||
|
|
|
|||
|
|
@ -1,2 +1,8 @@
|
|||
class Service:
|
||||
from abc import ABC
|
||||
|
||||
|
||||
class Service(ABC):
|
||||
name: str
|
||||
|
||||
def teardown(self):
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ from langflow.services.cache.manager import Subject
|
|||
from langflow.services.chat.utils import process_graph
|
||||
from langflow.interface.utils import pil_to_base64
|
||||
from langflow.services.schema import ServiceType
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
|
||||
|
||||
import asyncio
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ from fastapi import WebSocket
|
|||
from langflow.api.v1.schemas import ChatMessage
|
||||
from langflow.processing.base import get_result_and_steps
|
||||
from langflow.interface.utils import try_setting_streaming_options
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
|
||||
|
||||
async def process_graph(
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
from langflow.services.base import Service
|
||||
from langflow.services.database.models.user.crud import get_user_by_username
|
||||
from langflow.services.database.utils import Result, TableResults
|
||||
from langflow.services.utils import get_settings_manager
|
||||
from sqlalchemy import inspect
|
||||
import sqlalchemy as sa
|
||||
from sqlmodel import SQLModel, Session, create_engine
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
from alembic.config import Config
|
||||
from alembic import command
|
||||
from langflow.services.database import models # noqa
|
||||
|
|
@ -88,7 +89,7 @@ class DatabaseManager(Service):
|
|||
|
||||
for table in legacy_tables:
|
||||
if table in inspector.get_table_names():
|
||||
logger.warn(f"Legacy table exists: {table}")
|
||||
logger.warning(f"Legacy table exists: {table}")
|
||||
|
||||
return True
|
||||
|
||||
|
|
@ -159,3 +160,23 @@ class DatabaseManager(Service):
|
|||
)
|
||||
|
||||
logger.debug("Database and tables created successfully")
|
||||
|
||||
def teardown(self):
|
||||
logger.debug("Tearing down database")
|
||||
try:
|
||||
settings_manager = get_settings_manager()
|
||||
# remove the default superuser if auto_login is enabled
|
||||
# using the FIRST_SUPERUSER to get the user
|
||||
if settings_manager.auth_settings.AUTO_LOGIN:
|
||||
logger.debug("Removing default superuser")
|
||||
username = settings_manager.auth_settings.FIRST_SUPERUSER
|
||||
with Session(self.engine) as session:
|
||||
user = get_user_by_username(session, username)
|
||||
session.delete(user)
|
||||
session.commit()
|
||||
logger.debug("Default superuser removed")
|
||||
|
||||
except Exception as exc:
|
||||
logger.error(f"Error tearing down database: {exc}")
|
||||
|
||||
self.engine.dispose()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from dataclasses import dataclass
|
||||
from typing import TYPE_CHECKING
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
from contextlib import contextmanager
|
||||
from alembic.util.exc import CommandError
|
||||
from sqlmodel import Session
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
from langflow.services.schema import ServiceType
|
||||
from typing import TYPE_CHECKING, List, Optional
|
||||
from loguru import logger
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from langflow.services.factory import ServiceFactory
|
||||
|
|
@ -42,6 +43,7 @@ class ServiceManager:
|
|||
"""
|
||||
Create a new service given its name, handling dependencies.
|
||||
"""
|
||||
logger.debug(f"Create service {service_name}")
|
||||
self._validate_service_creation(service_name)
|
||||
|
||||
# Create dependencies first
|
||||
|
|
@ -74,9 +76,21 @@ class ServiceManager:
|
|||
Update a service by its name.
|
||||
"""
|
||||
if service_name in self.services:
|
||||
logger.debug(f"Update service {service_name}")
|
||||
self.services.pop(service_name, None)
|
||||
self.get(service_name)
|
||||
|
||||
def teardown(self):
|
||||
"""
|
||||
Teardown all the services.
|
||||
"""
|
||||
for service in self.services.values():
|
||||
logger.debug(f"Teardown service {service.name}")
|
||||
service.teardown()
|
||||
self.services = {}
|
||||
self.factories = {}
|
||||
self.dependencies = {}
|
||||
|
||||
|
||||
service_manager = ServiceManager()
|
||||
|
||||
|
|
@ -121,7 +135,7 @@ def initialize_session_manager():
|
|||
"""
|
||||
Initialize the session manager.
|
||||
"""
|
||||
from langflow.services.session import factory as session_manager_factory
|
||||
from langflow.services.session import factory as session_manager_factory # type: ignore
|
||||
from langflow.services.cache import factory as cache_factory
|
||||
|
||||
initialize_settings_manager()
|
||||
|
|
@ -134,3 +148,10 @@ def initialize_session_manager():
|
|||
session_manager_factory.SessionManagerFactory(),
|
||||
dependencies=[ServiceType.CACHE_MANAGER],
|
||||
)
|
||||
|
||||
|
||||
def teardown_services():
|
||||
"""
|
||||
Teardown all the services.
|
||||
"""
|
||||
service_manager.teardown()
|
||||
|
|
|
|||
|
|
@ -5,16 +5,17 @@ from langflow.services.settings.utils import read_secret_from_file, write_secret
|
|||
|
||||
from pydantic import BaseSettings, Field, validator
|
||||
from passlib.context import CryptContext
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
|
||||
|
||||
class AuthSettings(BaseSettings):
|
||||
# Login settings
|
||||
CONFIG_DIR: str
|
||||
SECRET_KEY: Optional[str] = Field(
|
||||
None,
|
||||
SECRET_KEY: str = Field(
|
||||
default="",
|
||||
description="Secret key for JWT. If not provided, a random one will be generated.",
|
||||
env="LANGFLOW_SECRET_KEY",
|
||||
allow_mutation=False,
|
||||
)
|
||||
ALGORITHM: str = "HS256"
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES: int = 60
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ from pathlib import Path
|
|||
|
||||
import yaml
|
||||
from pydantic import BaseSettings, root_validator, validator
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
|
||||
# BASE_COMPONENTS_PATH = str(Path(__file__).parent / "components")
|
||||
BASE_COMPONENTS_PATH = str(Path(__file__).parent.parent.parent / "components")
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from langflow.services.base import Service
|
||||
from langflow.services.settings.auth import AuthSettings
|
||||
from langflow.services.settings.base import Settings
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
import os
|
||||
import yaml
|
||||
|
||||
|
|
@ -35,5 +35,10 @@ class SettingsManager(Service):
|
|||
)
|
||||
|
||||
settings = Settings(**settings_dict)
|
||||
auth_settings = AuthSettings(CONFIG_DIR=settings.CONFIG_DIR)
|
||||
if not settings.CONFIG_DIR:
|
||||
raise ValueError("CONFIG_DIR must be set in settings")
|
||||
|
||||
auth_settings = AuthSettings(
|
||||
CONFIG_DIR=settings.CONFIG_DIR,
|
||||
)
|
||||
return cls(settings, auth_settings)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import os
|
|||
from pathlib import Path
|
||||
import platform
|
||||
|
||||
from langflow.utils.logger import logger
|
||||
from loguru import logger
|
||||
|
||||
|
||||
def set_secure_permissions(file_path):
|
||||
|
|
@ -43,5 +43,5 @@ def write_secret_to_file(path: Path, value: str) -> None:
|
|||
|
||||
|
||||
def read_secret_from_file(path: Path) -> str:
|
||||
with path.open("rb") as f:
|
||||
with path.open("r") as f:
|
||||
return f.read()
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
from langflow.services import ServiceType, service_manager
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Generator
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from langflow.services.database.manager import DatabaseManager
|
||||
from langflow.services.settings.manager import SettingsManager
|
||||
from langflow.services.chat.manager import ChatManager
|
||||
from sqlmodel import Session
|
||||
|
||||
|
||||
def get_settings_manager() -> "SettingsManager":
|
||||
|
|
@ -15,6 +17,10 @@ def get_db_manager() -> "DatabaseManager":
|
|||
return service_manager.get(ServiceType.DATABASE_MANAGER)
|
||||
|
||||
|
||||
def get_session():
|
||||
def get_session() -> Generator["Session", None, None]:
|
||||
db_manager = service_manager.get(ServiceType.DATABASE_MANAGER)
|
||||
yield from db_manager.get_session()
|
||||
|
||||
|
||||
def get_chat_manager() -> "ChatManager":
|
||||
return service_manager.get(ServiceType.CHAT_MANAGER)
|
||||
|
|
|
|||
|
|
@ -1,30 +1,35 @@
|
|||
import logging
|
||||
from typing import Optional
|
||||
from loguru import logger
|
||||
from pathlib import Path
|
||||
|
||||
from rich.logging import RichHandler
|
||||
|
||||
logger = logging.getLogger("langflow")
|
||||
|
||||
def configure(log_level: str = "DEBUG", log_file: Optional[Path] = None):
|
||||
log_format = "<green>{time:HH:mm:ss}</green> - <level>{level: <8}</level> - <level>{message}</level>"
|
||||
logger.remove() # Remove default handlers
|
||||
|
||||
def configure(log_level: str = "DEBUG", log_file: Path = None): # type: ignore
|
||||
log_format = "%(asctime)s - %(levelname)s - %(message)s"
|
||||
log_level_value = getattr(logging, log_level.upper(), logging.INFO)
|
||||
|
||||
logging.basicConfig(
|
||||
level=log_level_value,
|
||||
format=log_format,
|
||||
datefmt="[%X]",
|
||||
handlers=[RichHandler(rich_tracebacks=True)],
|
||||
# Configure loguru to use RichHandler
|
||||
logger.configure(
|
||||
handlers=[
|
||||
{
|
||||
"sink": RichHandler(rich_tracebacks=True, markup=True),
|
||||
"format": log_format,
|
||||
"level": log_level.upper(),
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
if log_file:
|
||||
log_file = Path(log_file)
|
||||
log_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
file_handler = logging.FileHandler(log_file)
|
||||
file_handler.setFormatter(logging.Formatter(log_format))
|
||||
logger.addHandler(file_handler)
|
||||
logger.add(
|
||||
sink=str(log_file),
|
||||
level=log_level.upper(),
|
||||
format=log_format,
|
||||
rotation="10 MB", # Log rotation based on file size
|
||||
)
|
||||
|
||||
logger.info(f"Logger set up with log level: {log_level_value}({log_level})")
|
||||
logger.info(f"Logger set up with log level: {log_level}")
|
||||
if log_file:
|
||||
logger.info(f"Log file: {log_file}")
|
||||
|
|
|
|||
|
|
@ -149,16 +149,21 @@ export default function Header(): JSX.Element {
|
|||
<DropdownMenuLabel>My Account</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
{isAdmin && (
|
||||
<DropdownMenuItem onClick={() => navigate("/admin")}>
|
||||
<DropdownMenuItem
|
||||
className="cursor-pointer"
|
||||
onClick={() => navigate("/admin")}
|
||||
>
|
||||
Admin Page
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
<DropdownMenuItem
|
||||
className="cursor-pointer"
|
||||
onClick={() => navigate("/account/settings")}
|
||||
>
|
||||
Profile Settings
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
className="cursor-pointer"
|
||||
onClick={() => {
|
||||
logout();
|
||||
navigate("/login");
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ export default function InputComponent({
|
|||
</Form.Control>
|
||||
) : (
|
||||
<Input
|
||||
type={password && !pwdVisible ? "password" : "text"}
|
||||
type="text"
|
||||
value={value}
|
||||
disabled={disabled}
|
||||
required={required}
|
||||
|
|
|
|||
|
|
@ -471,7 +471,7 @@ export async function updateUser(user_id: string, user: Users) {
|
|||
|
||||
export async function getApiKey() {
|
||||
try {
|
||||
const res = await api.get(`${BASE_URL_API}api_key`);
|
||||
const res = await api.get(`${BASE_URL_API}api_key/`);
|
||||
if (res.status === 200) {
|
||||
return res.data;
|
||||
}
|
||||
|
|
@ -483,7 +483,7 @@ export async function getApiKey() {
|
|||
|
||||
export async function createApiKey(name: string) {
|
||||
try {
|
||||
const res = await api.post(`${BASE_URL_API}api_key`, { name });
|
||||
const res = await api.post(`${BASE_URL_API}api_key/`, { name });
|
||||
if (res.status === 200) {
|
||||
return res.data;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ export default function LoginPage(): JSX.Element {
|
|||
|
||||
function signIn() {
|
||||
const user: LoginType = {
|
||||
username: username,
|
||||
password: password,
|
||||
username: username.trim(),
|
||||
password: password.trim(),
|
||||
};
|
||||
onLogin(user)
|
||||
.then((user) => {
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ export default function SignUp(): JSX.Element {
|
|||
function handleSignup(): void {
|
||||
const { username, password } = inputState;
|
||||
const newUser: UserInputType = {
|
||||
username,
|
||||
password,
|
||||
username: username.trim(),
|
||||
password: password.trim(),
|
||||
};
|
||||
addUser(newUser)
|
||||
.then((user) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue