Merge dev
This commit is contained in:
commit
0eb6f6b212
386 changed files with 27625 additions and 32139 deletions
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"):
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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"])
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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]:
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from langflow.interface.custom.custom_component import CustomComponent
|
||||
from langflow.custom import CustomComponent
|
||||
from langflow.schema import Record
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from langflow.interface.custom.custom_component import CustomComponent
|
||||
from langflow.custom import CustomComponent
|
||||
from langflow.schema import Record
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from langflow.interface.custom.custom_component import CustomComponent
|
||||
from langflow.custom import CustomComponent
|
||||
from langflow.schema import Record
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from langflow.interface.custom.custom_component import CustomComponent
|
||||
from langflow.custom import CustomComponent
|
||||
from langflow.field_typing import Text
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from langflow.interface.custom.custom_component import CustomComponent
|
||||
from langflow.custom import CustomComponent
|
||||
from langflow.field_typing import Text
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from langflow.interface.custom.custom_component import CustomComponent
|
||||
from langflow.custom import CustomComponent
|
||||
from langflow.schema import Record
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue