Merge branch 'dev' into 335-implement-docarray-vectorstore

This commit is contained in:
Gabriel Luiz Freitas Almeida 2023-05-26 22:50:16 -03:00 • committed by GitHub
commit 12c23408e0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 138 additions and 223 deletions

View file

@ -18,59 +18,10 @@ def get_number_of_workers(workers=None):
return workers return workers
def update_settings(config: str): def update_settings(config: str, dev: 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) settings.update_from_yaml(config, dev=dev)
@app.command()
def serve(
host: str = typer.Option("127.0.0.1", help="Host to bind the server to."),
workers: int = typer.Option(1, help="Number of worker processes."),
timeout: int = typer.Option(60, help="Worker timeout in seconds."),
port: int = typer.Option(7860, help="Port to listen on."),
config: str = typer.Option("config.yaml", help="Path to the configuration file."),
log_level: str = typer.Option("info", help="Logging level."),
log_file: Path = typer.Option("logs/langflow.log", help="Path to the log file."),
jcloud: bool = typer.Option(False, help="Deploy on Jina AI Cloud"),
):
"""
Run the Langflow server.
"""
if jcloud:
return serve_on_jcloud()
configure(log_level=log_level, log_file=log_file)
update_settings(config)
app = create_app()
# get the directory of the current file
path = Path(__file__).parent
static_files_dir = path / "frontend"
app.mount(
"/",
StaticFiles(directory=static_files_dir, html=True),
name="static",
)
options = {
"bind": f"{host}:{port}",
"workers": get_number_of_workers(workers),
"worker_class": "uvicorn.workers.UvicornWorker",
"timeout": timeout,
}
if platform.system() in ["Darwin", "Windows"]:
# Run using uvicorn on MacOS and Windows
# Windows doesn't support gunicorn
# MacOS requires an env variable to be set to use gunicorn
import uvicorn
uvicorn.run(app, host=host, port=port, log_level=log_level)
else:
from langflow.server import LangflowApplication
LangflowApplication(app, options).run()
def serve_on_jcloud(): def serve_on_jcloud():
@ -119,6 +70,56 @@ def serve_on_jcloud():
click.secho("https://github.com/jina-ai/langchain-serve", fg="blue") click.secho("https://github.com/jina-ai/langchain-serve", fg="blue")
@app.command()
def serve(
host: str = typer.Option("127.0.0.1", help="Host to bind the server to."),
workers: int = typer.Option(1, help="Number of worker processes."),
timeout: int = typer.Option(60, help="Worker timeout in seconds."),
port: int = typer.Option(7860, help="Port to listen on."),
config: str = typer.Option("config.yaml", help="Path to the configuration file."),
log_level: str = typer.Option("info", help="Logging level."),
log_file: Path = typer.Option("logs/langflow.log", help="Path to the log file."),
jcloud: bool = typer.Option(False, help="Deploy on Jina AI Cloud"),
dev: bool = typer.Option(False, help="Run in development mode (may contain bugs)"),
):
"""
Run the Langflow server.
"""
if jcloud:
return serve_on_jcloud()
configure(log_level=log_level, log_file=log_file)
update_settings(config, dev=dev)
app = create_app()
# get the directory of the current file
path = Path(__file__).parent
static_files_dir = path / "frontend"
app.mount(
"/",
StaticFiles(directory=static_files_dir, html=True),
name="static",
)
options = {
"bind": f"{host}:{port}",
"workers": get_number_of_workers(workers),
"worker_class": "uvicorn.workers.UvicornWorker",
"timeout": timeout,
}
if platform.system() in ["Darwin", "Windows"]:
# Run using uvicorn on MacOS and Windows
# Windows doesn't support gunicorn
# MacOS requires an env variable to be set to use gunicorn
import uvicorn
uvicorn.run(app, host=host, port=port, log_level=log_level)
else:
from langflow.server import LangflowApplication
LangflowApplication(app, options).run()
def main(): def main():
app() app()

View file

@ -16,7 +16,6 @@ chains:
- MidJourneyPromptChain - MidJourneyPromptChain
- TimeTravelGuideChain - TimeTravelGuideChain
- SQLDatabaseChain - SQLDatabaseChain
dev: false
documentloaders: documentloaders:
- AirbyteJSONLoader - AirbyteJSONLoader
- CoNLLULoader - CoNLLULoader
@ -109,9 +108,6 @@ utilities:
- SQLDatabase - SQLDatabase
vectorstores: vectorstores:
- Chroma - Chroma
- DocArrayHnswSearch
- DocArrayInMemorySearch
- Qdrant
wrappers: wrappers:
- RequestsWrapper # Wait more tests - RequestsWrapper # Wait more tests
# - ChatPromptTemplate # - ChatPromptTemplate

View file

@ -32,7 +32,7 @@ class Settings(BaseSettings):
values[key] = [] values[key] = []
return values return values
def update_from_yaml(self, file_path: str): def update_from_yaml(self, file_path: str, dev: bool = False):
new_settings = load_settings_from_yaml(file_path) new_settings = load_settings_from_yaml(file_path)
self.chains = new_settings.chains or [] self.chains = new_settings.chains or []
self.agents = new_settings.agents or [] self.agents = new_settings.agents or []
@ -44,7 +44,7 @@ class Settings(BaseSettings):
self.toolkits = new_settings.toolkits or [] self.toolkits = new_settings.toolkits or []
self.textsplitters = new_settings.textsplitters or [] self.textsplitters = new_settings.textsplitters or []
self.utilities = new_settings.utilities or [] self.utilities = new_settings.utilities or []
self.dev = new_settings.dev or False self.dev = dev
def save_settings_to_yaml(settings: Settings, file_path: str): def save_settings_to_yaml(settings: Settings, file_path: str):

View file

@ -14,7 +14,6 @@ export default function FloatComponent({
onChange(""); onChange("");
} }
}, [disabled, onChange]); }, [disabled, onChange]);
const {setDisableCopyPaste} = useContext(TabsContext)
return ( return (
<div className={disabled ? "pointer-events-none cursor-not-allowed" : ""}> <div className={disabled ? "pointer-events-none cursor-not-allowed" : ""}>
<input <input
@ -29,12 +28,7 @@ export default function FloatComponent({
setMyValue(e.target.value); setMyValue(e.target.value);
onChange(e.target.value); onChange(e.target.value);
}} }}
onBlur={() => {
setDisableCopyPaste(false)
}}
onFocus={() => {
setDisableCopyPaste(true)
}}
/> />
</div> </div>
); );

View file

