Merge branch 'db' of https://github.com/logspace-ai/langflow into db
This commit is contained in:
commit
1b0c173f39
7 changed files with 86 additions and 12 deletions
|
|
@ -27,12 +27,19 @@ def get_number_of_workers(workers=None):
|
||||||
return workers
|
return workers
|
||||||
|
|
||||||
|
|
||||||
def update_settings(config: str, dev: bool = False, database_url: Optional[str] = None):
|
def update_settings(
|
||||||
|
config: str,
|
||||||
|
dev: bool = False,
|
||||||
|
database_url: Optional[str] = None,
|
||||||
|
remove_api_keys: bool = False,
|
||||||
|
):
|
||||||
"""Update the settings from a config file."""
|
"""Update the settings from a config file."""
|
||||||
if config:
|
if config:
|
||||||
settings.update_from_yaml(config, dev=dev)
|
settings.update_from_yaml(config, dev=dev)
|
||||||
if database_url:
|
if database_url:
|
||||||
settings.update_database_url(database_url)
|
settings.update_settings(database_url=database_url)
|
||||||
|
if remove_api_keys:
|
||||||
|
settings.update_settings(remove_api_keys=remove_api_keys)
|
||||||
|
|
||||||
|
|
||||||
def serve_on_jcloud():
|
def serve_on_jcloud():
|
||||||
|
|
@ -107,6 +114,9 @@ def serve(
|
||||||
open_browser: bool = typer.Option(
|
open_browser: bool = typer.Option(
|
||||||
True, help="Open the browser after starting the server."
|
True, help="Open the browser after starting the server."
|
||||||
),
|
),
|
||||||
|
remove_api_keys: bool = typer.Option(
|
||||||
|
False, help="Remove API keys from the projects saved in the database."
|
||||||
|
),
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Run the Langflow server.
|
Run the Langflow server.
|
||||||
|
|
@ -132,7 +142,9 @@ def serve(
|
||||||
load_dotenv(env_file)
|
load_dotenv(env_file)
|
||||||
|
|
||||||
configure(log_level=log_level, log_file=log_file)
|
configure(log_level=log_level, log_file=log_file)
|
||||||
update_settings(config, dev=dev, database_url=database_url)
|
update_settings(
|
||||||
|
config, dev=dev, database_url=database_url, remove_api_keys=remove_api_keys
|
||||||
|
)
|
||||||
app = create_app()
|
app = create_app()
|
||||||
# get the directory of the current file
|
# get the directory of the current file
|
||||||
if not path:
|
if not path:
|
||||||
|
|
|
||||||
24
src/backend/langflow/api/utils.py
Normal file
24
src/backend/langflow/api/utils.py
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
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)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def remove_api_keys(flow: dict):
|
||||||
|
"""Remove api keys from flow data."""
|
||||||
|
if flow.get("data") and flow["data"].get("nodes"):
|
||||||
|
for node in flow["data"]["nodes"]:
|
||||||
|
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")
|
||||||
|
):
|
||||||
|
value["value"] = None
|
||||||
|
|
||||||
|
return flow
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
from typing import List
|
from typing import List
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
from langflow.settings import settings
|
||||||
|
from langflow.api.utils import remove_api_keys
|
||||||
from langflow.api.v1.schemas import FlowListCreate, FlowListRead
|
from langflow.api.v1.schemas import FlowListCreate, FlowListRead
|
||||||
from langflow.database.models.flow import (
|
from langflow.database.models.flow import (
|
||||||
Flow,
|
Flow,
|
||||||
|
|
@ -54,10 +56,13 @@ def update_flow(
|
||||||
*, session: Session = Depends(get_session), flow_id: UUID, flow: FlowUpdate
|
*, session: Session = Depends(get_session), flow_id: UUID, flow: FlowUpdate
|
||||||
):
|
):
|
||||||
"""Update a flow."""
|
"""Update a flow."""
|
||||||
|
|
||||||
db_flow = session.get(Flow, flow_id)
|
db_flow = session.get(Flow, flow_id)
|
||||||
if not db_flow:
|
if not db_flow:
|
||||||
raise HTTPException(status_code=404, detail="Flow not found")
|
raise HTTPException(status_code=404, detail="Flow not found")
|
||||||
flow_data = flow.dict(exclude_unset=True)
|
flow_data = flow.dict(exclude_unset=True)
|
||||||
|
if not settings.remove_api_keys:
|
||||||
|
flow_data = remove_api_keys(flow_data)
|
||||||
for key, value in flow_data.items():
|
for key, value in flow_data.items():
|
||||||
setattr(db_flow, key, value)
|
setattr(db_flow, key, value)
|
||||||
session.add(db_flow)
|
session.add(db_flow)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import os
|
import os
|
||||||
from typing import List, Optional
|
from typing import List
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
from pydantic import BaseSettings, root_validator
|
from pydantic import BaseSettings, root_validator
|
||||||
|
|
@ -21,6 +21,7 @@ class Settings(BaseSettings):
|
||||||
utilities: List[str] = []
|
utilities: List[str] = []
|
||||||
dev: bool = False
|
dev: bool = False
|
||||||
database_url: str = "sqlite:///./langflow.db"
|
database_url: str = "sqlite:///./langflow.db"
|
||||||
|
remove_api_keys: bool = False
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
validate_assignment = True
|
validate_assignment = True
|
||||||
|
|
@ -48,9 +49,10 @@ class Settings(BaseSettings):
|
||||||
self.utilities = new_settings.utilities or []
|
self.utilities = new_settings.utilities or []
|
||||||
self.dev = dev
|
self.dev = dev
|
||||||
|
|
||||||
def update_database_url(self, database_url: Optional[str] = None):
|
def update_settings(self, **kwargs):
|
||||||
if database_url:
|
for key, value in kwargs.items():
|
||||||
self.database_url = database_url
|
if hasattr(self, key):
|
||||||
|
setattr(self, key, value)
|
||||||
|
|
||||||
|
|
||||||
def save_settings_to_yaml(settings: Settings, file_path: str):
|
def save_settings_to_yaml(settings: Settings, file_path: str):
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,10 @@ class LLMFrontendNode(FrontendNode):
|
||||||
if field.name in SHOW_FIELDS:
|
if field.name in SHOW_FIELDS:
|
||||||
field.show = True
|
field.show = True
|
||||||
|
|
||||||
if "api" in field.name and ("key" in field.name or "token" in field.name):
|
if "api" in field.name and (
|
||||||
|
"key" in field.name
|
||||||
|
or ("token" in field.name and "tokens" not in field.name)
|
||||||
|
):
|
||||||
field.password = True
|
field.password = True
|
||||||
field.show = True
|
field.show = True
|
||||||
# Required should be False to support
|
# Required should be False to support
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,8 @@ BASE_API_URL = "${window.location.protocol}//${
|
||||||
window.location.host
|
window.location.host
|
||||||
}/ap1/v1/predict"
|
}/ap1/v1/predict"
|
||||||
FLOW_ID = "${flowId}"
|
FLOW_ID = "${flowId}"
|
||||||
|
# You can tweak the flow by adding a tweaks dictionary
|
||||||
|
# e.g {"OpenAI-XXXXX": {"model_name": "gpt-4"}}
|
||||||
TWEAKS = ${JSON.stringify(tweaks, null, 2)}
|
TWEAKS = ${JSON.stringify(tweaks, null, 2)}
|
||||||
|
|
||||||
def run_flow(message: str, flow_id: str, tweaks: dict = None) -> dict:
|
def run_flow(message: str, flow_id: str, tweaks: dict = None) -> dict:
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import _ from "lodash";
|
import _, { set } from "lodash";
|
||||||
import { useContext, useRef, useState, useEffect, useCallback } from "react";
|
import { useContext, useRef, useState, useEffect, useCallback } from "react";
|
||||||
import ReactFlow, {
|
import ReactFlow, {
|
||||||
OnSelectionChangeParams,
|
OnSelectionChangeParams,
|
||||||
|
|
@ -15,6 +15,7 @@ import ReactFlow, {
|
||||||
updateEdge,
|
updateEdge,
|
||||||
Background,
|
Background,
|
||||||
Controls,
|
Controls,
|
||||||
|
NodeChange,
|
||||||
} from "reactflow";
|
} from "reactflow";
|
||||||
import GenericNode from "../../../../CustomNodes/GenericNode";
|
import GenericNode from "../../../../CustomNodes/GenericNode";
|
||||||
import Chat from "../../../../components/chatComponent";
|
import Chat from "../../../../components/chatComponent";
|
||||||
|
|
@ -43,7 +44,9 @@ export default function Page({ flow }: { flow: FlowType }) {
|
||||||
lastCopiedSelection,
|
lastCopiedSelection,
|
||||||
setLastCopiedSelection,
|
setLastCopiedSelection,
|
||||||
tabsState,
|
tabsState,
|
||||||
saveFlow
|
saveFlow,
|
||||||
|
setTabsState,
|
||||||
|
tabId
|
||||||
} = useContext(TabsContext);
|
} = useContext(TabsContext);
|
||||||
const { types, reactFlowInstance, setReactFlowInstance, templates } =
|
const { types, reactFlowInstance, setReactFlowInstance, templates } =
|
||||||
useContext(typesContext);
|
useContext(typesContext);
|
||||||
|
|
@ -145,8 +148,31 @@ export default function Page({ flow }: { flow: FlowType }) {
|
||||||
let newX = _.cloneDeep(x);
|
let newX = _.cloneDeep(x);
|
||||||
return newX;
|
return newX;
|
||||||
});
|
});
|
||||||
|
setTabsState((prev) => {
|
||||||
|
return {
|
||||||
|
...prev,
|
||||||
|
[tabId]: {
|
||||||
|
isPending: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
},
|
},
|
||||||
[onEdgesChange, setNodes]
|
[onEdgesChange, setNodes,setTabsState,tabId]
|
||||||
|
);
|
||||||
|
|
||||||
|
const onNodesChangeMod = useCallback(
|
||||||
|
(s: NodeChange[]) => {
|
||||||
|
onNodesChange(s);
|
||||||
|
setTabsState((prev) => {
|
||||||
|
return {
|
||||||
|
...prev,
|
||||||
|
[tabId]: {
|
||||||
|
isPending: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[onNodesChange,setTabsState,tabId]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onConnect = useCallback(
|
const onConnect = useCallback(
|
||||||
|
|
@ -345,7 +371,7 @@ export default function Page({ flow }: { flow: FlowType }) {
|
||||||
onPaneMouseLeave={() => {
|
onPaneMouseLeave={() => {
|
||||||
setDisableCopyPaste(true);
|
setDisableCopyPaste(true);
|
||||||
}}
|
}}
|
||||||
onNodesChange={onNodesChange}
|
onNodesChange={onNodesChangeMod}
|
||||||
onEdgesChange={onEdgesChangeMod}
|
onEdgesChange={onEdgesChangeMod}
|
||||||
onConnect={onConnect}
|
onConnect={onConnect}
|
||||||
disableKeyboardA11y={true}
|
disableKeyboardA11y={true}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue