Merge branch 'feature/store' of github.com:logspace-ai/langflow into feature/store
This commit is contained in:
commit
7a15fb7a0d
123 changed files with 1843 additions and 2731 deletions
5
Makefile
5
Makefile
|
|
@ -30,13 +30,12 @@ else
|
|||
endif
|
||||
|
||||
format:
|
||||
poetry run black .
|
||||
poetry run ruff . --fix --exclude src/backend/langflow/alembic
|
||||
poetry run ruff . --fix
|
||||
poetry run ruff format .
|
||||
cd src/frontend && npm run format
|
||||
|
||||
lint:
|
||||
poetry run mypy src/backend/langflow
|
||||
poetry run black . --check
|
||||
poetry run ruff . --fix
|
||||
|
||||
install_frontend:
|
||||
|
|
|
|||
2295
poetry.lock
generated
2295
poetry.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -96,10 +96,9 @@ qianfan = "0.0.5"
|
|||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
types-redis = "^4.6.0.5"
|
||||
black = "^23.1.0"
|
||||
ipykernel = "^6.21.2"
|
||||
mypy = "^1.1.1"
|
||||
ruff = "^0.0.254"
|
||||
ruff = "^0.1.5"
|
||||
httpx = "*"
|
||||
pytest = "^7.2.2"
|
||||
types-requests = "^2.28.11"
|
||||
|
|
@ -136,6 +135,7 @@ markers = ["async_test"]
|
|||
|
||||
|
||||
[tool.ruff]
|
||||
exclude = ["src/backend/langflow/alembic/*"]
|
||||
line-length = 120
|
||||
|
||||
[build-system]
|
||||
|
|
|
|||
|
|
@ -98,12 +98,8 @@ def update_settings(
|
|||
|
||||
@app.command()
|
||||
def run(
|
||||
host: str = typer.Option(
|
||||
"127.0.0.1", help="Host to bind the server to.", envvar="LANGFLOW_HOST"
|
||||
),
|
||||
workers: int = typer.Option(
|
||||
1, help="Number of worker processes.", envvar="LANGFLOW_WORKERS"
|
||||
),
|
||||
host: str = typer.Option("127.0.0.1", help="Host to bind the server to.", envvar="LANGFLOW_HOST"),
|
||||
workers: int = typer.Option(1, help="Number of worker processes.", envvar="LANGFLOW_WORKERS"),
|
||||
timeout: int = typer.Option(300, help="Worker timeout in seconds."),
|
||||
port: int = typer.Option(7860, help="Port to listen on.", envvar="LANGFLOW_PORT"),
|
||||
components_path: Optional[Path] = typer.Option(
|
||||
|
|
@ -111,19 +107,11 @@ 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."
|
||||
),
|
||||
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"
|
||||
),
|
||||
log_file: Path = typer.Option(
|
||||
"logs/langflow.log", help="Path to the log file.", envvar="LANGFLOW_LOG_FILE"
|
||||
),
|
||||
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"),
|
||||
log_file: Path = typer.Option("logs/langflow.log", help="Path to the log file.", envvar="LANGFLOW_LOG_FILE"),
|
||||
cache: Optional[str] = typer.Option(
|
||||
envvar="LANGFLOW_LANGCHAIN_CACHE",
|
||||
help="Type of cache to use. (InMemoryCache, SQLiteCache)",
|
||||
|
|
@ -202,9 +190,7 @@ def run(
|
|||
|
||||
|
||||
def run_on_mac_or_linux(host, port, log_level, options, app, open_browser=True):
|
||||
webapp_process = Process(
|
||||
target=run_langflow, args=(host, port, log_level, options, app)
|
||||
)
|
||||
webapp_process = Process(target=run_langflow, args=(host, port, log_level, options, app))
|
||||
webapp_process.start()
|
||||
status_code = 0
|
||||
while status_code != 200:
|
||||
|
|
@ -280,9 +266,7 @@ def print_banner(host, port):
|
|||
)
|
||||
|
||||
# Create a panel with the title and the info text, and a border around it
|
||||
panel = Panel(
|
||||
f"{title}\n{info_text}", box=box.ROUNDED, border_style="blue", expand=False
|
||||
)
|
||||
panel = Panel(f"{title}\n{info_text}", box=box.ROUNDED, border_style="blue", expand=False)
|
||||
|
||||
# Print the banner with a separator line before and after
|
||||
rprint(panel)
|
||||
|
|
@ -314,12 +298,8 @@ def run_langflow(host, port, log_level, options, app):
|
|||
@app.command()
|
||||
def superuser(
|
||||
username: str = typer.Option(..., prompt=True, help="Username for the superuser."),
|
||||
password: str = typer.Option(
|
||||
..., prompt=True, hide_input=True, help="Password for the superuser."
|
||||
),
|
||||
log_level: str = typer.Option(
|
||||
"critical", help="Logging level.", envvar="LANGFLOW_LOG_LEVEL"
|
||||
),
|
||||
password: str = typer.Option(..., prompt=True, hide_input=True, help="Password for the superuser."),
|
||||
log_level: str = typer.Option("critical", help="Logging level.", envvar="LANGFLOW_LOG_LEVEL"),
|
||||
):
|
||||
"""
|
||||
Create a superuser.
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@ API_WORDS = ["api", "key", "token"]
|
|||
|
||||
|
||||
def has_api_terms(word: str):
|
||||
return "api" in word and (
|
||||
"key" in word or ("token" in word and "tokens" not in word)
|
||||
)
|
||||
return "api" in word and ("key" in word or ("token" in word and "tokens" not in word))
|
||||
|
||||
|
||||
def remove_api_keys(flow: dict):
|
||||
|
|
@ -14,11 +12,7 @@ def remove_api_keys(flow: dict):
|
|||
node_data = node.get("data").get("node")
|
||||
template = node_data.get("template")
|
||||
for value in template.values():
|
||||
if (
|
||||
isinstance(value, dict)
|
||||
and has_api_terms(value["name"])
|
||||
and value.get("password")
|
||||
):
|
||||
if isinstance(value, dict) and has_api_terms(value["name"]) and value.get("password"):
|
||||
value["value"] = None
|
||||
|
||||
return flow
|
||||
|
|
@ -39,9 +33,7 @@ def build_input_keys_response(langchain_object, artifacts):
|
|||
input_keys_response["input_keys"][key] = value
|
||||
# If the object has memory, that memory will have a memory_variables attribute
|
||||
# memory variables should be removed from the input keys
|
||||
if hasattr(langchain_object, "memory") and hasattr(
|
||||
langchain_object.memory, "memory_variables"
|
||||
):
|
||||
if hasattr(langchain_object, "memory") and hasattr(langchain_object.memory, "memory_variables"):
|
||||
# Remove memory variables from input keys
|
||||
input_keys_response["input_keys"] = {
|
||||
key: value
|
||||
|
|
@ -51,9 +43,7 @@ def build_input_keys_response(langchain_object, artifacts):
|
|||
# Add memory variables to memory_keys
|
||||
input_keys_response["memory_keys"] = langchain_object.memory.memory_variables
|
||||
|
||||
if hasattr(langchain_object, "prompt") and hasattr(
|
||||
langchain_object.prompt, "template"
|
||||
):
|
||||
if hasattr(langchain_object, "prompt") and hasattr(langchain_object.prompt, "template"):
|
||||
input_keys_response["template"] = langchain_object.prompt.template
|
||||
|
||||
return input_keys_response
|
||||
|
|
|
|||
|
|
@ -79,9 +79,7 @@ def save_store_api_key(
|
|||
try:
|
||||
api_key = api_key_request.api_key
|
||||
# Encrypt the API key
|
||||
encrypted = auth_utils.encrypt_api_key(
|
||||
api_key, settings_service=settings_service
|
||||
)
|
||||
encrypted = auth_utils.encrypt_api_key(api_key, settings_service=settings_service)
|
||||
current_user.store_api_key = encrypted
|
||||
db.commit()
|
||||
return {"detail": "API Key saved"}
|
||||
|
|
|
|||
|
|
@ -79,9 +79,7 @@ def validate_prompt(template: str):
|
|||
# Check if there are invalid characters in the input_variables
|
||||
input_variables = check_input_variables(input_variables)
|
||||
if any(var in INVALID_NAMES for var in input_variables):
|
||||
raise ValueError(
|
||||
f"Invalid input variables. None of the variables can be named {', '.join(input_variables)}. "
|
||||
)
|
||||
raise ValueError(f"Invalid input variables. None of the variables can be named {', '.join(input_variables)}. ")
|
||||
|
||||
try:
|
||||
PromptTemplate(template=template, input_variables=input_variables)
|
||||
|
|
@ -132,9 +130,7 @@ def check_input_variables(input_variables: list):
|
|||
return input_variables
|
||||
|
||||
|
||||
def build_error_message(
|
||||
input_variables, invalid_chars, wrong_variables, fixed_variables, empty_variables
|
||||
):
|
||||
def build_error_message(input_variables, invalid_chars, wrong_variables, fixed_variables, empty_variables):
|
||||
input_variables_str = ", ".join([f"'{var}'" for var in input_variables])
|
||||
error_string = f"Invalid input variables: {input_variables_str}. "
|
||||
|
||||
|
|
|
|||
|
|
@ -28,9 +28,7 @@ class AsyncStreamingLLMCallbackHandler(AsyncCallbackHandler):
|
|||
resp = ChatResponse(message=token, type="stream", intermediate_steps="")
|
||||
await self.websocket.send_json(resp.dict())
|
||||
|
||||
async def on_tool_start(
|
||||
self, serialized: Dict[str, Any], input_str: str, **kwargs: Any
|
||||
) -> Any:
|
||||
async def on_tool_start(self, serialized: Dict[str, Any], input_str: str, **kwargs: Any) -> Any:
|
||||
"""Run when tool starts running."""
|
||||
resp = ChatResponse(
|
||||
message="",
|
||||
|
|
|
|||
|
|
@ -37,13 +37,9 @@ async def chat(
|
|||
await websocket.accept()
|
||||
user = await get_current_user(token, db)
|
||||
if not user:
|
||||
await websocket.close(
|
||||
code=status.WS_1008_POLICY_VIOLATION, reason="Unauthorized"
|
||||
)
|
||||
await websocket.close(code=status.WS_1008_POLICY_VIOLATION, reason="Unauthorized")
|
||||
if not user.is_active:
|
||||
await websocket.close(
|
||||
code=status.WS_1008_POLICY_VIOLATION, reason="Unauthorized"
|
||||
)
|
||||
await websocket.close(code=status.WS_1008_POLICY_VIOLATION, reason="Unauthorized")
|
||||
|
||||
if client_id in chat_service.cache_service:
|
||||
await chat_service.handle_websocket(client_id, websocket)
|
||||
|
|
@ -59,9 +55,7 @@ async def chat(
|
|||
logger.error(f"Error in chat websocket: {exc}")
|
||||
messsage = exc.detail if isinstance(exc, HTTPException) else str(exc)
|
||||
if "Could not validate credentials" in str(exc):
|
||||
await websocket.close(
|
||||
code=status.WS_1008_POLICY_VIOLATION, reason="Unauthorized"
|
||||
)
|
||||
await websocket.close(code=status.WS_1008_POLICY_VIOLATION, reason="Unauthorized")
|
||||
else:
|
||||
await websocket.close(code=status.WS_1011_INTERNAL_ERROR, reason=messsage)
|
||||
|
||||
|
|
@ -103,15 +97,10 @@ async def init_build(
|
|||
|
||||
|
||||
@router.get("/build/{flow_id}/status", response_model=BuiltResponse)
|
||||
async def build_status(
|
||||
flow_id: str, cache_service: "BaseCacheService" = Depends(get_cache_service)
|
||||
):
|
||||
async def build_status(flow_id: str, cache_service: "BaseCacheService" = Depends(get_cache_service)):
|
||||
"""Check the flow_id is in the cache_service."""
|
||||
try:
|
||||
built = (
|
||||
flow_id in cache_service
|
||||
and cache_service[flow_id]["status"] == BuildStatus.SUCCESS
|
||||
)
|
||||
built = flow_id in cache_service and cache_service[flow_id]["status"] == BuildStatus.SUCCESS
|
||||
|
||||
return BuiltResponse(
|
||||
built=built,
|
||||
|
|
@ -173,9 +162,7 @@ async def stream_build(
|
|||
params = vertex._built_object_repr()
|
||||
valid = True
|
||||
logger.debug(f"Building node {str(vertex.vertex_type)}")
|
||||
logger.debug(
|
||||
f"Output: {params[:100]}{'...' if len(params) > 100 else ''}"
|
||||
)
|
||||
logger.debug(f"Output: {params[:100]}{'...' if len(params) > 100 else ''}")
|
||||
if vertex.artifacts:
|
||||
# The artifacts will be prompt variables
|
||||
# passed to build_input_keys_response
|
||||
|
|
@ -187,9 +174,7 @@ async def stream_build(
|
|||
valid = False
|
||||
update_build_status(cache_service, flow_id, BuildStatus.FAILURE)
|
||||
|
||||
vertex_id = (
|
||||
vertex.parent_node_id if vertex.parent_is_top_level else vertex.id
|
||||
)
|
||||
vertex_id = vertex.parent_node_id if vertex.parent_is_top_level else vertex.id
|
||||
if vertex_id in graph.top_level_nodes:
|
||||
response = {
|
||||
"valid": valid,
|
||||
|
|
@ -203,9 +188,7 @@ async def stream_build(
|
|||
langchain_object = graph.build()
|
||||
# Now we need to check the input_keys to send them to the client
|
||||
if hasattr(langchain_object, "input_keys"):
|
||||
input_keys_response = build_input_keys_response(
|
||||
langchain_object, artifacts
|
||||
)
|
||||
input_keys_response = build_input_keys_response(langchain_object, artifacts)
|
||||
else:
|
||||
input_keys_response = {
|
||||
"input_keys": None,
|
||||
|
|
|
|||
|
|
@ -92,12 +92,7 @@ async def process(
|
|||
)
|
||||
|
||||
# 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.query(Flow).filter(Flow.id == flow_id).filter(Flow.user_id == api_key_user.id).first()
|
||||
if flow is None:
|
||||
raise ValueError(f"Flow {flow_id} not found")
|
||||
|
||||
|
|
@ -111,9 +106,7 @@ async def process(
|
|||
logger.error(f"Error processing tweaks: {exc}")
|
||||
if sync:
|
||||
task_id, result = await task_service.launch_and_await_task(
|
||||
process_graph_cached_task
|
||||
if task_service.use_celery
|
||||
else process_graph_cached,
|
||||
process_graph_cached_task if task_service.use_celery else process_graph_cached,
|
||||
graph_data,
|
||||
inputs,
|
||||
clear_cache,
|
||||
|
|
@ -133,13 +126,9 @@ async def process(
|
|||
)
|
||||
if session_id is None:
|
||||
# Generate a session ID
|
||||
session_id = get_session_service().generate_key(
|
||||
session_id=session_id, data_graph=graph_data
|
||||
)
|
||||
session_id = get_session_service().generate_key(session_id=session_id, data_graph=graph_data)
|
||||
task_id, task = await task_service.launch_task(
|
||||
process_graph_cached_task
|
||||
if task_service.use_celery
|
||||
else process_graph_cached,
|
||||
process_graph_cached_task if task_service.use_celery else process_graph_cached,
|
||||
graph_data,
|
||||
inputs,
|
||||
clear_cache,
|
||||
|
|
@ -162,18 +151,12 @@ async def process(
|
|||
# StatementError('(builtins.ValueError) badly formed hexadecimal UUID string')
|
||||
if "badly formed hexadecimal UUID string" in str(exc):
|
||||
# This means the Flow ID is not a valid UUID which means it can't find the flow
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)
|
||||
) from exc
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc
|
||||
except ValueError as exc:
|
||||
if f"Flow {flow_id} not found" in str(exc):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)
|
||||
) from exc
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc
|
||||
else:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(exc)
|
||||
) from exc
|
||||
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(exc)) from exc
|
||||
except Exception as e:
|
||||
# Log stack trace
|
||||
logger.exception(e)
|
||||
|
|
|
|||
|
|
@ -64,12 +64,7 @@ def read_flow(
|
|||
current_user: User = Depends(get_current_active_user),
|
||||
):
|
||||
"""Read a flow."""
|
||||
if user_flow := (
|
||||
session.query(Flow)
|
||||
.filter(Flow.id == flow_id)
|
||||
.filter(Flow.user_id == current_user.id)
|
||||
.first()
|
||||
):
|
||||
if user_flow := (session.query(Flow).filter(Flow.id == flow_id).filter(Flow.user_id == current_user.id).first()):
|
||||
return user_flow
|
||||
else:
|
||||
raise HTTPException(status_code=404, detail="Flow not found")
|
||||
|
|
|
|||
|
|
@ -44,9 +44,7 @@ async def login_to_get_access_token(
|
|||
|
||||
|
||||
@router.get("/auto_login")
|
||||
async def auto_login(
|
||||
db: Session = Depends(get_session), settings_service=Depends(get_settings_service)
|
||||
):
|
||||
async def auto_login(db: Session = Depends(get_session), settings_service=Depends(get_settings_service)):
|
||||
if settings_service.auth_settings.AUTO_LOGIN:
|
||||
return create_user_longterm_token(db)
|
||||
|
||||
|
|
@ -60,9 +58,7 @@ async def auto_login(
|
|||
|
||||
|
||||
@router.post("/refresh")
|
||||
async def refresh_token(
|
||||
token: str, current_user: Session = Depends(get_current_active_user)
|
||||
):
|
||||
async def refresh_token(token: str, current_user: Session = Depends(get_current_active_user)):
|
||||
if token:
|
||||
return create_refresh_token(token)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -149,9 +149,7 @@ class StreamData(BaseModel):
|
|||
data: dict
|
||||
|
||||
def __str__(self) -> str:
|
||||
return (
|
||||
f"event: {self.event}\ndata: {orjson_dumps(self.data, indent_2=False)}\n\n"
|
||||
)
|
||||
return f"event: {self.event}\ndata: {orjson_dumps(self.data, indent_2=False)}\n\n"
|
||||
|
||||
|
||||
class CustomComponentCode(BaseModel):
|
||||
|
|
|
|||
|
|
@ -1,27 +1,25 @@
|
|||
from typing import List, Optional
|
||||
from datetime import datetime
|
||||
from typing import Annotated, Any, Dict, List, Optional, Union
|
||||
from uuid import UUID
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from httpx import HTTPStatusError
|
||||
|
||||
from langflow.services.auth import utils as auth_utils
|
||||
from langflow.services.database.models.user.user import User
|
||||
from langflow.services.deps import (
|
||||
get_store_service,
|
||||
get_settings_service,
|
||||
)
|
||||
from langflow.services.deps import get_settings_service, get_store_service
|
||||
from langflow.services.store.schema import (
|
||||
ComponentResponse,
|
||||
DownloadComponentResponse,
|
||||
ListComponentResponse,
|
||||
ListComponentResponseModel,
|
||||
StoreComponentCreate,
|
||||
TagResponse,
|
||||
UsersLikesResponse,
|
||||
)
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from datetime import datetime
|
||||
|
||||
from langflow.services.store.service import StoreService, user_data_context
|
||||
from langflow.services.store.utils import update_components_with_user_data
|
||||
|
||||
|
||||
router = APIRouter(prefix="/store", tags=["Components Store"])
|
||||
|
||||
|
||||
|
|
@ -30,9 +28,7 @@ def get_user_store_api_key(
|
|||
settings_service=Depends(get_settings_service),
|
||||
):
|
||||
if not user.store_api_key:
|
||||
raise HTTPException(
|
||||
status_code=400, detail="You must have a store API key set."
|
||||
)
|
||||
raise HTTPException(status_code=400, detail="You must have a store API key set.")
|
||||
decrypted = auth_utils.decrypt_api_key(user.store_api_key, settings_service)
|
||||
return decrypted
|
||||
|
||||
|
|
@ -79,78 +75,74 @@ def create_component(
|
|||
|
||||
@router.get("/components/", response_model=ListComponentResponseModel)
|
||||
def get_components(
|
||||
search: Optional[str] = Query(None),
|
||||
status: Optional[str] = Query(None),
|
||||
is_component: Optional[bool] = Query(None),
|
||||
tags: Optional[List[str]] = Query(None),
|
||||
sort: Optional[List[str]] = Query(None),
|
||||
filter_by_user: bool = Query(False),
|
||||
search: Annotated[Optional[str], Query()] = None,
|
||||
status: Annotated[Optional[str], Query()] = None,
|
||||
is_component: Annotated[Optional[bool], Query()] = None,
|
||||
tags: Annotated[Optional[list[str]], Query()] = None,
|
||||
sort: Annotated[Union[list[str], None], Query()] = None,
|
||||
filter_by_user: Annotated[bool, Query()] = False,
|
||||
page: int = 1,
|
||||
limit: int = 10,
|
||||
store_service: StoreService = Depends(get_store_service),
|
||||
store_api_Key: Optional[str] = Depends(get_optional_user_store_api_key),
|
||||
):
|
||||
try:
|
||||
with user_data_context(store_api_Key, store_service):
|
||||
with user_data_context(api_key=store_api_Key, store_service=store_service):
|
||||
filter_conditions: List[Dict[str, Any]] = []
|
||||
result: List[ListComponentResponse] = []
|
||||
authorized = False
|
||||
result = store_service.query_components(
|
||||
api_key=store_api_Key,
|
||||
page=page,
|
||||
limit=limit,
|
||||
filter_by_user=filter_by_user,
|
||||
is_component=is_component,
|
||||
search=search,
|
||||
status=status,
|
||||
tags=tags,
|
||||
sort=sort,
|
||||
)
|
||||
try:
|
||||
comp_count = store_service.count_components(
|
||||
result, filter_conditions = store_service.query_components(
|
||||
api_key=store_api_Key,
|
||||
page=page,
|
||||
limit=limit,
|
||||
filter_by_user=filter_by_user,
|
||||
is_component=is_component,
|
||||
search=search,
|
||||
status=status,
|
||||
tags=tags,
|
||||
sort=sort,
|
||||
)
|
||||
except Exception:
|
||||
#! This should be removed once we fix the bug
|
||||
comp_count = 0
|
||||
except HTTPStatusError as exc:
|
||||
if exc.response.status_code == 403:
|
||||
raise ValueError("You are not authorized to access this public resource")
|
||||
try:
|
||||
if result:
|
||||
if len(result) >= limit:
|
||||
comp_count = store_service.count_components(
|
||||
api_key=store_api_Key,
|
||||
filter_by_user=filter_by_user,
|
||||
filter_conditions=filter_conditions,
|
||||
)
|
||||
else:
|
||||
comp_count = len(result)
|
||||
else:
|
||||
comp_count = 0
|
||||
except HTTPStatusError as exc:
|
||||
if exc.response.status_code == 403:
|
||||
raise ValueError("You are not authorized to access this public resource")
|
||||
|
||||
if store_api_Key:
|
||||
if store_api_Key and result:
|
||||
# Now, from the result, we need to get the components
|
||||
# the user likes and set the liked_by_user to True
|
||||
try:
|
||||
updated_result = update_components_with_user_data(
|
||||
result, store_service, store_api_Key
|
||||
)
|
||||
updated_result = update_components_with_user_data(result, store_service, store_api_Key)
|
||||
authorized = True
|
||||
result = updated_result
|
||||
except Exception:
|
||||
# If we get an error here, it means the user is not authorized
|
||||
authorized = False
|
||||
return ListComponentResponseModel(
|
||||
results=result, authorized=authorized, count=comp_count
|
||||
)
|
||||
return ListComponentResponseModel(results=result, authorized=authorized, count=comp_count)
|
||||
except Exception as exc:
|
||||
if isinstance(exc, HTTPStatusError):
|
||||
if exc.response.status_code == 403:
|
||||
raise HTTPException(status_code=403, detail="Forbidden")
|
||||
elif isinstance(exc, ValueError):
|
||||
raise HTTPException(status_code=403, detail=str(exc))
|
||||
|
||||
raise HTTPException(status_code=500, detail=str(exc))
|
||||
|
||||
|
||||
@router.get("/components/count", response_model=dict)
|
||||
def count_components(
|
||||
filter_by_user: bool = Query(False),
|
||||
store_service: StoreService = Depends(get_store_service),
|
||||
store_api_Key: str = Depends(get_optional_user_store_api_key),
|
||||
is_component: Optional[bool] = Query(None),
|
||||
):
|
||||
try:
|
||||
result = store_service.count_components(
|
||||
api_key=store_api_Key,
|
||||
filter_by_user=filter_by_user,
|
||||
is_component=is_component,
|
||||
)
|
||||
return {"count": result}
|
||||
except Exception as exc:
|
||||
raise HTTPException(status_code=400, detail=str(exc))
|
||||
|
||||
|
||||
@router.get("/components/{component_id}", response_model=DownloadComponentResponse)
|
||||
def read_component(
|
||||
component_id: UUID,
|
||||
|
|
@ -235,9 +227,7 @@ def like_component(
|
|||
):
|
||||
try:
|
||||
result = store_service.like_component(store_api_Key, component_id)
|
||||
likes_count = store_service.get_component_likes_count(
|
||||
store_api_Key, component_id
|
||||
)
|
||||
likes_count = store_service.get_component_likes_count(store_api_Key, component_id)
|
||||
|
||||
return UsersLikesResponse(likes_count=likes_count, liked_by_user=result)
|
||||
except Exception as exc:
|
||||
|
|
|
|||
|
|
@ -46,9 +46,7 @@ def add_user(
|
|||
session.refresh(new_user)
|
||||
except IntegrityError as e:
|
||||
session.rollback()
|
||||
raise HTTPException(
|
||||
status_code=400, detail="This username is unavailable."
|
||||
) from e
|
||||
raise HTTPException(status_code=400, detail="This username is unavailable.") from e
|
||||
|
||||
return new_user
|
||||
|
||||
|
|
@ -96,14 +94,10 @@ def patch_user(
|
|||
Update an existing user's data.
|
||||
"""
|
||||
if not user.is_superuser and user.id != user_id:
|
||||
raise HTTPException(
|
||||
status_code=403, detail="You don't have the permission to update this user"
|
||||
)
|
||||
raise HTTPException(status_code=403, detail="You don't have the permission to update this user")
|
||||
if user_update.password:
|
||||
if not user.is_superuser:
|
||||
raise HTTPException(
|
||||
status_code=400, detail="You can't change your password here"
|
||||
)
|
||||
raise HTTPException(status_code=400, detail="You can't change your password here")
|
||||
user_update.password = get_password_hash(user_update.password)
|
||||
|
||||
if user_db := get_user_by_id(session, user_id):
|
||||
|
|
@ -123,16 +117,12 @@ def reset_password(
|
|||
Reset a user's password.
|
||||
"""
|
||||
if user_id != user.id:
|
||||
raise HTTPException(
|
||||
status_code=400, detail="You can't change another user's password"
|
||||
)
|
||||
raise HTTPException(status_code=400, detail="You can't change another user's password")
|
||||
|
||||
if not user:
|
||||
raise HTTPException(status_code=404, detail="User not found")
|
||||
if verify_password(user_update.password, user.password):
|
||||
raise HTTPException(
|
||||
status_code=400, detail="You can't use your current password"
|
||||
)
|
||||
raise HTTPException(status_code=400, detail="You can't use your current password")
|
||||
new_password = get_password_hash(user_update.password)
|
||||
user.password = new_password
|
||||
session.commit()
|
||||
|
|
@ -151,13 +141,9 @@ def delete_user(
|
|||
Delete a user from the database.
|
||||
"""
|
||||
if current_user.id == user_id:
|
||||
raise HTTPException(
|
||||
status_code=400, detail="You can't delete your own user account"
|
||||
)
|
||||
raise HTTPException(status_code=400, detail="You can't delete your own user account")
|
||||
elif not current_user.is_superuser:
|
||||
raise HTTPException(
|
||||
status_code=403, detail="You don't have the permission to delete this user"
|
||||
)
|
||||
raise HTTPException(status_code=403, detail="You don't have the permission to delete this user")
|
||||
|
||||
user_db = session.query(User).filter(User.id == user_id).first()
|
||||
if not user_db:
|
||||
|
|
|
|||
|
|
@ -41,9 +41,7 @@ def post_validate_prompt(prompt_request: ValidatePromptRequest):
|
|||
|
||||
add_new_variables_to_template(input_variables, prompt_request)
|
||||
|
||||
remove_old_variables_from_template(
|
||||
old_custom_fields, input_variables, prompt_request
|
||||
)
|
||||
remove_old_variables_from_template(old_custom_fields, input_variables, prompt_request)
|
||||
|
||||
update_input_variables_field(input_variables, prompt_request)
|
||||
|
||||
|
|
@ -58,19 +56,12 @@ def post_validate_prompt(prompt_request: ValidatePromptRequest):
|
|||
|
||||
def get_old_custom_fields(prompt_request):
|
||||
try:
|
||||
if (
|
||||
len(prompt_request.frontend_node.custom_fields) == 1
|
||||
and prompt_request.name == ""
|
||||
):
|
||||
if len(prompt_request.frontend_node.custom_fields) == 1 and prompt_request.name == "":
|
||||
# If there is only one custom field and the name is empty string
|
||||
# then we are dealing with the first prompt request after the node was created
|
||||
prompt_request.name = list(
|
||||
prompt_request.frontend_node.custom_fields.keys()
|
||||
)[0]
|
||||
prompt_request.name = list(prompt_request.frontend_node.custom_fields.keys())[0]
|
||||
|
||||
old_custom_fields = prompt_request.frontend_node.custom_fields[
|
||||
prompt_request.name
|
||||
].copy()
|
||||
old_custom_fields = prompt_request.frontend_node.custom_fields[prompt_request.name].copy()
|
||||
except KeyError:
|
||||
old_custom_fields = []
|
||||
prompt_request.frontend_node.custom_fields[prompt_request.name] = []
|
||||
|
|
@ -92,40 +83,26 @@ def add_new_variables_to_template(input_variables, prompt_request):
|
|||
)
|
||||
if variable in prompt_request.frontend_node.template:
|
||||
# Set the new field with the old value
|
||||
template_field.value = prompt_request.frontend_node.template[variable][
|
||||
"value"
|
||||
]
|
||||
template_field.value = prompt_request.frontend_node.template[variable]["value"]
|
||||
|
||||
prompt_request.frontend_node.template[variable] = template_field.to_dict()
|
||||
|
||||
# Check if variable is not already in the list before appending
|
||||
if (
|
||||
variable
|
||||
not in prompt_request.frontend_node.custom_fields[prompt_request.name]
|
||||
):
|
||||
prompt_request.frontend_node.custom_fields[prompt_request.name].append(
|
||||
variable
|
||||
)
|
||||
if variable not in prompt_request.frontend_node.custom_fields[prompt_request.name]:
|
||||
prompt_request.frontend_node.custom_fields[prompt_request.name].append(variable)
|
||||
|
||||
except Exception as exc:
|
||||
logger.exception(exc)
|
||||
raise HTTPException(status_code=500, detail=str(exc)) from exc
|
||||
|
||||
|
||||
def remove_old_variables_from_template(
|
||||
old_custom_fields, input_variables, prompt_request
|
||||
):
|
||||
def remove_old_variables_from_template(old_custom_fields, input_variables, prompt_request):
|
||||
for variable in old_custom_fields:
|
||||
if variable not in input_variables:
|
||||
try:
|
||||
# Remove the variable from custom_fields associated with the given name
|
||||
if (
|
||||
variable
|
||||
in prompt_request.frontend_node.custom_fields[prompt_request.name]
|
||||
):
|
||||
prompt_request.frontend_node.custom_fields[
|
||||
prompt_request.name
|
||||
].remove(variable)
|
||||
if variable in prompt_request.frontend_node.custom_fields[prompt_request.name]:
|
||||
prompt_request.frontend_node.custom_fields[prompt_request.name].remove(variable)
|
||||
|
||||
# Remove the variable from the template
|
||||
prompt_request.frontend_node.template.pop(variable, None)
|
||||
|
|
@ -137,6 +114,4 @@ def remove_old_variables_from_template(
|
|||
|
||||
def update_input_variables_field(input_variables, prompt_request):
|
||||
if "input_variables" in prompt_request.frontend_node.template:
|
||||
prompt_request.frontend_node.template["input_variables"][
|
||||
"value"
|
||||
] = input_variables
|
||||
prompt_request.frontend_node.template["input_variables"]["value"] = input_variables
|
||||
|
|
|
|||
|
|
@ -71,7 +71,9 @@ class ConversationalAgent(CustomComponent):
|
|||
extra_prompt_messages=[MessagesPlaceholder(variable_name=memory_key)],
|
||||
)
|
||||
agent = OpenAIFunctionsAgent(
|
||||
llm=llm, tools=tools, prompt=prompt # type: ignore
|
||||
llm=llm,
|
||||
tools=tools,
|
||||
prompt=prompt, # type: ignore
|
||||
)
|
||||
return AgentExecutor(
|
||||
agent=agent,
|
||||
|
|
|
|||
|
|
@ -18,9 +18,7 @@ class PromptRunner(CustomComponent):
|
|||
"code": {"show": False},
|
||||
}
|
||||
|
||||
def build(
|
||||
self, llm: BaseLLM, prompt: PromptTemplate, inputs: dict = {}
|
||||
) -> Document:
|
||||
def build(self, llm: BaseLLM, prompt: PromptTemplate, inputs: dict = {}) -> Document:
|
||||
chain = prompt | llm
|
||||
# The input is an empty dict because the prompt is already filled
|
||||
result = chain.invoke(input=inputs)
|
||||
|
|
|
|||
|
|
@ -18,9 +18,7 @@ class MetalRetrieverComponent(CustomComponent):
|
|||
"code": {"show": False},
|
||||
}
|
||||
|
||||
def build(
|
||||
self, api_key: str, client_id: str, index_id: str, params: Optional[dict] = None
|
||||
) -> BaseRetriever:
|
||||
def build(self, api_key: str, client_id: str, index_id: str, params: Optional[dict] = None) -> BaseRetriever:
|
||||
try:
|
||||
metal = Metal(api_key=api_key, client_id=client_id, index_id=index_id)
|
||||
except Exception as e:
|
||||
|
|
|
|||
|
|
@ -10,9 +10,7 @@ from langchain.agents.agent_toolkits.base import BaseToolkit
|
|||
class MetaphorToolkit(CustomComponent):
|
||||
display_name: str = "Metaphor"
|
||||
description: str = "Metaphor Toolkit"
|
||||
documentation = (
|
||||
"https://python.langchain.com/docs/integrations/tools/metaphor_search"
|
||||
)
|
||||
documentation = "https://python.langchain.com/docs/integrations/tools/metaphor_search"
|
||||
beta = True
|
||||
# api key should be password = True
|
||||
field_config = {
|
||||
|
|
@ -33,9 +31,7 @@ class MetaphorToolkit(CustomComponent):
|
|||
@tool
|
||||
def search(query: str):
|
||||
"""Call search engine with a query."""
|
||||
return client.search(
|
||||
query, use_autoprompt=use_autoprompt, num_results=search_num_results
|
||||
)
|
||||
return client.search(query, use_autoprompt=use_autoprompt, num_results=search_num_results)
|
||||
|
||||
@tool
|
||||
def get_contents(ids: List[str]):
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue