Merge branch 'dev' into feat/aws
This commit is contained in:
commit
ef7bd714b2
15 changed files with 4059 additions and 614 deletions
|
|
@ -0,0 +1,92 @@
|
|||
from typing import Optional
|
||||
from langflow import CustomComponent
|
||||
from langchain.chat_models.baidu_qianfan_endpoint import QianfanChatEndpoint
|
||||
from langchain.llms.base import BaseLLM
|
||||
|
||||
|
||||
class QianfanChatEndpointComponent(CustomComponent):
|
||||
display_name: str = "QianfanChatEndpoint"
|
||||
description: str = (
|
||||
"Baidu Qianfan chat models. Get more detail from "
|
||||
"https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint."
|
||||
)
|
||||
|
||||
def build_config(self):
|
||||
return {
|
||||
"model": {
|
||||
"display_name": "Model Name",
|
||||
"options": [
|
||||
"ERNIE-Bot",
|
||||
"ERNIE-Bot-turbo",
|
||||
"BLOOMZ-7B",
|
||||
"Llama-2-7b-chat",
|
||||
"Llama-2-13b-chat",
|
||||
"Llama-2-70b-chat",
|
||||
"Qianfan-BLOOMZ-7B-compressed",
|
||||
"Qianfan-Chinese-Llama-2-7B",
|
||||
"ChatGLM2-6B-32K",
|
||||
"AquilaChat-7B",
|
||||
],
|
||||
"info": "https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint",
|
||||
"required": True,
|
||||
},
|
||||
"qianfan_ak": {
|
||||
"display_name": "Qianfan Ak",
|
||||
"required": True,
|
||||
"password": True,
|
||||
"info": "which you could get from https://cloud.baidu.com/product/wenxinworkshop",
|
||||
},
|
||||
"qianfan_sk": {
|
||||
"display_name": "Qianfan Sk",
|
||||
"required": True,
|
||||
"password": True,
|
||||
"info": "which you could get from https://cloud.baidu.com/product/wenxinworkshop",
|
||||
},
|
||||
"top_p": {
|
||||
"display_name": "Top p",
|
||||
"field_type": "float",
|
||||
"info": "Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo",
|
||||
"value": 0.8,
|
||||
},
|
||||
"temperature": {
|
||||
"display_name": "Temperature",
|
||||
"field_type": "float",
|
||||
"info": "Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo",
|
||||
"value": 0.95,
|
||||
},
|
||||
"penalty_score": {
|
||||
"display_name": "Penalty Score",
|
||||
"field_type": "float",
|
||||
"info": "Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo",
|
||||
"value": 1.0,
|
||||
},
|
||||
"endpoint": {
|
||||
"display_name": "Endpoint",
|
||||
"info": "Endpoint of the Qianfan LLM, required if custom model used.",
|
||||
},
|
||||
"code": {"show": False},
|
||||
}
|
||||
|
||||
def build(
|
||||
self,
|
||||
model: str = "ERNIE-Bot-turbo",
|
||||
qianfan_ak: Optional[str] = None,
|
||||
qianfan_sk: Optional[str] = None,
|
||||
top_p: Optional[float] = None,
|
||||
temperature: Optional[float] = None,
|
||||
penalty_score: Optional[float] = None,
|
||||
endpoint: Optional[str] = None,
|
||||
) -> BaseLLM:
|
||||
try:
|
||||
output = QianfanChatEndpoint( # type: ignore
|
||||
model=model,
|
||||
qianfan_ak=qianfan_ak,
|
||||
qianfan_sk=qianfan_sk,
|
||||
top_p=top_p,
|
||||
temperature=temperature,
|
||||
penalty_score=penalty_score,
|
||||
endpoint=endpoint,
|
||||
)
|
||||
except Exception as e:
|
||||
raise ValueError("Could not connect to Baidu Qianfan API.") from e
|
||||
return output # type: ignore
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
from typing import Optional
|
||||
from langflow import CustomComponent
|
||||
from langchain.llms.baidu_qianfan_endpoint import QianfanLLMEndpoint
|
||||
from langchain.llms.base import BaseLLM
|
||||
|
||||
|
||||
class QianfanLLMEndpointComponent(CustomComponent):
|
||||
display_name: str = "QianfanLLMEndpoint"
|
||||
description: str = (
|
||||
"Baidu Qianfan hosted open source or customized models. "
|
||||
"Get more detail from https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint"
|
||||
)
|
||||
|
||||
def build_config(self):
|
||||
return {
|
||||
"model": {
|
||||
"display_name": "Model Name",
|
||||
"options": [
|
||||
"ERNIE-Bot",
|
||||
"ERNIE-Bot-turbo",
|
||||
"BLOOMZ-7B",
|
||||
"Llama-2-7b-chat",
|
||||
"Llama-2-13b-chat",
|
||||
"Llama-2-70b-chat",
|
||||
"Qianfan-BLOOMZ-7B-compressed",
|
||||
"Qianfan-Chinese-Llama-2-7B",
|
||||
"ChatGLM2-6B-32K",
|
||||
"AquilaChat-7B",
|
||||
],
|
||||
"info": "https://python.langchain.com/docs/integrations/chat/baidu_qianfan_endpoint",
|
||||
"required": True,
|
||||
},
|
||||
"qianfan_ak": {
|
||||
"display_name": "Qianfan Ak",
|
||||
"required": True,
|
||||
"password": True,
|
||||
"info": "which you could get from https://cloud.baidu.com/product/wenxinworkshop",
|
||||
},
|
||||
"qianfan_sk": {
|
||||
"display_name": "Qianfan Sk",
|
||||
"required": True,
|
||||
"password": True,
|
||||
"info": "which you could get from https://cloud.baidu.com/product/wenxinworkshop",
|
||||
},
|
||||
"top_p": {
|
||||
"display_name": "Top p",
|
||||
"field_type": "float",
|
||||
"info": "Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo",
|
||||
"value": 0.8,
|
||||
},
|
||||
"temperature": {
|
||||
"display_name": "Temperature",
|
||||
"field_type": "float",
|
||||
"info": "Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo",
|
||||
"value": 0.95,
|
||||
},
|
||||
"penalty_score": {
|
||||
"display_name": "Penalty Score",
|
||||
"field_type": "float",
|
||||
"info": "Model params, only supported in ERNIE-Bot and ERNIE-Bot-turbo",
|
||||
"value": 1.0,
|
||||
},
|
||||
"endpoint": {
|
||||
"display_name": "Endpoint",
|
||||
"info": "Endpoint of the Qianfan LLM, required if custom model used.",
|
||||
},
|
||||
"code": {"show": False},
|
||||
}
|
||||
|
||||
def build(
|
||||
self,
|
||||
model: str = "ERNIE-Bot-turbo",
|
||||
qianfan_ak: Optional[str] = None,
|
||||
qianfan_sk: Optional[str] = None,
|
||||
top_p: Optional[float] = None,
|
||||
temperature: Optional[float] = None,
|
||||
penalty_score: Optional[float] = None,
|
||||
endpoint: Optional[str] = None,
|
||||
) -> BaseLLM:
|
||||
try:
|
||||
output = QianfanLLMEndpoint( # type: ignore
|
||||
model=model,
|
||||
qianfan_ak=qianfan_ak,
|
||||
qianfan_sk=qianfan_sk,
|
||||
top_p=top_p,
|
||||
temperature=temperature,
|
||||
penalty_score=penalty_score,
|
||||
endpoint=endpoint,
|
||||
)
|
||||
except Exception as e:
|
||||
raise ValueError("Could not connect to Baidu Qianfan API.") from e
|
||||
return output # type: ignore
|
||||
|
|
@ -5,7 +5,6 @@ from langchain.vectorstores import Vectara
|
|||
from langchain.schema import Document
|
||||
from langchain.vectorstores.base import VectorStore
|
||||
from langchain.schema import BaseRetriever
|
||||
from langchain.embeddings.base import Embeddings
|
||||
|
||||
|
||||
class VectaraComponent(CustomComponent):
|
||||
|
|
@ -22,7 +21,6 @@ class VectaraComponent(CustomComponent):
|
|||
"vectara_api_key": {"display_name": "Vectara API Key", "password": True},
|
||||
"code": {"show": False},
|
||||
"documents": {"display_name": "Documents"},
|
||||
"embedding": {"display_name": "Embedding"},
|
||||
}
|
||||
|
||||
def build(
|
||||
|
|
@ -30,21 +28,21 @@ class VectaraComponent(CustomComponent):
|
|||
vectara_customer_id: str,
|
||||
vectara_corpus_id: str,
|
||||
vectara_api_key: str,
|
||||
embedding: Optional[Embeddings] = None,
|
||||
documents: Optional[Document] = None,
|
||||
) -> Union[VectorStore, BaseRetriever]:
|
||||
# If documents, then we need to create a Vectara instance using .from_documents
|
||||
if documents is not None and embedding is not None:
|
||||
if documents is not None:
|
||||
return Vectara.from_documents(
|
||||
documents=documents, # type: ignore
|
||||
vectara_customer_id=vectara_customer_id,
|
||||
vectara_corpus_id=vectara_corpus_id,
|
||||
vectara_api_key=vectara_api_key,
|
||||
embedding=embedding,
|
||||
source="langflow",
|
||||
)
|
||||
|
||||
return Vectara(
|
||||
vectara_customer_id=vectara_customer_id,
|
||||
vectara_corpus_id=vectara_corpus_id,
|
||||
vectara_api_key=vectara_api_key,
|
||||
source="langflow",
|
||||
)
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ class FieldFormatters(BaseModel):
|
|||
|
||||
class FrontendNode(BaseModel):
|
||||
template: Template
|
||||
description: str
|
||||
description: Optional[str] = None
|
||||
base_classes: List[str]
|
||||
name: str = ""
|
||||
display_name: str = ""
|
||||
|
|
|
|||
|
|
@ -260,9 +260,6 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
|||
|
||||
// simulate a click on the link element to trigger the download
|
||||
link.click();
|
||||
setNoticeData({
|
||||
title: "Warning: Critical data, JSON file may include API keys.",
|
||||
});
|
||||
}
|
||||
|
||||
function downloadFlows() {
|
||||
|
|
@ -300,7 +297,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
|||
let fileData = JSON.parse(text);
|
||||
if (fileData.flows) {
|
||||
fileData.flows.forEach((flow: FlowType) => {
|
||||
id = addFlow(flow, newProject);
|
||||
id = addFlow(newProject, flow);
|
||||
});
|
||||
}
|
||||
// parse the text into a JSON object
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import IconComponent from "../../components/genericIconComponent";
|
|||
import { Button } from "../../components/ui/button";
|
||||
import { Checkbox } from "../../components/ui/checkbox";
|
||||
import { EXPORT_DIALOG_SUBTITLE } from "../../constants/constants";
|
||||
import { alertContext } from "../../contexts/alertContext";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import { removeApiKeys } from "../../utils/reactflowUtils";
|
||||
import BaseModal from "../baseModal";
|
||||
|
|
@ -11,7 +12,8 @@ import BaseModal from "../baseModal";
|
|||
const ExportModal = forwardRef(
|
||||
(props: { children: ReactNode }, ref): JSX.Element => {
|
||||
const { flows, tabId, downloadFlow } = useContext(TabsContext);
|
||||
const [checked, setChecked] = useState(false);
|
||||
const { setNoticeData } = useContext(alertContext);
|
||||
const [checked, setChecked] = useState(true);
|
||||
const flow = flows.find((f) => f.id === tabId);
|
||||
useEffect(() => {
|
||||
setName(flow!.name);
|
||||
|
|
@ -44,6 +46,7 @@ const ExportModal = forwardRef(
|
|||
<div className="mt-3 flex items-center space-x-2">
|
||||
<Checkbox
|
||||
id="terms"
|
||||
checked={checked}
|
||||
onCheckedChange={(event: boolean) => {
|
||||
setChecked(event);
|
||||
}}
|
||||
|
|
@ -52,18 +55,26 @@ const ExportModal = forwardRef(
|
|||
Save with my API keys
|
||||
</label>
|
||||
</div>
|
||||
<span className="text-xs text-destructive">
|
||||
Caution: Uncheck this box only removes API keys from fields
|
||||
specifically designated for API keys.
|
||||
</span>
|
||||
</BaseModal.Content>
|
||||
|
||||
<BaseModal.Footer>
|
||||
<Button
|
||||
onClick={() => {
|
||||
if (checked)
|
||||
if (checked) {
|
||||
downloadFlow(
|
||||
flows.find((flow) => flow.id === tabId)!,
|
||||
name!,
|
||||
description
|
||||
);
|
||||
else
|
||||
setNoticeData({
|
||||
title:
|
||||
"Warning: Critical data, JSON file may include API keys.",
|
||||
});
|
||||
} else
|
||||
downloadFlow(
|
||||
removeApiKeys(flows.find((flow) => flow.id === tabId)!),
|
||||
name!,
|
||||
|
|
|
|||
2684
src/frontend/tests/onlyFront/assets/collection.json
Normal file
2684
src/frontend/tests/onlyFront/assets/collection.json
Normal file
File diff suppressed because it is too large
Load diff
96
src/frontend/tests/onlyFront/assets/flow.json
Normal file
96
src/frontend/tests/onlyFront/assets/flow.json
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
{
|
||||
"description": "Engineered for Excellence, Built for Business.",
|
||||
"name": "Fluffy Sinoussi",
|
||||
"data": {
|
||||
"nodes": [
|
||||
{
|
||||
"id": "AgentInitializer-Zza0A",
|
||||
"type": "genericNode",
|
||||
"position": { "x": 595, "y": 224.25 },
|
||||
"data": {
|
||||
"type": "AgentInitializer",
|
||||
"node": {
|
||||
"template": {
|
||||
"llm": {
|
||||
"required": true,
|
||||
"placeholder": "",
|
||||
"show": true,
|
||||
"multiline": false,
|
||||
"password": false,
|
||||
"name": "llm",
|
||||
"display_name": "LLM",
|
||||
"advanced": false,
|
||||
"dynamic": false,
|
||||
"info": "",
|
||||
"type": "BaseLanguageModel",
|
||||
"list": false
|
||||
},
|
||||
"memory": {
|
||||
"required": false,
|
||||
"placeholder": "",
|
||||
"show": true,
|
||||
"multiline": false,
|
||||
"password": false,
|
||||
"name": "memory",
|
||||
"advanced": false,
|
||||
"dynamic": false,
|
||||
"info": "",
|
||||
"type": "BaseChatMemory",
|
||||
"list": false
|
||||
},
|
||||
"tools": {
|
||||
"required": true,
|
||||
"placeholder": "",
|
||||
"show": true,
|
||||
"multiline": false,
|
||||
"password": false,
|
||||
"name": "tools",
|
||||
"advanced": false,
|
||||
"dynamic": false,
|
||||
"info": "",
|
||||
"type": "Tool",
|
||||
"list": true
|
||||
},
|
||||
"agent": {
|
||||
"required": true,
|
||||
"placeholder": "",
|
||||
"show": true,
|
||||
"multiline": false,
|
||||
"value": "zero-shot-react-description",
|
||||
"password": false,
|
||||
"options": [
|
||||
"zero-shot-react-description",
|
||||
"react-docstore",
|
||||
"self-ask-with-search",
|
||||
"conversational-react-description",
|
||||
"openai-functions",
|
||||
"openai-multi-functions"
|
||||
],
|
||||
"name": "agent",
|
||||
"advanced": false,
|
||||
"dynamic": false,
|
||||
"info": "",
|
||||
"type": "str",
|
||||
"list": true
|
||||
},
|
||||
"_type": "initialize_agent"
|
||||
},
|
||||
"description": "Construct a zero shot agent from an LLM and tools.",
|
||||
"base_classes": ["AgentExecutor", "function"],
|
||||
"display_name": "AgentInitializer",
|
||||
"custom_fields": {},
|
||||
"output_types": [],
|
||||
"documentation": "https://python.langchain.com/docs/modules/agents/agent_types/",
|
||||
"beta": false,
|
||||
"error": null
|
||||
},
|
||||
"id": "AgentInitializer-Zza0A"
|
||||
},
|
||||
"positionAbsolute": { "x": 595, "y": 224.25 }
|
||||
}
|
||||
],
|
||||
"edges": [],
|
||||
"viewport": { "x": 0, "y": 0, "zoom": 1 }
|
||||
},
|
||||
"id": "84c4b46f-063b-4d48-bf7f-6c668013064f"
|
||||
}
|
||||
87
src/frontend/tests/onlyFront/dragAndDrop.spec.ts
Normal file
87
src/frontend/tests/onlyFront/dragAndDrop.spec.ts
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
import { readFileSync } from "fs";
|
||||
|
||||
test.describe("drag and drop test", () => {
|
||||
/// <reference lib="dom"/>
|
||||
test("drop collection", async ({ page }) => {
|
||||
await page.routeFromHAR("harFiles/langflow.har", {
|
||||
url: "**/api/v1/**",
|
||||
update: false,
|
||||
});
|
||||
await page.route("**/api/v1/flows/", async (route) => {
|
||||
const json = {
|
||||
id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210",
|
||||
};
|
||||
await route.fulfill({ json, status: 201 });
|
||||
});
|
||||
await page.goto("http:localhost:3000/");
|
||||
await page.locator("span").filter({ hasText: "My Collection" }).isVisible();
|
||||
// Read your file into a buffer.
|
||||
const jsonContent = readFileSync(
|
||||
"tests/onlyFront/assets/collection.json",
|
||||
"utf-8"
|
||||
);
|
||||
|
||||
// Create the DataTransfer and File
|
||||
const dataTransfer = await page.evaluateHandle((data) => {
|
||||
const dt = new DataTransfer();
|
||||
// Convert the buffer to a hex array
|
||||
const file = new File([data], "collection.json", {
|
||||
type: "application/json",
|
||||
});
|
||||
dt.items.add(file);
|
||||
return dt;
|
||||
}, jsonContent);
|
||||
|
||||
// Now dispatch
|
||||
await page.dispatchEvent('//*[@id="root"]/div/div[2]/div[2]', "drop", {
|
||||
dataTransfer,
|
||||
});
|
||||
expect(
|
||||
await page
|
||||
.locator(".main-page-flows-display")
|
||||
.evaluate((el) => el.children)
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
test("drop flow", async ({ page }) => {
|
||||
await page.routeFromHAR("harFiles/langflow.har", {
|
||||
url: "**/api/v1/**",
|
||||
update: false,
|
||||
});
|
||||
await page.route("**/api/v1/flows/", async (route) => {
|
||||
const json = {
|
||||
id: "e9ac1bdc-429b-475d-ac03-d26f9a2a3210",
|
||||
};
|
||||
await route.fulfill({ json, status: 201 });
|
||||
});
|
||||
await page.goto("http:localhost:3000/");
|
||||
await page.locator("span").filter({ hasText: "My Collection" }).isVisible();
|
||||
// Read your file into a buffer.
|
||||
const jsonContent = readFileSync(
|
||||
"tests/onlyFront/assets/flow.json",
|
||||
"utf-8"
|
||||
);
|
||||
|
||||
// Create the DataTransfer and File
|
||||
const dataTransfer = await page.evaluateHandle((data) => {
|
||||
const dt = new DataTransfer();
|
||||
// Convert the buffer to a hex array
|
||||
const file = new File([data], "flow.json", {
|
||||
type: "application/json",
|
||||
});
|
||||
dt.items.add(file);
|
||||
return dt;
|
||||
}, jsonContent);
|
||||
|
||||
// Now dispatch
|
||||
await page.dispatchEvent('//*[@id="root"]/div/div[2]/div[2]', "drop", {
|
||||
dataTransfer,
|
||||
});
|
||||
expect(
|
||||
await page
|
||||
.locator(".main-page-flows-display")
|
||||
.evaluate((el) => el.children)
|
||||
).toBeTruthy();
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue