Merge branch 'release' into merge-release

This commit is contained in:
anovazzi1 2023-06-30 17:49:24 -03:00
commit 1dc54dda02
19 changed files with 607 additions and 156 deletions

View file

@ -19,8 +19,11 @@ async def chat(client_id: str, websocket: WebSocket):
if client_id in chat_manager.in_memory_cache:
await chat_manager.handle_websocket(client_id, websocket)
else:
# We accept the connection but close it immediately
# if the flow is not built yet
await websocket.accept()
message = "Please, build the flow before sending messages"
await websocket.close(code=status.WS_1008_POLICY_VIOLATION, reason=message)
await websocket.close(code=status.WS_1011_INTERNAL_ERROR, reason=message)
except WebSocketException as exc:
logger.error(exc)
await websocket.close(code=status.WS_1011_INTERNAL_ERROR, reason=str(exc))

View file

@ -119,6 +119,15 @@ llms:
documentation: "https://python.langchain.com/docs/modules/model_io/models/chat/integrations/anthropic"
HuggingFaceHub:
documentation: "https://python.langchain.com/docs/modules/model_io/models/llms/integrations/huggingface_hub"
VertexAI:
documentation: "https://python.langchain.com/docs/modules/model_io/models/llms/integrations/google_vertex_ai_palm"
###
# There's a bug in this component deactivating until we get it sorted: _language_models.py", line 804, in send_message
# is_blocked=safety_attributes.get("blocked", False),
# AttributeError: 'list' object has no attribute 'get'
# ChatVertexAI:
# documentation: "https://python.langchain.com/docs/modules/model_io/models/chat/integrations/google_vertex_ai_palm"
###
memories:
# https://github.com/supabase-community/supabase-py/issues/482
# ZepChatMessageHistory:

View file

@ -10,8 +10,12 @@ from langchain import (
text_splitter,
)
from langchain.agents import agent_toolkits
from langchain.chat_models import AzureChatOpenAI, ChatOpenAI
from langchain.chat_models import ChatAnthropic
from langchain.chat_models import (
AzureChatOpenAI,
ChatOpenAI,
ChatVertexAI,
ChatAnthropic,
)
from langflow.interface.importing.utils import import_class
from langflow.interface.agents.custom import CUSTOM_AGENTS
@ -22,6 +26,7 @@ llm_type_to_cls_dict = llms.type_to_cls_dict
llm_type_to_cls_dict["anthropic-chat"] = ChatAnthropic # type: ignore
llm_type_to_cls_dict["azure-chat"] = AzureChatOpenAI # type: ignore
llm_type_to_cls_dict["openai-chat"] = ChatOpenAI # type: ignore
llm_type_to_cls_dict["vertexai-chat"] = ChatVertexAI # type: ignore
# Toolkits

View file

@ -0,0 +1,9 @@
def initialize_vertexai(class_object, params):
if credentials_path := params.get("credentials"):
from google.oauth2 import service_account # type: ignore
credentials_object = service_account.Credentials.from_service_account_file(
filename=credentials_path
)
params["credentials"] = credentials_object
return class_object(**params)

View file

@ -6,6 +6,7 @@ from langchain.agents import agent as agent_module
from langchain.agents.agent import AgentExecutor
from langchain.agents.agent_toolkits.base import BaseToolkit
from langchain.agents.tools import BaseTool
from langflow.interface.initialize.llm import initialize_vertexai
from langflow.interface.initialize.vector_store import vecstore_initializer
@ -88,6 +89,15 @@ def instantiate_based_on_type(class_object, base_type, node_type, params):
return class_object(**params)
def instantiate_llm(node_type, class_object, params: Dict):
# This is a workaround so JinaChat works until streaming is implemented
# if "openai_api_base" in params and "jina" in params["openai_api_base"]:
# False if condition is True
if node_type == "VertexAI":
return initialize_vertexai(class_object=class_object, params=params)
return class_object(**params)
def instantiate_memory(node_type, class_object, params):
try:
return class_object(**params)
@ -117,10 +127,6 @@ def instantiate_retriever(node_type, class_object, params):
return class_object(**params)
def instantiate_llm(node_type, class_object, params: Dict):
return class_object(**params)
def instantiate_chains(node_type, class_object: Type[Chain], params: Dict):
if "retriever" in params and hasattr(params["retriever"], "as_retriever"):
params["retriever"] = params["retriever"].as_retriever()

View file

@ -8,6 +8,49 @@ from langflow.template.frontend_node.constants import OPENAI_API_BASE_INFO
class LLMFrontendNode(FrontendNode):
def add_extra_fields(self) -> None:
if "VertexAI" in self.template.type_name:
# Add credentials field which should of type file.
self.template.add_field(
TemplateField(
field_type="file",
required=False,
show=True,
name="credentials",
value="",
suffixes=[".json"],
fileTypes=["json"],
)
)
@staticmethod
def format_vertex_field(field: TemplateField, name: str):
if "VertexAI" in name:
advanced_fields = [
"tuned_model_name",
"verbose",
"top_p",
"top_k",
"max_output_tokens",
]
if field.name in advanced_fields:
field.advanced = True
show_fields = [
"tuned_model_name",
"verbose",
"project",
"location",
"credentials",
"max_output_tokens",
"model_name",
"temperature",
"top_p",
"top_k",
]
if field.name in show_fields:
field.show = True
@staticmethod
def format_openai_field(field: TemplateField):
if "openai" in field.name.lower():
@ -60,6 +103,8 @@ class LLMFrontendNode(FrontendNode):
LLMFrontendNode.format_azure_field(field)
if name and "llama" in name.lower():
LLMFrontendNode.format_llama_field(field)
if name and "vertex" in name.lower():
LLMFrontendNode.format_vertex_field(field, name)
SHOW_FIELDS = ["repo_id"]
if field.name in SHOW_FIELDS:
field.show = True
@ -95,6 +140,17 @@ class LLMFrontendNode(FrontendNode):
"model_file",
"model_type",
"deployment_name",
"credentials",
]:
field.advanced = False
field.show = True
if field.name == "credentials":
field.field_type = "file"
if name == "VertexAI" and field.name not in [
"callbacks",
"client",
"stop",
"tags",
"cache",
]:
field.show = True

View file

@ -51,6 +51,9 @@ export default function App() {
useEffect(() => {
// If there is an error alert open with data, add it to the alertsList
if (errorOpen && errorData) {
if(alertsList.length > 0 && JSON.stringify(alertsList[alertsList.length - 1].data)===JSON.stringify(errorData)){
return;
}
setErrorOpen(false);
setAlertsList((old) => {
let newAlertsList = [
@ -62,6 +65,9 @@ export default function App() {
}
// If there is a notice alert open with data, add it to the alertsList
else if (noticeOpen && noticeData) {
if(alertsList.length > 0 && JSON.stringify(alertsList[alertsList.length - 1].data)===JSON.stringify(noticeData)){
return;
}
setNoticeOpen(false);
setAlertsList((old) => {
let newAlertsList = [
@ -73,6 +79,9 @@ export default function App() {
}
// If there is a success alert open with data, add it to the alertsList
else if (successOpen && successData) {
if(alertsList.length > 0 && JSON.stringify(alertsList[alertsList.length - 1].data)===JSON.stringify(successData)){
return;
}
setSuccessOpen(false);
setAlertsList((old) => {
let newAlertsList = [
@ -152,4 +161,4 @@ export default function App() {
</div>
</div>
);
}
}

View file

@ -78,9 +78,9 @@ export function AlertProvider({ children }: { children: ReactNode }) {
* @param newState An object containing the new error data, including title and optional list of error messages
*/
function setErrorData(newState: { title: string; list?: Array<string> }) {
setErrorDataState(newState);
setErrorOpen(true);
if (newState.title && newState.title !== "") {
setErrorDataState(newState);
setErrorOpen(true);
setNotificationCenter(true);
pushNotificationList({
type: "error",
@ -95,9 +95,9 @@ export function AlertProvider({ children }: { children: ReactNode }) {
* @param newState An object containing the title of the notice and optionally a link.
*/
function setNoticeData(newState: { title: string; link?: string }) {
setNoticeDataState(newState);
setNoticeOpen(true);
if (newState.title && newState.title !== "") {
setNoticeDataState(newState);
setNoticeOpen(true);
// Add new notice to notification center
setNotificationCenter(true);
pushNotificationList({
@ -113,11 +113,10 @@ export function AlertProvider({ children }: { children: ReactNode }) {
* @param newState - A state object with a "title" property to set in the success data state.
*/
function setSuccessData(newState: { title: string }) {
setSuccessDataState(newState); // update the success data state with the provided new state
setSuccessOpen(true); // open the success alert
// If the new state has a "title" property, add a new success notification to the list
if (newState.title && newState.title !== "") {
setSuccessDataState(newState); // update the success data state with the provided new state
setSuccessOpen(true); // open the success alert
setNotificationCenter(true); // show the notification center
pushNotificationList({
// add the new notification to the list

View file

@ -0,0 +1,9 @@
import React, { forwardRef } from "react";
import { ReactComponent as VertexAISVG } from "./vertex_ai.svg";
export const VertexAIIcon = forwardRef<
SVGSVGElement,
React.PropsWithChildren<{}>
>((props, ref) => {
return <VertexAISVG ref={ref} {...props} />;
});

View file

@ -0,0 +1 @@
<svg viewBox="0 0 32 32" fit="" height="100%" width="100%" preserveAspectRatio="xMidYMid meet" focusable="false"><path d="M26.69 18.53a1 1 0 00-1.4-.22L16 25.17v.29a1 1 0 110 1.91v.05a1 1 0 00.6-.19l9.88-7.3a1 1 0 00.21-1.4z" fill="#80868b"></path><path d="M16 27.37a1 1 0 110-1.91v-.29l-9.29-6.86a1 1 0 00-1.4.22 1 1 0 00.21 1.4l9.89 7.3a1 1 0 00.59.19v-.05z" fill="#9ba0a5"></path><path d="M16 24.46a2 2 0 102 2 2 2 0 00-2-2zm0 2.91a1 1 0 111-.95 1 1 0 01-1 .95z" fill="#606368"></path><path d="M8 8.14a1 1 0 01-1-1V4.63a1 1 0 112 0v2.51a1 1 0 01-1 1z" fill="#9ba0a5"></path><circle cx="7.97" cy="16" r="1.01" fill="#9ba0a5"></circle><circle cx="7.97" cy="13.05" r="1.01" fill="#9ba0a5"></circle><circle cx="7.97" cy="10.09" r="1.01" fill="#9ba0a5"></circle><path d="M24 11.07a1 1 0 01-1-1V7.55a1 1 0 012 0v2.52a1 1 0 01-1 1z" fill="#606368"></path><circle cx="24.03" cy="16.01" r="1.01" fill="#606368"></circle><circle cx="24.03" cy="13.02" r="1.01" fill="#606368"></circle><circle cx="24.03" cy="4.63" r="1.01" fill="#606368"></circle><path d="M16 20a1 1 0 01-1-1v-2.54a1 1 0 012 0V19a1 1 0 01-1 1z" fill="#80868b"></path><circle cx="16" cy="21.93" r="1.01" fill="#80868b"></circle><circle cx="16" cy="13.51" r="1.01" fill="#80868b"></circle><circle cx="16" cy="10.56" r="1.01" fill="#80868b"></circle><path d="M20 14.05a1 1 0 01-1-1v-2.51a1 1 0 112 0v2.51a1 1 0 01-1 1z" fill="#606368"></path><circle cx="20.02" cy="7.58" r="1.01" fill="#606368"></circle><circle cx="20.02" cy="18.92" r="1.01" fill="#606368"></circle><circle cx="20.02" cy="15.97" r="1.01" fill="#606368"></circle><circle cx="11.98" cy="18.92" r="1.01" fill="#9ba0a5"></circle><circle cx="11.98" cy="10.56" r="1.01" fill="#9ba0a5"></circle><circle cx="11.98" cy="7.58" r="1.01" fill="#9ba0a5"></circle><path d="M12 17a1 1 0 01-1-1v-2.54a1 1 0 012 0V16a1 1 0 01-1 1z" fill="#9ba0a5"></path></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -11,6 +11,7 @@ import { ChatMessageType } from "../../types/chat";
import ChatInput from "./chatInput";
import _ from "lodash";
import { getHealth } from "../../controllers/API";
export default function ChatModal({
flow,
@ -204,25 +205,25 @@ export default function ChatModal({
handleOnClose(event);
};
newWs.onerror = (ev) => {
console.log(ev, "error");
if (flow.id === "") {
connectWS();
} else {
getHealth().then((res) => {
if (res.status === 200) {
connectWS();
}
}).catch((err) => {
setErrorData({
title: "There was an error on web connection, please: ",
// message when the backend failed
title: "The backend is not responding. Please try again later.",
// possible solution list
list: [
"Refresh the page",
"Use a new flow tab",
"Check if the backend is up",
"Check your internet connection.",
"Check if the backend is running."
],
});
}
})
};
ws.current = newWs;
} catch (error) {
if (flow.id === "") {
connectWS();
}
console.log(error);
}
}

View file

@ -118,7 +118,7 @@ const NodeToolbarComponent = (props) => {
{/*
<Menu as="div" className="relative inline-block text-left z-100">
<button className="hover:dark:hover:bg-[#242f47] text-foreground transition-all duration-500 ease-in-out dark:bg-gray-800 shadow-md relative -ml-px inline-flex items-center bg-white px-2 py-2 ring-1 ring-inset ring-gray-300 hover:bg-muted focus:z-10 rounded-r-md">
<button className="hover:dark:hover:bg-[#242f47] text-gray-700 transition-all duration-500 ease-in-out dark:bg-gray-800 dark:text-gray-300 shadow-md relative -ml-px inline-flex items-center bg-white px-2 py-2 ring-1 ring-inset ring-gray-300 hover:bg-muted focus:z-10 rounded-r-md">
<div>
<Menu.Button className="flex items-center">
<EllipsisVerticalIcon

View file

@ -47,6 +47,7 @@ import {
} from "lucide-react";
import { SupabaseIcon } from "./icons/supabase";
import { MongoDBIcon } from "./icons/MongoDB";
import { VertexAIIcon } from "./icons/VertexAI";
export function classNames(...classes: Array<string>) {
return classes.filter(Boolean).join(" ");
@ -241,6 +242,12 @@ export const nodeIconsLucide: {
SupabaseVectorStore: SupabaseIcon as React.ForwardRefExoticComponent<
ComponentType<SVGProps<SVGSVGElement>>
>,
VertexAI: VertexAIIcon as React.ForwardRefExoticComponent<
ComponentType<SVGProps<SVGSVGElement>>
>,
ChatVertexAI: VertexAIIcon as React.ForwardRefExoticComponent<
ComponentType<SVGProps<SVGSVGElement>>
>,
agents: Rocket as React.ForwardRefExoticComponent<
ComponentType<SVGProps<SVGSVGElement>>
>,