@ -11,7 +11,6 @@ export default function InputComponent({
}: InputComponentType) { }: InputComponentType) {
const [myValue, setMyValue] = useState(value ?? ""); const [myValue, setMyValue] = useState(value ?? "");
const [pwdVisible, setPwdVisible] = useState(false); const [pwdVisible, setPwdVisible] = useState(false);
const {setDisableCopyPaste} = useContext(TabsContext)
useEffect(() => { useEffect(() => {
if (disabled) { if (disabled) {
setMyValue(""); setMyValue("");
@ -28,12 +27,7 @@ export default function InputComponent({
> >
<input <input
value={myValue} value={myValue}
onBlur={() => {
setDisableCopyPaste(false)
}}
onFocus={() => {
setDisableCopyPaste(true)
}}
className={classNames( className={classNames(
"block w-full pr-12 form-input dark:bg-gray-900 dark:border-gray-600 rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm", "block w-full pr-12 form-input dark:bg-gray-900 dark:border-gray-600 rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm",
disabled ? " bg-gray-200 dark:bg-gray-700" : "", disabled ? " bg-gray-200 dark:bg-gray-700" : "",

View file

@ -17,7 +17,6 @@ export default function InputListComponent({
onChange([""]); onChange([""]);
} }
}, [disabled, onChange]); }, [disabled, onChange]);
const {setDisableCopyPaste} = useContext(TabsContext)
return ( return (
<div <div
className={ className={
@ -43,12 +42,6 @@ export default function InputListComponent({
}); });
onChange(inputList); onChange(inputList);
}} }}
onBlur={() => {
setDisableCopyPaste(false)
}}
onFocus={() => {
setDisableCopyPaste(true)
}}
/> />
{idx === inputList.length - 1 ? ( {idx === inputList.length - 1 ? (
<button <button

View file

@ -14,7 +14,6 @@ export default function IntComponent({
onChange(""); onChange("");
} }
}, [disabled, onChange]); }, [disabled, onChange]);
const {setDisableCopyPaste} =useContext(TabsContext)
return ( return (
<div <div
className={ className={
@ -45,12 +44,7 @@ export default function IntComponent({
setMyValue(e.target.value); setMyValue(e.target.value);
onChange(e.target.value); onChange(e.target.value);
}} }}
onBlur={() => {
setDisableCopyPaste(false)
}}
onFocus={() => {
setDisableCopyPaste(true)
}}
/> />
</div> </div>

View file

@ -17,8 +17,6 @@ export default function ChatInput({
} }
}, [chatValue]); }, [chatValue]);
const { setDisableCopyPaste } = useContext(TabsContext);
return ( return (
<div className="relative"> <div className="relative">
<textarea <textarea
@ -27,12 +25,6 @@ export default function ChatInput({
sendMessage(); sendMessage();
} }
}} }}
onBlur={() => {
setDisableCopyPaste(false)
}}
onFocus={() => {
setDisableCopyPaste(true)
}}
rows={1} rows={1}
ref={inputRef} ref={inputRef}
disabled={lockChat} disabled={lockChat}

View file

@ -15,7 +15,7 @@ import { sendAllProps } from "../../types/api";
import { ChatMessageType, ChatType } from "../../types/chat"; import { ChatMessageType, ChatType } from "../../types/chat";
import ChatInput from "./chatInput"; import ChatInput from "./chatInput";
import _ from "lodash"; import _, { set } from "lodash";
export default function ChatModal({ export default function ChatModal({
flow, flow,
@ -100,9 +100,9 @@ export default function ChatModal({
function handleOnClose(event: CloseEvent) { function handleOnClose(event: CloseEvent) {
if (isOpen.current) { if (isOpen.current) {
setErrorData({ title: event.reason }); setErrorData({ title: event.reason });
setLockChat(false);
setTimeout(() => { setTimeout(() => {
connectWS(); connectWS();
setLockChat(false);
}, 1000); }, 1000);
} }
} }
@ -235,6 +235,13 @@ export default function ChatModal({
}; };
}, []); }, []);
useEffect(() => {
if((ws.current.readyState=== ws.current.CLOSED || ws.current.readyState=== ws.current.CLOSING)){
connectWS();
setLockChat(false);
}
},[lockChat]);
async function sendAll(data: sendAllProps) { async function sendAll(data: sendAllProps) {
try { try {
if (ws) { if (ws) {
@ -339,6 +346,7 @@ export default function ChatModal({
function clearChat() { function clearChat() {
setChatHistory([]); setChatHistory([]);
ws.current.send(JSON.stringify({ clear_history: true })); ws.current.send(JSON.stringify({ clear_history: true }));
if(lockChat) setLockChat(false);
} }
function setModalOpen(x: boolean) { function setModalOpen(x: boolean) {

View file

@ -23,7 +23,6 @@ export default function CodeAreaModal({
const [code, setCode] = useState(value); const [code, setCode] = useState(value);
const { dark } = useContext(darkContext); const { dark } = useContext(darkContext);
const { setErrorData, setSuccessData } = useContext(alertContext); const { setErrorData, setSuccessData } = useContext(alertContext);
const { setDisableCopyPaste } = useContext(TabsContext);
const { closePopUp } = useContext(PopUpContext); const { closePopUp } = useContext(PopUpContext);
const ref = useRef(); const ref = useRef();
function setModalOpen(x: boolean) { function setModalOpen(x: boolean) {
@ -111,12 +110,6 @@ export default function CodeAreaModal({
onChange={(value) => { onChange={(value) => {
setCode(value); setCode(value);
}} }}
onBlur={() => {
setDisableCopyPaste(false)
}}
onFocus={() => {
setDisableCopyPaste(true)
}}
className="h-full w-full rounded-lg" className="h-full w-full rounded-lg"
/> />
</div> </div>

View file

@ -16,7 +16,7 @@ export default function ExportModal() {
const { closePopUp } = useContext(PopUpContext); const { closePopUp } = useContext(PopUpContext);
const ref = useRef(); const ref = useRef();
const { setErrorData } = useContext(alertContext); const { setErrorData } = useContext(alertContext);
const { flows, tabIndex, updateFlow, downloadFlow,setDisableCopyPaste } = useContext(TabsContext); const { flows, tabIndex, updateFlow, downloadFlow } = useContext(TabsContext);
function setModalOpen(x: boolean) { function setModalOpen(x: boolean) {
setOpen(x); setOpen(x);
if (x === false) { if (x === false) {
@ -113,12 +113,6 @@ export default function ExportModal() {
placeholder="File name" placeholder="File name"
id="name" id="name"
className="focus:border focus:border-blue block w-full px-3 py-2 border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-800 dark:border-gray-600 dark:focus:border-blue-500 dark:focus:ring-blue-500 text-gray-900 dark:text-gray-100" className="focus:border focus:border-blue block w-full px-3 py-2 border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-800 dark:border-gray-600 dark:focus:border-blue-500 dark:focus:ring-blue-500 text-gray-900 dark:text-gray-100"
onBlur={() => {
setDisableCopyPaste(false);
}}
onFocus={() => {
setDisableCopyPaste(true);
}}
/> />
</div> </div>
<div className="w-full"> <div className="w-full">
@ -133,12 +127,6 @@ export default function ExportModal() {
</span> </span>
</label> </label>
<textarea <textarea
onBlur={() => {
setDisableCopyPaste(false);
}}
onFocus={() => {
setDisableCopyPaste(true);
}}
name="description" name="description"
id="description" id="description"
onChange={(event) => { onChange={(event) => {
@ -163,12 +151,7 @@ export default function ExportModal() {
id="checkbox" id="checkbox"
type="checkbox" type="checkbox"
className="h-4 w-4 text-blue-600 border-gray-300 rounded dark:bg-gray-800 dark:border-gray-600 dark:focus:border-blue-500 dark:focus:ring-blue-500" className="h-4 w-4 text-blue-600 border-gray-300 rounded dark:bg-gray-800 dark:border-gray-600 dark:focus:border-blue-500 dark:focus:ring-blue-500"
onBlur={() => {
setDisableCopyPaste(false);
}}
onFocus={() => {
setDisableCopyPaste(true);
}}
/> />
<span className="ml-2 font-medium text-gray-700 dark:text-white"> <span className="ml-2 font-medium text-gray-700 dark:text-white">
Save with my API keys Save with my API keys

View file

@ -24,7 +24,7 @@ export default function ButtonBox({
}) { }) {
let bigCircle: string; let bigCircle: string;
let smallCircle: string; let smallCircle: string;
let minTitleFontSize: number; let titleFontSize: string;
let descriptionFontSize: string; let descriptionFontSize: string;
let padding: string; let padding: string;
let marginTop: string; let marginTop: string;
@ -32,88 +32,48 @@ export default function ButtonBox({
let width: string; let width: string;
let textHeight: number; let textHeight: number;
let textWidth: number; let textWidth: number;
const [truncate, setTruncate] = useState<boolean>(false);
switch (size) { switch (size) {
case "small": case "small":
bigCircle = "h-12 w-12"; bigCircle = "h-12 w-12";
smallCircle = "h-8 w-8"; smallCircle = "h-8 w-8";
minTitleFontSize =9; titleFontSize = "text-sm";
descriptionFontSize = "text-xs"; descriptionFontSize = "text-xs";
padding = "p-2 py-3"; padding = "p-2 py-3";
marginTop = "mt-2"; marginTop = "mt-2";
height = "h-36"; height = "h-36";
textHeight = 70; width = "w-32";
textWidth = 40; break;
width = "w-32"; case "medium":
break; bigCircle = "h-16 w-16";
case "medium": smallCircle = "h-12 w-12";
bigCircle = "h-16 w-16"; titleFontSize = "text-base";
smallCircle = "h-12 w-12"; descriptionFontSize = "text-sm";
minTitleFontSize = 11; padding = "p-4 py-5";
descriptionFontSize = "text-sm"; marginTop = "mt-3";
padding = "p-4 py-5"; height = "h-44";
marginTop = "mt-3"; width = "w-36";
textHeight = 112; break;
textWidth = 162; case "big":
height = "h-44"; bigCircle = "h-20 w-20";
width = "w-36"; smallCircle = "h-16 w-16";
break; titleFontSize = "text-lg";
case "big": descriptionFontSize = "text-sm";
bigCircle = "h-20 w-20"; padding = "p-8 py-10";
smallCircle = "h-16 w-16"; marginTop = "mt-6";
minTitleFontSize = 12; height = "h-56";
descriptionFontSize = "text-sm"; width = "w-44";
padding = "p-8 py-10"; break;
marginTop = "mt-6"; default:
height = "h-56"; bigCircle = "h-20 w-20";
width = "w-44"; smallCircle = "h-16 w-16";
break; titleFontSize = "text-lg";
default: descriptionFontSize = "text-sm";
bigCircle = "h-20 w-20"; padding = "p-8 py-10";
smallCircle = "h-16 w-16"; marginTop = "mt-6";
minTitleFontSize = 12; height = "h-56";
descriptionFontSize = "text-sm"; width = "w-44";
padding = "p-8 py-10"; break;
marginTop = "mt-6";
height = "h-56";
width = "w-44";
break;
}
const [fontSize, setFontSize] = useState<number>(16); // Initial font size value
const titleRef = useRef<HTMLHeadingElement>(null);
const parentDivRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const textElement = titleRef.current;
const parentDivElement = parentDivRef.current;
if (!textElement || !parentDivElement) return;
const parentDivHeight = parentDivElement.offsetHeight;
const parentDivWidth = parentDivElement.offsetWidth;
let textElementHeight = textElement.scrollHeight;
let textElementWidth = textElement.scrollWidth;
if (textElementHeight > parentDivHeight || textElementWidth > parentDivWidth && fontSize > minTitleFontSize) {
let newFontSize = fontSize;
while (textElementHeight > parentDivHeight || textElementWidth > parentDivWidth) {
newFontSize -= 1;
textElement.style.fontSize = `${newFontSize}px`;
textElementHeight = textElement.scrollHeight;
textElementWidth = textElement.scrollWidth;
}
if(newFontSize <= minTitleFontSize){
setTruncate(true);
setFontSize(minTitleFontSize);
}
else{
setFontSize(newFontSize);
}
} }
}, [title, size, fontSize]);
return ( return (
@ -136,15 +96,17 @@ export default function ButtonBox({
<div className={textColor}>{icon}</div> <div className={textColor}>{icon}</div>
</div> </div>
</div> </div>
<div ref={parentDivRef} className="w-full h-1/2 mt-auto"> <div className="w-full mt-auto mb-auto">
<div <h3
ref={titleRef} className={classNames(
className={classNames(truncate?"truncate":"", "w-full font-semibold break-words text-white dark:text-white/80 truncate-multiline",
" font-semibold text-white h-full dark:text-white/80", titleFontSize,
)} > marginTop
{title} )}
</div> >
</div> {title}
</h3>
</div>
</div> </div>
</button> </button>
); );

View file

@ -177,10 +177,10 @@ export default function ImportModal() {
!loadingExamples && !loadingExamples &&
examples.map((example, index) => { examples.map((example, index) => {
return ( return (
<div id="index"> <div key={index}>
{" "} {" "}
<ButtonBox <ButtonBox
size="big" size="small"
bgColor="bg-emerald-500 dark:bg-emerald-500/75" bgColor="bg-emerald-500 dark:bg-emerald-500/75"
description={ description={
example.description ?? "Prebuilt Examples" example.description ?? "Prebuilt Examples"

View file

@ -14,7 +14,7 @@ export default function TabComponent({
selected: boolean; selected: boolean;
onClick: () => void; onClick: () => void;
}) { }) {
const { removeFlow, updateFlow, flows, setDisableCopyPaste } = useContext(TabsContext); const { removeFlow, updateFlow, flows } = useContext(TabsContext);
const [isRename, setIsRename] = useState(false); const [isRename, setIsRename] = useState(false);
const [value, setValue] = useState(""); const [value, setValue] = useState("");
return ( return (
@ -40,14 +40,10 @@ export default function TabComponent({
<div className="bg-white dark:text-white dark:bg-gray-700/60 flex select-none justify-between w-44 items-center border border-b-0 border-gray-300 dark:border-gray-600 px-4 py-1 rounded-t-xl -ml-px"> <div className="bg-white dark:text-white dark:bg-gray-700/60 flex select-none justify-between w-44 items-center border border-b-0 border-gray-300 dark:border-gray-600 px-4 py-1 rounded-t-xl -ml-px">
{isRename ? ( {isRename ? (
<input <input
onFocus={() => {
setDisableCopyPaste(true);
}}
autoFocus autoFocus
className="bg-transparent focus:border-none active:outline hover:outline focus:outline outline-gray-300 rounded-md w-28" className="bg-transparent focus:border-none active:outline hover:outline focus:outline outline-gray-300 rounded-md w-28"
onBlur={() => { onBlur={() => {
setIsRename(false); setIsRename(false);
setDisableCopyPaste(false);
if (value !== "") { if (value !== "") {
let newFlow = _.cloneDeep(flow); let newFlow = _.cloneDeep(flow);
newFlow.name = value; newFlow.name = value;

View file

@ -155,10 +155,6 @@ export default function FlowPage({ flow }: { flow: FlowType }) {
params.targetHandle.split("|")[0] === "Text" params.targetHandle.split("|")[0] === "Text"
? { stroke: "#333333", strokeWidth: 2 } ? { stroke: "#333333", strokeWidth: 2 }
: { stroke: "#222222" }, : { stroke: "#222222" },
className:
params.targetHandle.split("|")[0] === "Text"
? ""
: "animate-pulse",
animated: params.targetHandle.split("|")[0] === "Text", animated: params.targetHandle.split("|")[0] === "Text",
}, },
eds eds
@ -306,8 +302,10 @@ export default function FlowPage({ flow }: { flow: FlowType }) {
setLastSelection(flow); setLastSelection(flow);
}, []); }, []);
const {setDisableCopyPaste} = useContext(TabsContext)
return ( return (
<div className="w-full h-full" ref={reactFlowWrapper}> <div className="w-full h-full" ref={reactFlowWrapper} >
{Object.keys(templates).length > 0 && Object.keys(types).length > 0 ? ( {Object.keys(templates).length > 0 && Object.keys(types).length > 0 ? (
<> <>
<ReactFlow <ReactFlow
@ -316,6 +314,9 @@ export default function FlowPage({ flow }: { flow: FlowType }) {
updateFlow({ ...flow, data: reactFlowInstance.toObject() }); updateFlow({ ...flow, data: reactFlowInstance.toObject() });
}} }}
edges={edges} edges={edges}
onPaneClick={() => {setDisableCopyPaste(false);}}
onNodeClick={() => {setDisableCopyPaste(true);}}
onPaneMouseLeave={() => {setDisableCopyPaste(true);}}
onNodesChange={onNodesChange} onNodesChange={onNodesChange}
onEdgesChange={onEdgesChangeMod} onEdgesChange={onEdgesChangeMod}
onConnect={onConnect} onConnect={onConnect}

View file

@ -42,6 +42,14 @@ module.exports = {
display: "none", display: "none",
}, },
}, },
".truncate-multiline": {
"display": "-webkit-box",
"-webkit-line-clamp": "3", /* Change this number to the number of lines you want to show */
"-webkit-box-orient": "vertical",
"overflow": "hidden",
"text-overflow": "ellipsis",
},
".arrow-hide": { ".arrow-hide": {
"&::-webkit-inner-spin-button": { "&::-webkit-inner-spin-button": {
"-webkit-appearance": "none", "-webkit-appearance": "none",