Merge dev

This commit is contained in:
igorrCarvalho 2024-05-29 12:35:09 -03:00
commit 0eb6f6b212
386 changed files with 27625 additions and 32139 deletions

View file

@ -22,7 +22,8 @@ from sqlmodel import select
from langflow.main import setup_app
from langflow.services.database.models.folder.utils import create_default_folder_if_it_doesnt_exist
from langflow.services.database.utils import session_getter
from langflow.services.deps import get_db_service
from langflow.services.deps import get_db_service, get_settings_service, session_scope
from langflow.services.settings.constants import DEFAULT_SUPERUSER
from langflow.services.utils import initialize_services
from langflow.utils.logger import configure, logger
from langflow.utils.util import update_settings
@ -83,7 +84,6 @@ def run(
help="Path to the directory containing custom components.",
envvar="LANGFLOW_COMPONENTS_PATH",
),
config: str = typer.Option(Path(__file__).parent / "config.yaml", help="Path to the configuration file."),
# .env file param
env_file: Path = typer.Option(None, help="Path to the .env file containing environment variables."),
log_level: str = typer.Option("critical", help="Logging level.", envvar="LANGFLOW_LOG_LEVEL"),
@ -132,7 +132,6 @@ def run(
load_dotenv(env_file, override=True)
update_settings(
config,
dev=dev,
remove_api_keys=remove_api_keys,
cache=cache,
@ -510,6 +509,66 @@ def migration(
display_results(results)
@app.command()
def api_key(
log_level: str = typer.Option("error", help="Logging level.", envvar="LANGFLOW_LOG_LEVEL"),
):
"""
Creates an API key for the default superuser if AUTO_LOGIN is enabled.
Args:
log_level (str, optional): Logging level. Defaults to "error".
Returns:
None
"""
configure(log_level=log_level)
initialize_services()
settings_service = get_settings_service()
auth_settings = settings_service.auth_settings
if not auth_settings.AUTO_LOGIN:
typer.echo("Auto login is disabled. API keys cannot be created through the CLI.")
return
with session_scope() as session:
from langflow.services.database.models.user.model import User
superuser = session.exec(select(User).where(User.username == DEFAULT_SUPERUSER)).first()
if not superuser:
typer.echo("Default superuser not found. This command requires a superuser and AUTO_LOGIN to be enabled.")
return
from langflow.services.database.models.api_key import ApiKey, ApiKeyCreate
from langflow.services.database.models.api_key.crud import create_api_key, delete_api_key
api_key = session.exec(select(ApiKey).where(ApiKey.user_id == superuser.id)).first()
if api_key:
delete_api_key(session, api_key.id)
api_key_create = ApiKeyCreate(name="CLI")
unmasked_api_key = create_api_key(session, api_key_create, user_id=superuser.id)
session.commit()
# Create a banner to display the API key and tell the user it won't be shown again
api_key_banner(unmasked_api_key)
def api_key_banner(unmasked_api_key):
is_mac = platform.system() == "Darwin"
import pyperclip # type: ignore
pyperclip.copy(unmasked_api_key.api_key)
panel = Panel(
f"[bold]API Key Created Successfully:[/bold]\n\n"
f"[bold blue]{unmasked_api_key.api_key}[/bold blue]\n\n"
"This is the only time the API key will be displayed. \n"
"Make sure to store it in a secure location. \n\n"
f"The API key has been copied to your clipboard. [bold]{['Ctrl','Cmd'][is_mac]} + V[/bold] to paste it.",
box=box.ROUNDED,
border_style="blue",
expand=False,
)
console = Console()
console.print(panel)
def main():
with warnings.catch_warnings():
warnings.simplefilter("ignore")

View file

@ -140,7 +140,10 @@ def get_file_path_value(file_path):
# If the path is not in the cache dir, return empty string
# This is to prevent access to files outside the cache dir
# If the path is not a file, return empty string
if not path.exists() or not str(path).startswith(user_cache_dir("langflow", "langflow")):
if not str(path).startswith(user_cache_dir("langflow", "langflow")):
return ""
if not path.exists():
return ""
return file_path

View file

@ -1,13 +1,12 @@
from typing import TYPE_CHECKING, Any, Dict, List, Optional
from uuid import UUID
from langchain.schema import AgentAction, AgentFinish
from langchain_core.callbacks.base import AsyncCallbackHandler
from loguru import logger
from langflow.api.v1.schemas import ChatResponse, PromptResponse
from langflow.services.deps import get_chat_service, get_socket_service
from langflow.utils.util import remove_ansi_escape_codes
from langchain_core.agents import AgentAction, AgentFinish
if TYPE_CHECKING:
from langflow.services.socket.service import SocketIOService

View file

@ -53,7 +53,7 @@ async def try_running_celery_task(vertex, user_id):
@router.post("/build/{flow_id}/vertices", response_model=VerticesOrderResponse)
async def retrieve_vertices_order(
flow_id: str,
flow_id: uuid.UUID,
data: Optional[Annotated[Optional[FlowDataRequest], Body(embed=True)]] = None,
stop_component_id: Optional[str] = None,
start_component_id: Optional[str] = None,
@ -78,12 +78,13 @@ async def retrieve_vertices_order(
HTTPException: If there is an error checking the build status.
"""
try:
flow_id_str = str(flow_id)
# First, we need to check if the flow_id is in the cache
if not data:
graph = await build_and_cache_graph_from_db(flow_id=flow_id, session=session, chat_service=chat_service)
graph = await build_and_cache_graph_from_db(flow_id=flow_id_str, session=session, chat_service=chat_service)
else:
graph = await build_and_cache_graph_from_data(
flow_id=flow_id, graph_data=data.model_dump(), chat_service=chat_service
flow_id=flow_id_str, graph_data=data.model_dump(), chat_service=chat_service
)
graph.validate_stream()
if stop_component_id or start_component_id:
@ -119,7 +120,7 @@ async def retrieve_vertices_order(
@router.post("/build/{flow_id}/vertices/{vertex_id}")
async def build_vertex(
flow_id: str,
flow_id: uuid.UUID,
vertex_id: str,
background_tasks: BackgroundTasks,
inputs: Annotated[Optional[InputValueRequest], Body(embed=True)] = None,
@ -143,27 +144,25 @@ async def build_vertex(
HTTPException: If there is an error building the vertex.
"""
flow_id_str = str(flow_id)
start_time = time.perf_counter()
next_runnable_vertices = []
top_level_vertices = []
try:
start_time = time.perf_counter()
cache = await chat_service.get_cache(flow_id)
cache = await chat_service.get_cache(flow_id_str)
if not cache:
# If there's no cache
logger.warning(f"No cache found for {flow_id}. Building graph starting at {vertex_id}")
logger.warning(f"No cache found for {flow_id_str}. Building graph starting at {vertex_id}")
graph = await build_and_cache_graph_from_db(
flow_id=flow_id, session=next(get_session()), chat_service=chat_service
flow_id=flow_id_str, session=next(get_session()), chat_service=chat_service
)
else:
graph = cache.get("result")
result_data_response = ResultDataResponse(results={})
duration = ""
vertex = graph.get_vertex(vertex_id)
try:
lock = chat_service._cache_locks[flow_id]
set_cache_coro = partial(chat_service.set_cache, flow_id=flow_id)
lock = chat_service._cache_locks[flow_id_str]
set_cache_coro = partial(chat_service.set_cache, flow_id=flow_id_str)
(
next_runnable_vertices,
top_level_vertices,
@ -189,13 +188,13 @@ async def build_vertex(
artifacts = {}
# If there's an error building the vertex
# we need to clear the cache
await chat_service.clear_cache(flow_id)
await chat_service.clear_cache(flow_id_str)
# Log the vertex build
if not vertex.will_stream:
background_tasks.add_task(
log_vertex_build,
flow_id=flow_id,
flow_id=flow_id_str,
vertex_id=vertex_id,
valid=valid,
params=params,
@ -212,7 +211,7 @@ async def build_vertex(
inactivated_vertices = list(graph.inactivated_vertices)
graph.reset_inactivated_vertices()
graph.reset_activated_vertices()
await chat_service.set_cache(flow_id, graph)
await chat_service.set_cache(flow_id_str, graph)
# graph.stop_vertex tells us if the user asked
# to stop the build of the graph at a certain vertex
@ -240,7 +239,7 @@ async def build_vertex(
@router.get("/build/{flow_id}/{vertex_id}/stream", response_class=StreamingResponse)
async def build_vertex_stream(
flow_id: str,
flow_id: uuid.UUID,
vertex_id: str,
session_id: Optional[str] = None,
chat_service: "ChatService" = Depends(get_chat_service),
@ -272,21 +271,22 @@ async def build_vertex_stream(
HTTPException: If an error occurs while building the vertex.
"""
try:
flow_id_str = str(flow_id)
async def stream_vertex():
try:
if not session_id:
cache = await chat_service.get_cache(flow_id)
cache = await chat_service.get_cache(flow_id_str)
if not cache:
# If there's no cache
raise ValueError(f"No cache found for {flow_id}.")
raise ValueError(f"No cache found for {flow_id_str}.")
else:
graph = cache.get("result")
else:
session_data = await session_service.load_session(session_id, flow_id=flow_id)
session_data = await session_service.load_session(session_id, flow_id=flow_id_str)
graph, artifacts = session_data if session_data else (None, None)
if not graph:
raise ValueError(f"No graph found for {flow_id}.")
raise ValueError(f"No graph found for {flow_id_str}.")
vertex: "InterfaceVertex" = graph.get_vertex(vertex_id)
if not hasattr(vertex, "stream"):

View file

@ -1,10 +1,11 @@
from http import HTTPStatus
from typing import Annotated, List, Optional, Union
from uuid import UUID
import sqlalchemy as sa
from fastapi import APIRouter, Body, Depends, HTTPException, UploadFile, status
from loguru import logger
from sqlmodel import Session, col, select
from sqlmodel import Session, select
from langflow.api.utils import update_frontend_node_with_template_values
from langflow.api.v1.schemas import (
@ -17,11 +18,9 @@ from langflow.api.v1.schemas import (
UpdateCustomComponentRequest,
UploadFileResponse,
)
from langflow.custom import CustomComponent
from langflow.custom.utils import build_custom_component_template
from langflow.graph.graph.base import Graph
from langflow.graph.schema import RunOutputs
from langflow.interface.custom.custom_component import CustomComponent
from langflow.interface.custom.directory_reader import DirectoryReader
from langflow.interface.custom.utils import build_custom_component_template
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
@ -44,7 +43,7 @@ def get_all(
logger.debug("Building langchain types dict")
try:
all_types_dict = get_all_types_dict(settings_service.settings.COMPONENTS_PATH)
all_types_dict = get_all_types_dict(settings_service.settings.components_path)
return all_types_dict
except Exception as exc:
logger.exception(exc)
@ -54,7 +53,7 @@ def get_all(
@router.post("/run/{flow_id}", response_model=RunResponse, response_model_exclude_none=True)
async def simplified_run_flow(
db: Annotated[Session, Depends(get_session)],
flow_id: str,
flow_id: UUID,
input_request: SimplifiedAPIRequest = SimplifiedAPIRequest(),
stream: bool = False,
api_key_user: User = Depends(api_key_security),
@ -111,26 +110,26 @@ async def simplified_run_flow(
session_id = input_request.session_id
try:
task_result: List[RunOutputs] = []
flow_id_str = str(flow_id)
artifacts = {}
if input_request.session_id:
session_data = await session_service.load_session(input_request.session_id, flow_id=flow_id)
session_data = await session_service.load_session(input_request.session_id, flow_id=flow_id_str)
graph, artifacts = session_data if session_data else (None, None)
if graph is None:
raise ValueError(f"Session {input_request.session_id} not found")
else:
# Get the flow that matches the flow_id and belongs to the user
# flow = session.query(Flow).filter(Flow.id == flow_id).filter(Flow.user_id == api_key_user.id).first()
flow = db.exec(select(Flow).where(Flow.id == flow_id).where(Flow.user_id == api_key_user.id)).first()
flow = db.exec(select(Flow).where(Flow.id == flow_id_str).where(Flow.user_id == api_key_user.id)).first()
if flow is None:
raise ValueError(f"Flow {flow_id} not found")
raise ValueError(f"Flow {flow_id_str} not found")
if flow.data is None:
raise ValueError(f"Flow {flow_id} has no data")
raise ValueError(f"Flow {flow_id_str} has no data")
graph_data = flow.data
graph_data = process_tweaks(graph_data, input_request.tweaks or {}, stream=stream)
graph = Graph.from_payload(graph_data, flow_id=flow_id, user_id=str(api_key_user.id))
graph = Graph.from_payload(graph_data, flow_id=flow_id_str, user_id=str(api_key_user.id))
inputs = [
InputValueRequest(components=[], input_value=input_request.input_value, type=input_request.input_type)
]
@ -153,7 +152,7 @@ async def simplified_run_flow(
]
task_result, session_id = await run_graph_internal(
graph=graph,
flow_id=flow_id,
flow_id=flow_id_str,
session_id=input_request.session_id,
inputs=inputs,
outputs=outputs,
@ -166,12 +165,12 @@ async def simplified_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} is not a valid UUID")
logger.error(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
except ValueError as exc:
if f"Flow {flow_id} not found" in str(exc):
logger.error(f"Flow {flow_id} not found")
if f"Flow {flow_id_str} not found" in str(exc):
logger.error(f"Flow {flow_id_str} not found")
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc
elif f"Session {session_id} not found" in str(exc):
logger.error(f"Session {session_id} not found")
@ -187,7 +186,7 @@ async def simplified_run_flow(
@router.post("/run/advanced/{flow_id}", response_model=RunResponse, response_model_exclude_none=True)
async def experimental_run_flow(
session: Annotated[Session, Depends(get_session)],
flow_id: str,
flow_id: UUID,
inputs: Optional[List[InputValueRequest]] = [InputValueRequest(components=[], input_value="")],
outputs: Optional[List[str]] = [],
tweaks: Annotated[Optional[Tweaks], Body(embed=True)] = None, # noqa: F821
@ -235,31 +234,33 @@ async def experimental_run_flow(
This endpoint facilitates complex flow executions with customized inputs, outputs, and configurations, catering to diverse application requirements.
"""
try:
flow_id_str = str(flow_id)
if outputs is None:
outputs = []
task_result: List[RunOutputs] = []
artifacts = {}
if session_id:
session_data = await session_service.load_session(session_id, flow_id=flow_id)
session_data = await session_service.load_session(session_id, flow_id=flow_id_str)
graph, artifacts = session_data if session_data else (None, None)
if graph is None:
raise ValueError(f"Session {session_id} not found")
else:
# Get the flow that matches the flow_id and belongs to the user
# flow = session.query(Flow).filter(Flow.id == flow_id).filter(Flow.user_id == api_key_user.id).first()
flow = session.exec(select(Flow).where(Flow.id == flow_id).where(Flow.user_id == api_key_user.id)).first()
flow = session.exec(
select(Flow).where(Flow.id == flow_id_str).where(Flow.user_id == api_key_user.id)
).first()
if flow is None:
raise ValueError(f"Flow {flow_id} not found")
raise ValueError(f"Flow {flow_id_str} not found")
if flow.data is None:
raise ValueError(f"Flow {flow_id} has no data")
raise ValueError(f"Flow {flow_id_str} has no data")
graph_data = flow.data
graph_data = process_tweaks(graph_data, tweaks or {})
graph = Graph.from_payload(graph_data, flow_id=flow_id)
graph = Graph.from_payload(graph_data, flow_id=flow_id_str)
task_result, session_id = await run_graph_internal(
graph=graph,
flow_id=flow_id,
flow_id=flow_id_str,
session_id=session_id,
inputs=inputs,
outputs=outputs,
@ -272,12 +273,12 @@ 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} is not a valid UUID")
logger.error(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
except ValueError as exc:
if f"Flow {flow_id} not found" in str(exc):
logger.error(f"Flow {flow_id} not found")
if f"Flow {flow_id_str} not found" in str(exc):
logger.error(f"Flow {flow_id_str} not found")
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc
elif f"Session {session_id} not found" in str(exc):
logger.error(f"Session {session_id} not found")
@ -357,13 +358,14 @@ async def get_task_status(task_id: str):
)
async def create_upload_file(
file: UploadFile,
flow_id: str,
flow_id: UUID,
):
try:
file_path = save_uploaded_file(file, folder_name=flow_id)
flow_id_str = str(flow_id)
file_path = save_uploaded_file(file, folder_name=flow_id_str)
return UploadFileResponse(
flowId=flow_id,
flowId=flow_id_str,
file_path=file_path,
)
except Exception as exc:
@ -400,23 +402,6 @@ async def custom_component(
return built_frontend_node
@router.post("/custom_component/reload", status_code=HTTPStatus.OK)
async def reload_custom_component(path: str, user: User = Depends(get_current_active_user)):
from langflow.interface.custom.utils import build_custom_component_template
try:
reader = DirectoryReader("")
valid, content = reader.process_file(path)
if not valid:
raise ValueError(content)
extractor = CustomComponent(code=content)
frontend_node, _ = build_custom_component_template(extractor, user_id=user.id)
return frontend_node
except Exception as exc:
raise HTTPException(status_code=400, detail=str(exc))
@router.post("/custom_component/update", status_code=HTTPStatus.OK)
async def custom_component_update(
code_request: UpdateCustomComponentRequest,

View file

@ -1,6 +1,7 @@
import hashlib
from http import HTTPStatus
from io import BytesIO
from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, UploadFile
from fastapi.responses import StreamingResponse
@ -20,38 +21,41 @@ router = APIRouter(tags=["Files"], prefix="/files")
# then finds it in the database and returns it while
# using the current user as the owner
def get_flow_id(
flow_id: str,
flow_id: UUID,
current_user=Depends(get_current_active_user),
session=Depends(get_session),
):
flow_id_str = str(flow_id)
# AttributeError: 'SelectOfScalar' object has no attribute 'first'
flow = session.get(Flow, flow_id)
flow = session.get(Flow, flow_id_str)
if not flow:
raise HTTPException(status_code=404, detail="Flow not found")
if flow.user_id != current_user.id:
raise HTTPException(status_code=403, detail="You don't have access to this flow")
return flow_id
return flow_id_str
@router.post("/upload/{flow_id}", status_code=HTTPStatus.CREATED)
async def upload_file(
file: UploadFile,
flow_id: str = Depends(get_flow_id),
flow_id: UUID = Depends(get_flow_id),
storage_service: StorageService = Depends(get_storage_service),
):
try:
flow_id_str = str(flow_id)
file_content = await file.read()
file_name = file.filename or hashlib.sha256(file_content).hexdigest()
folder = flow_id
folder = flow_id_str
await storage_service.save_file(flow_id=folder, file_name=file_name, data=file_content)
return UploadFileResponse(flowId=flow_id, file_path=f"{folder}/{file_name}")
return UploadFileResponse(flowId=flow_id_str, file_path=f"{folder}/{file_name}")
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.get("/download/{flow_id}/{file_name}")
async def download_file(file_name: str, flow_id: str, storage_service: StorageService = Depends(get_storage_service)):
async def download_file(file_name: str, flow_id: UUID, storage_service: StorageService = Depends(get_storage_service)):
try:
flow_id_str = str(flow_id)
extension = file_name.split(".")[-1]
if not extension:
@ -62,7 +66,7 @@ async def download_file(file_name: str, flow_id: str, storage_service: StorageSe
if not content_type:
raise HTTPException(status_code=500, detail=f"Content type not found for extension {extension}")
file_content = await storage_service.get_file(flow_id=flow_id, file_name=file_name)
file_content = await storage_service.get_file(flow_id=flow_id_str, file_name=file_name)
headers = {
"Content-Disposition": f"attachment; filename={file_name} filename*=UTF-8''{file_name}",
"Content-Type": "application/octet-stream",
@ -74,9 +78,10 @@ async def download_file(file_name: str, flow_id: str, storage_service: StorageSe
@router.get("/images/{flow_id}/{file_name}")
async def download_image(file_name: str, flow_id: str, storage_service: StorageService = Depends(get_storage_service)):
async def download_image(file_name: str, flow_id: UUID, storage_service: StorageService = Depends(get_storage_service)):
try:
extension = file_name.split(".")[-1]
flow_id_str = str(flow_id)
if not extension:
raise HTTPException(status_code=500, detail=f"Extension not found for file {file_name}")
@ -88,7 +93,7 @@ async def download_image(file_name: str, flow_id: str, storage_service: StorageS
elif not content_type.startswith("image"):
raise HTTPException(status_code=500, detail=f"Content type {content_type} is not an image")
file_content = await storage_service.get_file(flow_id=flow_id, file_name=file_name)
file_content = await storage_service.get_file(flow_id=flow_id_str, file_name=file_name)
return StreamingResponse(BytesIO(file_content), media_type=content_type)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@ -96,10 +101,11 @@ async def download_image(file_name: str, flow_id: str, storage_service: StorageS
@router.get("/list/{flow_id}")
async def list_files(
flow_id: str = Depends(get_flow_id), storage_service: StorageService = Depends(get_storage_service)
flow_id: UUID = Depends(get_flow_id), storage_service: StorageService = Depends(get_storage_service)
):
try:
files = await storage_service.list_files(flow_id=flow_id)
flow_id_str = str(flow_id)
files = await storage_service.list_files(flow_id=flow_id_str)
return {"files": files}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@ -107,10 +113,11 @@ async def list_files(
@router.delete("/delete/{flow_id}/{file_name}")
async def delete_file(
file_name: str, flow_id: str = Depends(get_flow_id), storage_service: StorageService = Depends(get_storage_service)
file_name: str, flow_id: UUID = Depends(get_flow_id), storage_service: StorageService = Depends(get_storage_service)
):
try:
await storage_service.delete_file(flow_id=flow_id, file_name=file_name)
flow_id_str = str(flow_id)
await storage_service.delete_file(flow_id=flow_id_str, file_name=file_name)
return {"message": f"File {file_name} deleted successfully"}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))

View file

@ -2,7 +2,6 @@ from datetime import datetime, timezone
from typing import List
from uuid import UUID
from langflow.services.database.models.folder.constants import DEFAULT_FOLDER_NAME
import orjson
from fastapi import APIRouter, Depends, File, HTTPException, UploadFile
from fastapi.encoders import jsonable_encoder
@ -14,6 +13,7 @@ from langflow.api.v1.schemas import FlowListCreate, FlowListIds, FlowListRead
from langflow.initial_setup.setup import STARTER_FOLDER_NAME
from langflow.services.auth.utils import get_current_active_user
from langflow.services.database.models.flow import Flow, FlowCreate, FlowRead, FlowUpdate
from langflow.services.database.models.folder.constants import DEFAULT_FOLDER_NAME
from langflow.services.database.models.folder.model import Folder
from langflow.services.database.models.user.model import User
from langflow.services.deps import get_session, get_settings_service
@ -38,7 +38,10 @@ def create_flow(
db_flow.updated_at = datetime.now(timezone.utc)
if db_flow.folder_id is None:
default_folder = session.exec(select(Folder).where(Folder.name == DEFAULT_FOLDER_NAME)).first()
# Make sure flows always have a folder
default_folder = session.exec(
select(Folder).where(Folder.name == DEFAULT_FOLDER_NAME, Folder.user_id == current_user.id)
).first()
if default_folder:
db_flow.folder_id = default_folder.id
@ -71,12 +74,9 @@ def read_flows(
flow_ids = [flow.id for flow in flows]
# with the session get the flows that DO NOT have a user_id
try:
example_flows = session.exec(
select(Flow).where(
Flow.user_id == None, # noqa
Flow.folder.has(Folder.name == STARTER_FOLDER_NAME),
)
).all()
folder = session.exec(select(Folder).where(Folder.name == STARTER_FOLDER_NAME)).first()
example_flows = folder.flows if folder else []
for example_flow in example_flows:
if example_flow.id not in flow_ids:
flows.append(example_flow) # type: ignore
@ -130,7 +130,7 @@ def update_flow(
if not db_flow:
raise HTTPException(status_code=404, detail="Flow not found")
flow_data = flow.model_dump(exclude_unset=True)
if settings_service.settings.REMOVE_API_KEYS:
if settings_service.settings.remove_api_keys:
flow_data = remove_api_keys(flow_data)
for key, value in flow_data.items():
if value is not None:

View file

@ -1,17 +1,16 @@
from typing import List
from uuid import UUID
from fastapi import APIRouter, Depends, File, HTTPException, Response, UploadFile, status
from langflow.api.v1.flows import create_flows
from langflow.api.v1.schemas import FlowListCreate, FlowListReadWithFolderName
from langflow.initial_setup.setup import STARTER_FOLDER_NAME
from langflow.services.database.models.flow.model import Flow, FlowCreate, FlowRead
from langflow.services.database.models.folder.constants import DEFAULT_FOLDER_NAME
import orjson
from sqlalchemy import update
from fastapi import APIRouter, Depends, File, HTTPException, Response, UploadFile, status
from sqlalchemy import or_, update
from sqlmodel import Session, select
from langflow.api.v1.flows import create_flows
from langflow.api.v1.schemas import FlowListCreate, FlowListReadWithFolderName
from langflow.services.auth.utils import get_current_active_user
from langflow.services.database.models.flow.model import Flow, FlowCreate, FlowRead
from langflow.services.database.models.folder.constants import DEFAULT_FOLDER_NAME
from langflow.services.database.models.folder.model import (
Folder,
FolderCreate,
@ -35,20 +34,32 @@ def create_folder(
try:
new_folder = Folder.model_validate(folder, from_attributes=True)
new_folder.user_id = current_user.id
folder_results = session.exec(
select(Folder).where(
Folder.name.like(f"{new_folder.name}%"), # type: ignore
Folder.user_id == current_user.id,
)
)
existing_folder_names = [folder.name for folder in folder_results]
if existing_folder_names:
new_folder.name = f"{new_folder.name} ({len(existing_folder_names) + 1})"
session.add(new_folder)
session.commit()
session.refresh(new_folder)
if folder.components_list.__len__() > 0:
if folder.components_list:
update_statement_components = (
update(Flow).where(Flow.id.in_(folder.components_list)).values(folder_id=new_folder.id)
update(Flow).where(Flow.id.in_(folder.components_list)).values(folder_id=new_folder.id) # type: ignore
)
session.exec(update_statement_components)
session.exec(update_statement_components) # type: ignore
session.commit()
if folder.flows_list.__len__() > 0:
update_statement_flows = update(Flow).where(Flow.id.in_(folder.flows_list)).values(folder_id=new_folder.id)
session.exec(update_statement_flows)
if folder.flows_list:
update_statement_flows = update(Flow).where(Flow.id.in_(folder.flows_list)).values(folder_id=new_folder.id) # type: ignore
session.exec(update_statement_flows) # type: ignore
session.commit()
return new_folder
@ -63,16 +74,11 @@ def read_folders(
current_user: User = Depends(get_current_active_user),
):
try:
folders = session.exec(select(Folder).where(Folder.user_id == current_user.id)).all()
return folders
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.get("/starter-projects", response_model=FolderReadWithFlows, status_code=200)
def read_starter_folders(*, session: Session = Depends(get_session)):
try:
folders = session.exec(select(Folder).where(Folder.name == STARTER_FOLDER_NAME)).first()
folders = session.exec(
select(Folder).where(
or_(Folder.user_id == current_user.id, Folder.user_id == None) # type: ignore # noqa: E711
)
).all()
return folders
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@ -89,7 +95,6 @@ def read_folder(
folder = session.exec(select(Folder).where(Folder.id == folder_id, Folder.user_id == current_user.id)).first()
if not folder:
raise HTTPException(status_code=404, detail="Folder not found")
folder.flows = session.exec(select(Flow).where(Flow.folder_id == folder_id)).all()
return folder
except Exception as e:
if "No result found" in str(e):
@ -128,16 +133,16 @@ def update_folder(
my_collection_folder = session.exec(select(Folder).where(Folder.name == DEFAULT_FOLDER_NAME)).first()
if my_collection_folder:
update_statement_my_collection = (
update(Flow).where(Flow.id.in_(excluded_flows)).values(folder_id=my_collection_folder.id)
update(Flow).where(Flow.id.in_(excluded_flows)).values(folder_id=my_collection_folder.id) # type: ignore
)
session.exec(update_statement_my_collection)
session.exec(update_statement_my_collection) # type: ignore
session.commit()
if concat_folder_components.__len__() > 0:
if concat_folder_components:
update_statement_components = (
update(Flow).where(Flow.id.in_(concat_folder_components)).values(folder_id=existing_folder.id)
update(Flow).where(Flow.id.in_(concat_folder_components)).values(folder_id=existing_folder.id) # type: ignore
)
session.exec(update_statement_components)
session.exec(update_statement_components) # type: ignore
session.commit()
return existing_folder
@ -177,20 +182,8 @@ async def download_file(
):
"""Download all flows from folder."""
try:
flows = session.exec(
select(Flow).distinct().join(Folder).where(Flow.folder_id == folder_id, Folder.user_id == current_user.id)
).all()
folder_name = (
session.exec(select(Folder).where(Folder.id == folder_id, Folder.user_id == current_user.id)).first().name
)
folder_description = (
session.exec(select(Folder).where(Folder.id == folder_id, Folder.user_id == current_user.id))
.first()
.description
)
if not flows:
flows = []
return FlowListReadWithFolderName(flows=flows, folder_name=folder_name, folder_description=folder_description)
folder = session.exec(select(Folder).where(Folder.id == folder_id, Folder.user_id == current_user.id)).first()
return folder
except Exception as e:
if "No result found" in str(e):
raise HTTPException(status_code=404, detail="Folder not found")
@ -208,16 +201,19 @@ async def upload_file(
contents = await file.read()
data = orjson.loads(contents)
if data.__len__() == 0:
if not data:
raise HTTPException(status_code=400, detail="No flows found in the file")
folder_results = session.exec(
select(Folder).where(Folder.name.like(f"{data['folder_name']}%"), Folder.user_id == current_user.id)
select(Folder).where(
Folder.name == data["folder_name"],
Folder.user_id == current_user.id,
)
)
existing_folder_names = [folder.name for folder in folder_results]
if existing_folder_names.__len__() > 0:
data["folder_name"] = f"{data['folder_name']} ({existing_folder_names.__len__() + 1})"
if existing_folder_names:
data["folder_name"] = f"{data['folder_name']} ({len(existing_folder_names) + 1})"
folder = FolderCreate(name=data["folder_name"], description=data["folder_description"])

View file

@ -149,8 +149,8 @@ class FlowListRead(BaseModel):
class FlowListReadWithFolderName(BaseModel):
flows: List[FlowRead]
folder_name: str
folder_description: str
name: str
description: str
class InitResponse(BaseModel):

View file

@ -54,7 +54,7 @@ def check_if_store_is_enabled(
settings_service=Depends(get_settings_service),
):
return {
"enabled": settings_service.settings.STORE,
"enabled": settings_service.settings.store,
}

View file

@ -1,8 +1,8 @@
from typing import Optional, Union
from langflow.custom import CustomComponent
from langflow.field_typing import Text
from langflow.helpers.record import records_to_text
from langflow.interface.custom.custom_component import CustomComponent
from langflow.memory import store_message
from langflow.schema import Record

View file

@ -1,8 +1,8 @@
from typing import Optional
from langflow.custom import CustomComponent
from langflow.field_typing import Text
from langflow.helpers.record import records_to_text
from langflow.interface.custom.custom_component import CustomComponent
from langflow.schema.schema import Record

View file

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

View file

@ -1,10 +1,10 @@
from fastapi import HTTPException
from langchain.prompts import PromptTemplate
from loguru import logger
from langflow.api.v1.base import INVALID_NAMES, check_input_variables
from langflow.interface.utils import extract_input_variables_from_prompt
from langflow.template.field.prompt import DefaultPromptField
from langchain_core.prompts import PromptTemplate
def validate_prompt(prompt_template: str, silent_errors: bool = False) -> list[str]:

View file

@ -1,52 +0,0 @@
from typing import Callable, List, Optional, Union
from langchain.agents import AgentExecutor, AgentType, initialize_agent, types
from langflow.field_typing import BaseChatMemory, BaseLanguageModel, Tool
from langflow.interface.custom.custom_component import CustomComponent
class AgentInitializerComponent(CustomComponent):
display_name: str = "Agent Initializer"
description: str = "Initialize a Langchain Agent."
documentation: str = "https://python.langchain.com/docs/modules/agents/agent_types/"
def build_config(self):
agents = list(types.AGENT_TO_CLASS.keys())
# field_type and required are optional
return {
"agent": {"options": agents, "value": agents[0], "display_name": "Agent Type"},
"max_iterations": {"display_name": "Max Iterations", "value": 10},
"memory": {"display_name": "Memory"},
"tools": {"display_name": "Tools"},
"llm": {"display_name": "Language Model"},
"code": {"advanced": True},
}
def build(
self,
agent: str,
llm: BaseLanguageModel,
tools: List[Tool],
max_iterations: int,
memory: Optional[BaseChatMemory] = None,
) -> Union[AgentExecutor, Callable]:
agent = AgentType(agent)
if memory:
return initialize_agent(
tools=tools,
llm=llm,
agent=agent,
memory=memory,
return_intermediate_steps=True,
handle_parsing_errors=True,
max_iterations=max_iterations,
)
return initialize_agent(
tools=tools,
llm=llm,
agent=agent,
return_intermediate_steps=True,
handle_parsing_errors=True,
max_iterations=max_iterations,
)

View file

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

View file

@ -1,96 +0,0 @@
from typing import List, Optional
from langchain.agents.agent import AgentExecutor
from langchain.agents.agent_toolkits.conversational_retrieval.openai_functions import _get_default_system_message
from langchain.agents.openai_functions_agent.base import OpenAIFunctionsAgent
from langchain.memory.token_buffer import ConversationTokenBufferMemory
from langchain.prompts import SystemMessagePromptTemplate
from langchain.prompts.chat import MessagesPlaceholder
from langchain.schema.memory import BaseMemory
from langchain.tools import Tool
from langchain_openai import ChatOpenAI
from langflow.field_typing.range_spec import RangeSpec
from langflow.interface.custom.custom_component import CustomComponent
class ConversationalAgent(CustomComponent):
display_name: str = "OpenAI Conversational Agent"
description: str = "Conversational Agent that can use OpenAI's function calling API"
icon = "OpenAI"
def build_config(self):
openai_function_models = [
"gpt-4-turbo-preview",
"gpt-4-0125-preview",
"gpt-4-1106-preview",
"gpt-4-vision-preview",
"gpt-3.5-turbo-0125",
"gpt-3.5-turbo-1106",
]
return {
"tools": {"display_name": "Tools"},
"memory": {"display_name": "Memory"},
"system_message": {"display_name": "System Message"},
"max_token_limit": {"display_name": "Max Token Limit"},
"model_name": {
"display_name": "Model Name",
"options": openai_function_models,
"value": openai_function_models[0],
},
"code": {"show": False},
"temperature": {
"display_name": "Temperature",
"value": 0.2,
"rangeSpec": RangeSpec(min=0, max=2, step=0.1),
},
}
def build(
self,
model_name: str,
openai_api_key: str,
tools: List[Tool],
openai_api_base: Optional[str] = None,
memory: Optional[BaseMemory] = None,
system_message: Optional[SystemMessagePromptTemplate] = None,
max_token_limit: int = 2000,
temperature: float = 0.9,
) -> AgentExecutor:
llm = ChatOpenAI(
model=model_name,
api_key=openai_api_key,
base_url=openai_api_base,
max_tokens=max_token_limit,
temperature=temperature,
)
if not memory:
memory_key = "chat_history"
memory = ConversationTokenBufferMemory(
memory_key=memory_key,
return_messages=True,
output_key="output",
llm=llm,
max_token_limit=max_token_limit,
)
else:
memory_key = memory.memory_key # type: ignore
_system_message = system_message or _get_default_system_message()
prompt = OpenAIFunctionsAgent.create_prompt(
system_message=_system_message, # type: ignore
extra_prompt_messages=[MessagesPlaceholder(variable_name=memory_key)],
)
agent = OpenAIFunctionsAgent(
llm=llm,
tools=tools,
prompt=prompt, # type: ignore
)
return AgentExecutor(
agent=agent,
tools=tools, # type: ignore
memory=memory,
verbose=True,
return_intermediate_steps=True,
handle_parsing_errors=True,
)

View file

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

View file

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

View file

@ -4,7 +4,7 @@ from langchain.agents import create_vectorstore_router_agent
from langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreRouterToolkit
from langchain_core.language_models.base import BaseLanguageModel
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
class VectorStoreRouterAgentComponent(CustomComponent):

View file

@ -1,17 +1,13 @@
from .AgentInitializer import AgentInitializerComponent
from .CSVAgent import CSVAgentComponent
from .JsonAgent import JsonAgentComponent
from .OpenAIConversationalAgent import ConversationalAgent
from .SQLAgent import SQLAgentComponent
from .VectorStoreAgent import VectorStoreAgentComponent
from .VectorStoreRouterAgent import VectorStoreRouterAgentComponent
from .XMLAgent import XMLAgentComponent
__all__ = [
"AgentInitializerComponent",
"CSVAgentComponent",
"JsonAgentComponent",
"ConversationalAgent",
"SQLAgentComponent",
"VectorStoreAgentComponent",
"VectorStoreRouterAgentComponent",

View file

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

View file

@ -1,11 +1,11 @@
from typing import Optional
from langchain.chains.llm import LLMChain
from langflow.field_typing import BaseLanguageModel, BaseMemory, Text
from langflow.interface.custom.custom_component import CustomComponent
from langchain_core.prompts import PromptTemplate
from langflow.custom import CustomComponent
from langflow.field_typing import BaseLanguageModel, BaseMemory, Text
class LLMChainComponent(CustomComponent):
display_name = "LLMChain"

View file

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

View file

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

View file

@ -3,8 +3,8 @@ from typing import Optional
from langchain.chains.retrieval_qa.base import RetrievalQA
from langchain_core.documents import Document
from langflow.custom import CustomComponent
from langflow.field_typing import BaseLanguageModel, BaseMemory, BaseRetriever, Text
from langflow.interface.custom.custom_component import CustomComponent
from langflow.schema.schema import Record

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,7 +1,8 @@
from langchain.embeddings.base import Embeddings
from langchain_community.embeddings import AzureOpenAIEmbeddings
from langchain_core.embeddings import Embeddings
from langchain_openai import AzureOpenAIEmbeddings
from pydantic.v1 import SecretStr
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
class AzureOpenAIEmbeddingsComponent(CustomComponent):
@ -52,12 +53,16 @@ class AzureOpenAIEmbeddingsComponent(CustomComponent):
api_version: str,
api_key: str,
) -> Embeddings:
if api_key:
azure_api_key = SecretStr(api_key)
else:
azure_api_key = None
try:
embeddings = AzureOpenAIEmbeddings(
azure_endpoint=azure_endpoint,
azure_deployment=azure_deployment,
api_version=api_version,
api_key=api_key,
api_key=azure_api_key,
)
except Exception as e:

View file

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

View file

@ -3,7 +3,7 @@ from typing import Dict, Optional
from langchain_community.embeddings.huggingface import HuggingFaceInferenceAPIEmbeddings
from pydantic.v1.types import SecretStr
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
class HuggingFaceInferenceAPIEmbeddingsComponent(CustomComponent):

View file

@ -1,7 +1,7 @@
from langchain_mistralai.embeddings import MistralAIEmbeddings
from pydantic.v1 import SecretStr
from langchain_mistralai.embeddings import MistralAIEmbeddings
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
from langflow.field_typing import Embeddings

View file

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

View file

@ -1,10 +1,10 @@
from typing import Any, Dict, List, Optional
from typing import Dict, List, Optional
from langchain_openai.embeddings.base import OpenAIEmbeddings
from pydantic.v1 import SecretStr
from langflow.custom import CustomComponent
from langflow.field_typing import Embeddings, NestedDict
from langflow.interface.custom.custom_component import CustomComponent
class OpenAIEmbeddingsComponent(CustomComponent):
@ -94,7 +94,6 @@ class OpenAIEmbeddingsComponent(CustomComponent):
allowed_special: List[str] = [],
disallowed_special: List[str] = ["all"],
chunk_size: int = 1000,
client: Optional[Any] = None,
deployment: str = "text-embedding-ada-002",
embedding_ctx_length: int = 8191,
max_retries: int = 6,
@ -126,7 +125,6 @@ class OpenAIEmbeddingsComponent(CustomComponent):
allowed_special=set(allowed_special),
disallowed_special="all",
chunk_size=chunk_size,
client=client,
deployment=deployment,
embedding_ctx_length=embedding_ctx_length,
max_retries=max_retries,

View file

@ -2,7 +2,7 @@ from typing import List, Optional
from langchain_google_vertexai import VertexAIEmbeddings
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
class VertexAIEmbeddingsComponent(CustomComponent):

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,7 +1,8 @@
from typing import Union
from langflow.interface.custom.custom_component import CustomComponent
from langflow.schema import Record
from langflow.custom import CustomComponent
from langflow.field_typing import Text
from langflow.schema import Record
class PassComponent(CustomComponent):

View file

@ -1,8 +1,8 @@
from typing import Callable
from langflow.custom import CustomComponent
from langflow.custom.utils import get_function
from langflow.field_typing import Code
from langflow.interface.custom.custom_component import CustomComponent
from langflow.interface.custom.utils import get_function
class PythonFunctionComponent(CustomComponent):

View file

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

View file

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

View file

@ -1,7 +1,7 @@
from typing import Optional
from langflow.custom import CustomComponent
from langflow.field_typing import Text
from langflow.interface.custom.custom_component import CustomComponent
from langflow.schema import Record
from langflow.utils.util import unescape_string

View file

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

View file

@ -1,8 +1,8 @@
from typing import Optional, Union
from langflow.interface.custom.custom_component import CustomComponent
from langflow.schema import Record
from langflow.custom import CustomComponent
from langflow.field_typing import Text
from langflow.schema import Record
class TextOperatorComponent(CustomComponent):

View file

@ -1,4 +1,4 @@
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
from langflow.field_typing import Text

View file

@ -1,4 +1,4 @@
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
from langflow.field_typing import Text

View file

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

View file

@ -2,7 +2,7 @@ from typing import List
from langchain_core.documents import Document
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
from langflow.schema import Record

View file

@ -1,7 +1,7 @@
import uuid
from typing import Any, Optional
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
class UUIDGeneratorComponent(CustomComponent):

View file

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

View file

@ -1,6 +1,6 @@
from langflow.custom import CustomComponent
from langflow.field_typing import Text
from langflow.helpers.record import records_to_text
from langflow.interface.custom.custom_component import CustomComponent
from langflow.schema import Record

View file

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

View file

@ -1,7 +1,7 @@
from langchain_core.prompts import PromptTemplate
from langflow.custom import CustomComponent
from langflow.field_typing import Prompt, TemplateField, Text
from langflow.interface.custom.custom_component import CustomComponent
class PromptComponent(CustomComponent):

View file

@ -3,7 +3,7 @@
# We need to make sure this class is importable from the context where this code will be running.
from langchain_community.utilities.bing_search import BingSearchAPIWrapper
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
class BingSearchAPIWrapperComponent(CustomComponent):

View file

@ -2,7 +2,7 @@ from typing import Callable, Union
from langchain_community.utilities.google_search import GoogleSearchAPIWrapper
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
class GoogleSearchAPIWrapperComponent(CustomComponent):

View file

@ -4,7 +4,7 @@ from typing import Dict
# If this class does not exist, you would need to create it or import the appropriate class from another module
from langchain_community.utilities.google_serper import GoogleSerperAPIWrapper
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
class GoogleSerperAPIWrapperComponent(CustomComponent):

View file

@ -13,7 +13,7 @@
from langchain_core.documents import Document
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
from langflow.services.database.models.base import orjson_dumps

View file

@ -1,6 +1,6 @@
from langchain_experimental.sql.base import SQLDatabase
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
class SQLDatabaseComponent(CustomComponent):

View file

@ -2,7 +2,7 @@ from typing import Dict, Optional
from langchain_community.utilities.searx_search import SearxSearchWrapper
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
class SearxSearchWrapperComponent(CustomComponent):

View file

@ -2,7 +2,7 @@ from typing import Callable, Union
from langchain_community.utilities.serpapi import SerpAPIWrapper
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
class SerpAPIWrapperComponent(CustomComponent):

View file

@ -2,7 +2,7 @@ from typing import Callable, Union
from langchain_community.utilities.wikipedia import WikipediaAPIWrapper
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
# Assuming WikipediaAPIWrapper is a class that needs to be imported.
# The import statement is not included as it is not provided in the JSON

View file

@ -2,7 +2,7 @@ from typing import Callable, Union
from langchain_community.utilities.wolfram_alpha import WolframAlphaAPIWrapper
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
# Since all the fields in the JSON have show=False, we will only create a basic component
# without any configurable fields.

View file

@ -0,0 +1,91 @@
from typing import Optional, cast
from langchain_astradb.chat_message_histories import AstraDBChatMessageHistory
from langflow.base.memory.memory import BaseMemoryComponent
from langflow.field_typing import Text
from langflow.schema.schema import Record
class AstraDBMessageReaderComponent(BaseMemoryComponent):
display_name = "Astra DB Message Reader"
description = "Retrieves stored chat messages from Astra DB."
def build_config(self):
return {
"session_id": {
"display_name": "Session ID",
"info": "Session ID of the chat history.",
"input_types": ["Text"],
},
"collection_name": {
"display_name": "Collection Name",
"info": "Collection name for Astra DB.",
"input_types": ["Text"],
},
"token": {
"display_name": "Astra DB Application Token",
"info": "Token for the Astra DB instance.",
"password": True,
},
"api_endpoint": {
"display_name": "Astra DB API Endpoint",
"info": "API Endpoint for the Astra DB instance.",
"password": True,
},
"namespace": {
"display_name": "Namespace",
"info": "Namespace for the Astra DB instance.",
"input_types": ["Text"],
"advanced": True,
},
}
def get_messages(self, **kwargs) -> list[Record]:
"""
Retrieves messages from the AstraDBChatMessageHistory memory.
Args:
memory (AstraDBChatMessageHistory): The AstraDBChatMessageHistory instance to retrieve messages from.
Returns:
list[Record]: A list of Record objects representing the search results.
"""
memory: AstraDBChatMessageHistory = cast(AstraDBChatMessageHistory, kwargs.get("memory"))
if not memory:
raise ValueError("AstraDBChatMessageHistory instance is required.")
# Get messages from the memory
messages = memory.messages
results = [Record.from_lc_message(message) for message in messages]
return list(results)
def build(
self,
session_id: Text,
collection_name: str,
token: str,
api_endpoint: str,
namespace: Optional[str] = None,
) -> list[Record]:
try:
pass
except ImportError:
raise ImportError(
"Could not import langchain Astra DB integration package. "
"Please install it with `pip install langchain-astradb`."
)
memory = AstraDBChatMessageHistory(
session_id=session_id,
collection_name=collection_name,
token=token,
api_endpoint=api_endpoint,
namespace=namespace,
)
records = self.get_messages(memory=memory)
self.status = records
return records

View file

@ -0,0 +1,117 @@
from typing import Optional
from langflow.base.memory.memory import BaseMemoryComponent
from langflow.field_typing import Text
from langflow.schema.schema import Record
from langchain_core.messages import BaseMessage
from langchain_astradb import AstraDBChatMessageHistory
class AstraDBMessageWriterComponent(BaseMemoryComponent):
display_name = "Astra DB Message Writer"
description = "Writes a message to Astra DB."
def build_config(self):
return {
"input_value": {
"display_name": "Input Record",
"info": "Record to write to Astra DB.",
},
"session_id": {
"display_name": "Session ID",
"info": "Session ID of the chat history.",
"input_types": ["Text"],
},
"collection_name": {
"display_name": "Collection Name",
"info": "Collection name for Astra DB.",
"input_types": ["Text"],
},
"token": {
"display_name": "Astra DB Application Token",
"info": "Token for the Astra DB instance.",
"password": True,
},
"api_endpoint": {
"display_name": "Astra DB API Endpoint",
"info": "API Endpoint for the Astra DB instance.",
"password": True,
},
"namespace": {
"display_name": "Namespace",
"info": "Namespace for the Astra DB instance.",
"input_types": ["Text"],
"advanced": True,
},
}
def add_message(
self,
sender: str,
sender_name: str,
text: Text,
session_id: str,
metadata: Optional[dict] = None,
**kwargs,
):
"""
Adds a message to the AstraDBChatMessageHistory memory.
Args:
sender (Text): The type of the message sender. Valid values are "Machine" or "User".
sender_name (Text): The name of the message sender.
text (Text): The content of the message.
session_id (Text): The session ID associated with the message.
metadata (dict | None, optional): Additional metadata for the message. Defaults to None.
**kwargs: Additional keyword arguments.
Raises:
ValueError: If the AstraDBChatMessageHistory instance is not provided.
"""
memory: AstraDBChatMessageHistory | None = kwargs.pop("memory", None)
if memory is None:
raise ValueError("AstraDBChatMessageHistory instance is required.")
text_list = [
BaseMessage(
content=text,
sender=sender,
sender_name=sender_name,
metadata=metadata,
session_id=session_id,
)
]
memory.add_messages(text_list)
def build(
self,
input_value: Record,
session_id: Text,
collection_name: str,
token: str,
api_endpoint: str,
namespace: Optional[str] = None,
) -> Record:
try:
pass
except ImportError:
raise ImportError(
"Could not import langchain Astra DB integration package. "
"Please install it with `pip install langchain-astradb`."
)
memory = AstraDBChatMessageHistory(
session_id=session_id,
collection_name=collection_name,
token=token,
api_endpoint=api_endpoint,
namespace=namespace,
)
self.add_message(**input_value.data, memory=memory)
self.status = f"Added message to Astra DB memory for session {session_id}"
return input_value

View file

@ -116,19 +116,18 @@ class ZepMessageReaderComponent(BaseMemoryComponent):
url: Optional[Text] = None,
api_key: Optional[Text] = None,
query: Optional[Text] = None,
search_scope: SearchScope = SearchScope.messages,
search_type: SearchType = SearchType.similarity,
search_scope: str = SearchScope.messages,
search_type: str = SearchType.similarity,
limit: Optional[int] = None,
) -> list[Record]:
try:
from zep_python import ZepClient
from zep_python.langchain import ZepChatMessageHistory
# Monkeypatch API_BASE_PATH to
# avoid 404
# This is a workaround for the local Zep instance
# cloud Zep works with v2
import zep_python.zep_client
from zep_python import ZepClient
from zep_python.langchain import ZepChatMessageHistory
zep_python.zep_client.API_BASE_PATH = api_base_path
except ImportError:

View file

@ -1,8 +1,9 @@
from typing import Optional
from langflow.field_typing import BaseLanguageModel
from langchain_community.llms.bedrock import Bedrock
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
from langflow.field_typing import BaseLanguageModel
class AmazonBedrockComponent(CustomComponent):

View file

@ -1,10 +1,10 @@
from typing import Optional
from langchain.llms.base import BaseLanguageModel
from langchain_anthropic import ChatAnthropic
from langchain_core.language_models import BaseLanguageModel
from pydantic.v1 import SecretStr
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
class ChatAntropicSpecsComponent(CustomComponent):
@ -35,8 +35,8 @@ class ChatAntropicSpecsComponent(CustomComponent):
},
"max_tokens": {
"display_name": "Max Tokens",
"field_type": "int",
"value": 256,
"advanced": True,
"info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.",
},
"temperature": {
"display_name": "Temperature",

View file

@ -1,9 +1,10 @@
from typing import Optional
from langchain.llms.base import BaseLanguageModel
from langchain_community.chat_models.azure_openai import AzureChatOpenAI
from langchain_core.language_models import BaseLanguageModel
from langchain_openai import AzureChatOpenAI
from pydantic.v1 import SecretStr
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
class AzureChatOpenAISpecsComponent(CustomComponent):
@ -65,11 +66,8 @@ class AzureChatOpenAISpecsComponent(CustomComponent):
},
"max_tokens": {
"display_name": "Max Tokens",
"value": 1000,
"required": False,
"field_type": "int",
"advanced": True,
"info": "Maximum number of tokens to generate.",
"info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.",
},
"code": {"show": False},
}
@ -84,15 +82,19 @@ class AzureChatOpenAISpecsComponent(CustomComponent):
temperature: float = 0.7,
max_tokens: Optional[int] = 1000,
) -> BaseLanguageModel:
if api_key:
azure_api_key = SecretStr(api_key)
else:
azure_api_key = None
try:
llm = AzureChatOpenAI(
model=model,
azure_endpoint=azure_endpoint,
azure_deployment=azure_deployment,
api_version=api_version,
api_key=api_key,
api_key=azure_api_key,
temperature=temperature,
max_tokens=max_tokens,
max_tokens=max_tokens or None,
)
except Exception as e:
raise ValueError("Could not connect to AzureOpenAI API.") from e

View file

@ -1,10 +1,11 @@
from typing import Optional
from langchain_community.chat_models.baidu_qianfan_endpoint import QianfanChatEndpoint
from pydantic.v1 import SecretStr
from langflow.custom import CustomComponent
from langflow.field_typing import BaseLanguageModel
from langflow.interface.custom.custom_component import CustomComponent
class QianfanChatEndpointComponent(CustomComponent):

View file

@ -2,7 +2,7 @@ from typing import Optional
from langchain_community.llms.baidu_qianfan_endpoint import QianfanLLMEndpoint
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
from langflow.field_typing import BaseLanguageModel

View file

@ -46,9 +46,8 @@ class AnthropicLLM(CustomComponent):
},
"max_tokens": {
"display_name": "Max Tokens",
"field_type": "int",
"advanced": True,
"value": 256,
"info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.",
},
"temperature": {
"display_name": "Temperature",

View file

@ -1,8 +1,9 @@
from typing import Any, Dict, Optional
from langchain_community.chat_models.litellm import ChatLiteLLM, ChatLiteLLMException
from langflow.custom import CustomComponent
from langflow.field_typing import BaseLanguageModel
from langflow.interface.custom.custom_component import CustomComponent
class ChatLiteLLMComponent(CustomComponent):
@ -81,12 +82,9 @@ class ChatLiteLLMComponent(CustomComponent):
"default": 1,
},
"max_tokens": {
"display_name": "Max tokens",
"field_type": "int",
"advanced": False,
"required": False,
"default": 256,
"info": "The maximum number of tokens to generate for each chat completion.",
"display_name": "Max Tokens",
"advanced": True,
"info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.",
},
"max_retries": {
"display_name": "Max retries",

View file

@ -77,7 +77,7 @@ class MistralAIModelComponent(CustomComponent):
output = ChatMistralAI(
model_name=model,
api_key=(SecretStr(mistral_api_key) if mistral_api_key else None),
max_tokens=max_tokens,
max_tokens=max_tokens or None,
temperature=temperature,
endpoint=mistral_api_base,
)

View file

@ -1,11 +1,11 @@
from typing import Any, Dict, List, Optional
from typing import Dict, List, Optional
# from langchain_community.chat_models import ChatOllama
from langchain_community.chat_models import ChatOllama
from langchain_core.language_models.chat_models import BaseChatModel
# from langchain.chat_models import ChatOllama
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
# from langchain.callbacks.manager import CallbackManager
@ -182,7 +182,7 @@ class ChatOllamaComponent(CustomComponent):
num_ctx: Optional[int] = None,
num_gpu: Optional[int] = None,
format: Optional[str] = None,
metadata: Optional[Dict[str, Any]] = None,
metadata: Optional[Dict] = None,
num_thread: Optional[int] = None,
repeat_penalty: Optional[float] = None,
stop: Optional[List[str]] = None,

View file

@ -1,10 +1,11 @@
from typing import Optional
from langchain_openai import ChatOpenAI
from pydantic.v1 import SecretStr
from langflow.base.models.openai_constants import MODEL_NAMES
from langflow.custom import CustomComponent
from langflow.field_typing import BaseLanguageModel, NestedDict
from langflow.interface.custom.custom_component import CustomComponent
class ChatOpenAIComponent(CustomComponent):
@ -16,8 +17,8 @@ class ChatOpenAIComponent(CustomComponent):
return {
"max_tokens": {
"display_name": "Max Tokens",
"advanced": False,
"required": False,
"advanced": True,
"info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.",
},
"model_kwargs": {
"display_name": "Model Kwargs",
@ -50,7 +51,7 @@ class ChatOpenAIComponent(CustomComponent):
def build(
self,
max_tokens: Optional[int] = 256,
max_tokens: Optional[int] = 0,
model_kwargs: NestedDict = {},
model_name: str = "gpt-4o",
openai_api_base: Optional[str] = None,
@ -59,11 +60,15 @@ class ChatOpenAIComponent(CustomComponent):
) -> BaseLanguageModel:
if not openai_api_base:
openai_api_base = "https://api.openai.com/v1"
if openai_api_key:
api_key = SecretStr(openai_api_key)
else:
api_key = None
return ChatOpenAI(
max_tokens=max_tokens,
max_tokens=max_tokens or None,
model_kwargs=model_kwargs,
model=model_name,
base_url=openai_api_base,
api_key=openai_api_key,
api_key=api_key,
temperature=temperature,
)

View file

@ -1,10 +1,9 @@
from typing import List, Optional
from typing import Optional
from langchain_community.chat_models.vertexai import ChatVertexAI
from langchain_core.messages.base import BaseMessage
from langflow.custom import CustomComponent
from langflow.field_typing import BaseLanguageModel
from langflow.interface.custom.custom_component import CustomComponent
class ChatVertexAIComponent(CustomComponent):
@ -65,7 +64,6 @@ class ChatVertexAIComponent(CustomComponent):
self,
credentials: Optional[str],
project: str,
examples: Optional[List[BaseMessage]] = [],
location: str = "us-central1",
max_output_tokens: int = 128,
model_name: str = "chat-bison",
@ -76,7 +74,6 @@ class ChatVertexAIComponent(CustomComponent):
) -> BaseLanguageModel:
return ChatVertexAI(
credentials=credentials,
examples=examples,
location=location,
max_output_tokens=max_output_tokens,
model_name=model_name,

View file

@ -1,7 +1,10 @@
from langchain_community.llms.cohere import Cohere
from langchain_core.language_models.base import BaseLanguageModel
from typing import Optional
from langflow.interface.custom.custom_component import CustomComponent
from langchain_cohere import ChatCohere
from langchain_core.language_models.base import BaseLanguageModel
from pydantic.v1 import SecretStr
from langflow.custom import CustomComponent
class CohereComponent(CustomComponent):
@ -13,14 +16,22 @@ class CohereComponent(CustomComponent):
def build_config(self):
return {
"cohere_api_key": {"display_name": "Cohere API Key", "type": "password", "password": True},
"max_tokens": {"display_name": "Max Tokens", "default": 256, "type": "int", "show": True},
"max_tokens": {
"display_name": "Max Tokens",
"advanced": True,
"info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.",
},
"temperature": {"display_name": "Temperature", "default": 0.75, "type": "float", "show": True},
}
def build(
self,
cohere_api_key: str,
max_tokens: int = 256,
max_tokens: Optional[int] = 256,
temperature: float = 0.75,
) -> BaseLanguageModel:
return Cohere(cohere_api_key=cohere_api_key, max_tokens=max_tokens, temperature=temperature) # type: ignore
if cohere_api_key:
api_key = SecretStr(cohere_api_key)
else:
api_key = None
return ChatCohere(cohere_api_key=api_key, max_tokens=max_tokens or None, temperature=temperature) # type: ignore

View file

@ -3,8 +3,8 @@ from typing import Optional
from langchain_google_genai import ChatGoogleGenerativeAI # type: ignore
from pydantic.v1.types import SecretStr
from langflow.custom import CustomComponent
from langflow.field_typing import BaseLanguageModel, RangeSpec
from langflow.interface.custom.custom_component import CustomComponent
class GoogleGenerativeAIComponent(CustomComponent):

View file

@ -1,9 +1,9 @@
from typing import Optional
from langflow.field_typing import BaseLanguageModel
from langchain_community.llms.huggingface_endpoint import HuggingFaceEndpoint
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
from langflow.field_typing import BaseLanguageModel
class HuggingFaceEndpointsComponent(CustomComponent):

View file

@ -1,9 +1,9 @@
from typing import List, Optional
from langflow.field_typing import BaseLanguageModel
from langchain_community.llms.ollama import Ollama
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
from langflow.field_typing import BaseLanguageModel
class OllamaLLM(CustomComponent):

View file

@ -1,9 +1,9 @@
from typing import Dict, Optional
from langflow.field_typing import BaseLanguageModel
from langchain_community.llms.vertexai import VertexAI
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
from langflow.field_typing import BaseLanguageModel
class VertexAIComponent(CustomComponent):

View file

@ -49,9 +49,8 @@ class AnthropicLLM(LCModelComponent):
},
"max_tokens": {
"display_name": "Max Tokens",
"field_type": "int",
"advanced": True,
"value": 256,
"info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.",
},
"temperature": {
"display_name": "Temperature",

View file

@ -74,9 +74,8 @@ class AzureChatOpenAIComponent(LCModelComponent):
},
"max_tokens": {
"display_name": "Max Tokens",
"value": 1000,
"advanced": True,
"info": "Maximum number of tokens to generate.",
"info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.",
},
"code": {"show": False},
"input_value": {"display_name": "Input"},
@ -117,7 +116,7 @@ class AzureChatOpenAIComponent(LCModelComponent):
api_version=api_version,
api_key=secret_api_key,
temperature=temperature,
max_tokens=max_tokens,
max_tokens=max_tokens or None,
)
except Exception as e:
raise ValueError("Could not connect to AzureOpenAI API.") from e

View file

@ -93,9 +93,7 @@ class ChatLiteLLMModelComponent(LCModelComponent):
},
"max_tokens": {
"display_name": "Max tokens",
"field_type": "int",
"advanced": False,
"required": False,
"default": 256,
"info": "The maximum number of tokens to generate for each chat completion.",
},

View file

@ -1,10 +1,10 @@
from typing import Optional
from langchain_community.chat_models.cohere import ChatCohere
from pydantic.v1 import SecretStr
from langflow.field_typing import Text
from langflow.base.constants import STREAM_INFO_TEXT
from langflow.base.models.model import LCModelComponent
from langchain_cohere import ChatCohere
class CohereComponent(LCModelComponent):
@ -34,9 +34,7 @@ class CohereComponent(LCModelComponent):
"max_tokens": {
"display_name": "Max Tokens",
"advanced": True,
"default": 256,
"type": "int",
"show": True,
"info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.",
},
"temperature": {
"display_name": "Temperature",

View file

@ -31,6 +31,7 @@ class MistralAIModelComponent(LCModelComponent):
"max_tokens": {
"display_name": "Max Tokens",
"advanced": True,
"info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.",
},
"model_name": {
"display_name": "Model Name",
@ -125,7 +126,7 @@ class MistralAIModelComponent(LCModelComponent):
api_key = None
chat_model = ChatMistralAI(
max_tokens=max_tokens,
max_tokens=max_tokens or None,
model_name=model_name,
endpoint=mistral_api_base,
api_key=api_key,

View file

@ -1,4 +1,4 @@
from typing import Any, Dict, List, Optional
from typing import Dict, List, Optional
# from langchain_community.chat_models import ChatOllama
from langchain_community.chat_models import ChatOllama
@ -229,7 +229,7 @@ class ChatOllamaComponent(LCModelComponent):
num_ctx: Optional[int] = None,
num_gpu: Optional[int] = None,
format: Optional[str] = None,
metadata: Optional[Dict[str, Any]] = None,
metadata: Optional[Dict] = None,
num_thread: Optional[int] = None,
repeat_penalty: Optional[float] = None,
stop: Optional[List[str]] = None,

View file

@ -32,6 +32,7 @@ class OpenAIModelComponent(LCModelComponent):
"max_tokens": {
"display_name": "Max Tokens",
"advanced": True,
"info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.",
},
"model_kwargs": {
"display_name": "Model Kwargs",
@ -93,7 +94,7 @@ class OpenAIModelComponent(LCModelComponent):
api_key = None
output = ChatOpenAI(
max_tokens=max_tokens,
max_tokens=max_tokens or None,
model_kwargs=model_kwargs,
model=model_name,
base_url=openai_api_base,

View file

@ -1,6 +1,5 @@
from typing import List, Optional
from typing import Optional
from langchain_core.messages.base import BaseMessage
from langflow.base.constants import STREAM_INFO_TEXT
from langflow.base.models.model import LCModelComponent
@ -93,7 +92,6 @@ class ChatVertexAIComponent(LCModelComponent):
input_value: Text,
credentials: Optional[str],
project: str,
examples: Optional[List[BaseMessage]] = [],
location: str = "us-central1",
max_output_tokens: int = 128,
model_name: str = "chat-bison",
@ -112,7 +110,6 @@ class ChatVertexAIComponent(LCModelComponent):
)
output = ChatVertexAI(
credentials=credentials,
examples=examples,
location=location,
max_output_tokens=max_output_tokens,
model_name=model_name,

View file

@ -1,8 +1,8 @@
from langflow.base.io.text import TextComponent
from langflow.custom import CustomComponent
from langflow.schema import Record
class RecordsOutput(TextComponent):
class RecordsOutput(CustomComponent):
display_name = "Records Output"
description = "Display Records as a Table"

View file

@ -1,9 +1,9 @@
from typing import Optional
from langchain.schema import BaseRetriever
from langchain_community.retrievers import AmazonKendraRetriever
from langchain_core.retrievers import BaseRetriever
from langflow.interface.custom.custom_component import CustomComponent
from langflow.custom import CustomComponent
class AmazonKendraRetrieverComponent(CustomComponent):

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