From e67e55d94e66909a30f7748aaa77f97728609658 Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Thu, 22 Jun 2023 15:12:38 -0300 Subject: [PATCH 1/8] feat(API): add UpdateTemplate function to update templates via API call --- src/frontend/src/controllers/API/index.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/frontend/src/controllers/API/index.ts b/src/frontend/src/controllers/API/index.ts index 40b132261..f19dbd5d8 100644 --- a/src/frontend/src/controllers/API/index.ts +++ b/src/frontend/src/controllers/API/index.ts @@ -3,6 +3,8 @@ import { PromptTypeAPI, errorsTypeAPI, InitTypeAPI, + TemplateVariableType, + APITemplateType, } from "./../../types/api/index"; import { APIObjectType, sendAllProps } from "../../types/api/index"; import axios, { AxiosResponse } from "axios"; @@ -319,3 +321,7 @@ export async function postBuildInit( ): Promise> { return await axios.post(`/api/v1/build/init`, flow); } + +export async function UpdateTemplate(type:string, template:APITemplateType):Promise>{ + return await axios.post(`/api/v1/UpdateTemplate`); +} \ No newline at end of file From ec517fd9b64307e96d1eee0d59902ad5a6846a01 Mon Sep 17 00:00:00 2001 From: gustavoschaedler Date: Thu, 22 Jun 2023 21:00:02 +0100 Subject: [PATCH 2/8] Endpoint dynamic_node template to test --- src/backend/langflow/main.py | 226 +++++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) diff --git a/src/backend/langflow/main.py b/src/backend/langflow/main.py index ad3217eb5..53749d9c8 100644 --- a/src/backend/langflow/main.py +++ b/src/backend/langflow/main.py @@ -4,6 +4,228 @@ from fastapi.middleware.cors import CORSMiddleware from langflow.api import router from langflow.database.base import create_db_and_tables +template_node = { + "template": { + "lc_kwargs": { + "required": "false", + "placeholder": "", + "show": "false", + "multiline": "false", + "password": "false", + "name": "lc_kwargs", + "advanced": "true", + "type": "code", + "list": "false" + }, + "verbose": { + "required": "false", + "placeholder": "", + "show": "false", + "multiline": "false", + "value": "false", + "password": "false", + "name": "verbose", + "advanced": "false", + "type": "bool", + "list": "false" + }, + "callbacks": { + "required": "false", + "placeholder": "", + "show": "false", + "multiline": "false", + "password": "false", + "name": "callbacks", + "advanced": "false", + "type": "langchain.callbacks.base.BaseCallbackHandler", + "list": "true" + }, + "tags": { + "required": "false", + "placeholder": "", + "show": "false", + "multiline": "false", + "password": "false", + "name": "tags", + "advanced": "false", + "type": "str", + "list": "true" + }, + "client": { + "required": "false", + "placeholder": "", + "show": "false", + "multiline": "false", + "password": "false", + "name": "client", + "advanced": "false", + "type": "Any", + "list": "false" + }, + "model_name": { + "required": "false", + "placeholder": "", + "show": "true", + "multiline": "false", + "value": "gpt-3.5-turbo", + "password": "false", + "options": [ + "gpt-3.5-turbo-0613", + "gpt-3.5-turbo", + "gpt-3.5-turbo-16k-0613", + "gpt-3.5-turbo-16k", + "gpt-4-0613", + "gpt-4-32k-0613", + "gpt-4", + "gpt-4-32k" + ], + "name": "model_name", + "advanced": "false", + "type": "str", + "list": "true" + }, + "temperature": { + "required": "false", + "placeholder": "", + "show": "true", + "multiline": "false", + "value": 0.7, + "password": "false", + "name": "temperature", + "advanced": "false", + "type": "float", + "list": "false" + }, + "model_kwargs": { + "required": "false", + "placeholder": "", + "show": "true", + "multiline": "false", + "password": "false", + "name": "model_kwargs", + "advanced": "true", + "type": "code", + "list": "false" + }, + "openai_api_key": { + "required": "false", + "placeholder": "", + "show": "true", + "multiline": "false", + "value": "", + "password": "true", + "name": "openai_api_key", + "display_name": "OpenAI API Key", + "advanced": "false", + "type": "str", + "list": "false" + }, + "openai_api_base": { + "required": "false", + "placeholder": "", + "show": "true", + "multiline": "false", + "password": "false", + "name": "openai_api_base", + "display_name": "OpenAI API Base", + "advanced": "false", + "type": "str", + "list": "false" + }, + "openai_organization": { + "required": "false", + "placeholder": "", + "show": "false", + "multiline": "false", + "password": "false", + "name": "openai_organization", + "display_name": "OpenAI Organization", + "advanced": "false", + "type": "str", + "list": "false" + }, + "openai_proxy": { + "required": "false", + "placeholder": "", + "show": "false", + "multiline": "false", + "password": "false", + "name": "openai_proxy", + "display_name": "OpenAI Proxy", + "advanced": "false", + "type": "str", + "list": "false" + }, + "request_timeout": { + "required": "false", + "placeholder": "", + "show": "false", + "multiline": "false", + "password": "false", + "name": "request_timeout", + "advanced": "false", + "type": "float", + "list": "false" + }, + "max_retries": { + "required": "false", + "placeholder": "", + "show": "false", + "multiline": "false", + "value": 6, + "password": "false", + "name": "max_retries", + "advanced": "false", + "type": "int", + "list": "false" + }, + "streaming": { + "required": "false", + "placeholder": "", + "show": "false", + "multiline": "false", + "value": "false", + "password": "false", + "name": "streaming", + "advanced": "false", + "type": "bool", + "list": "false" + }, + "n": { + "required": "false", + "placeholder": "", + "show": "false", + "multiline": "false", + "value": 1, + "password": "false", + "name": "n", + "advanced": "false", + "type": "int", + "list": "false" + }, + "max_tokens": { + "required": "false", + "placeholder": "", + "show": "true", + "multiline": "false", + "password": "true", + "name": "max_tokens", + "advanced": "false", + "type": "int", + "list": "false" + }, + "_type": "ChatOpenAI" + }, + "description": "Wrapper around OpenAI Chat large language models.", + "base_classes": [ + "BaseChatModel", + "Serializable", + "BaseLanguageModel", + "ChatOpenAI" + ], + "display_name": "ChatOpenAI" +} + def create_app(): """Create the FastAPI app and include the router.""" @@ -18,6 +240,10 @@ def create_app(): def get_health(): return {"status": "OK"} + @app.get("/dynamic_node") + def get_dynamic_nome(): + return template_node + app.add_middleware( CORSMiddleware, allow_origins=origins, From 2c256421f45e9c66067c0e727b89872b78ff68f9 Mon Sep 17 00:00:00 2001 From: gustavoschaedler Date: Thu, 22 Jun 2023 21:16:10 +0100 Subject: [PATCH 3/8] Remove description --- src/backend/langflow/main.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/backend/langflow/main.py b/src/backend/langflow/main.py index 53749d9c8..d93d0efab 100644 --- a/src/backend/langflow/main.py +++ b/src/backend/langflow/main.py @@ -215,15 +215,7 @@ template_node = { "list": "false" }, "_type": "ChatOpenAI" - }, - "description": "Wrapper around OpenAI Chat large language models.", - "base_classes": [ - "BaseChatModel", - "Serializable", - "BaseLanguageModel", - "ChatOpenAI" - ], - "display_name": "ChatOpenAI" + } } From a458b2d91c04b2c8e18ecd6f5e301446b6f9f3e5 Mon Sep 17 00:00:00 2001 From: gustavoschaedler Date: Thu, 22 Jun 2023 21:26:25 +0100 Subject: [PATCH 4/8] Change type str to bool --- src/backend/langflow/main.py | 208 +++++++++++++++++------------------ 1 file changed, 104 insertions(+), 104 deletions(-) diff --git a/src/backend/langflow/main.py b/src/backend/langflow/main.py index d93d0efab..713c921cd 100644 --- a/src/backend/langflow/main.py +++ b/src/backend/langflow/main.py @@ -7,68 +7,68 @@ from langflow.database.base import create_db_and_tables template_node = { "template": { "lc_kwargs": { - "required": "false", + "required": False, "placeholder": "", - "show": "false", - "multiline": "false", - "password": "false", + "show": False, + "multiline": False, + "password": False, "name": "lc_kwargs", - "advanced": "true", + "advanced": True, "type": "code", - "list": "false" + "list": False }, "verbose": { - "required": "false", + "required": False, "placeholder": "", - "show": "false", - "multiline": "false", - "value": "false", - "password": "false", + "show": False, + "multiline": False, + "value": False, + "password": False, "name": "verbose", - "advanced": "false", + "advanced": False, "type": "bool", - "list": "false" + "list": False }, "callbacks": { - "required": "false", + "required": False, "placeholder": "", - "show": "false", - "multiline": "false", - "password": "false", + "show": False, + "multiline": False, + "password": False, "name": "callbacks", - "advanced": "false", + "advanced": False, "type": "langchain.callbacks.base.BaseCallbackHandler", - "list": "true" + "list": True }, "tags": { - "required": "false", + "required": False, "placeholder": "", - "show": "false", - "multiline": "false", - "password": "false", + "show": False, + "multiline": False, + "password": False, "name": "tags", - "advanced": "false", + "advanced": False, "type": "str", - "list": "true" + "list": True }, "client": { - "required": "false", + "required": False, "placeholder": "", - "show": "false", - "multiline": "false", - "password": "false", + "show": False, + "multiline": False, + "password": False, "name": "client", - "advanced": "false", + "advanced": False, "type": "Any", - "list": "false" + "list": False }, "model_name": { - "required": "false", + "required": False, "placeholder": "", - "show": "true", - "multiline": "false", + "show": True, + "multiline": False, "value": "gpt-3.5-turbo", - "password": "false", + "password": False, "options": [ "gpt-3.5-turbo-0613", "gpt-3.5-turbo", @@ -80,139 +80,139 @@ template_node = { "gpt-4-32k" ], "name": "model_name", - "advanced": "false", + "advanced": False, "type": "str", - "list": "true" + "list": True }, "temperature": { - "required": "false", + "required": False, "placeholder": "", - "show": "true", - "multiline": "false", + "show": True, + "multiline": False, "value": 0.7, - "password": "false", + "password": False, "name": "temperature", - "advanced": "false", + "advanced": False, "type": "float", - "list": "false" + "list": False }, "model_kwargs": { - "required": "false", + "required": False, "placeholder": "", - "show": "true", - "multiline": "false", - "password": "false", + "show": True, + "multiline": False, + "password": False, "name": "model_kwargs", - "advanced": "true", + "advanced": True, "type": "code", - "list": "false" + "list": False }, "openai_api_key": { - "required": "false", + "required": False, "placeholder": "", - "show": "true", - "multiline": "false", + "show": True, + "multiline": False, "value": "", - "password": "true", + "password": True, "name": "openai_api_key", "display_name": "OpenAI API Key", - "advanced": "false", + "advanced": False, "type": "str", - "list": "false" + "list": False }, "openai_api_base": { - "required": "false", + "required": False, "placeholder": "", - "show": "true", - "multiline": "false", - "password": "false", + "show": True, + "multiline": False, + "password": False, "name": "openai_api_base", "display_name": "OpenAI API Base", - "advanced": "false", + "advanced": False, "type": "str", - "list": "false" + "list": False }, "openai_organization": { - "required": "false", + "required": False, "placeholder": "", - "show": "false", - "multiline": "false", - "password": "false", + "show": False, + "multiline": False, + "password": False, "name": "openai_organization", "display_name": "OpenAI Organization", - "advanced": "false", + "advanced": False, "type": "str", - "list": "false" + "list": False }, "openai_proxy": { - "required": "false", + "required": False, "placeholder": "", - "show": "false", - "multiline": "false", - "password": "false", + "show": False, + "multiline": False, + "password": False, "name": "openai_proxy", "display_name": "OpenAI Proxy", - "advanced": "false", + "advanced": False, "type": "str", - "list": "false" + "list": False }, "request_timeout": { - "required": "false", + "required": False, "placeholder": "", - "show": "false", - "multiline": "false", - "password": "false", + "show": False, + "multiline": False, + "password": False, "name": "request_timeout", - "advanced": "false", + "advanced": False, "type": "float", - "list": "false" + "list": False }, "max_retries": { - "required": "false", + "required": False, "placeholder": "", - "show": "false", - "multiline": "false", + "show": False, + "multiline": False, "value": 6, - "password": "false", + "password": False, "name": "max_retries", - "advanced": "false", + "advanced": False, "type": "int", - "list": "false" + "list": False }, "streaming": { - "required": "false", + "required": False, "placeholder": "", - "show": "false", - "multiline": "false", - "value": "false", - "password": "false", + "show": False, + "multiline": False, + "value": False, + "password": False, "name": "streaming", - "advanced": "false", + "advanced": False, "type": "bool", - "list": "false" + "list": False }, "n": { - "required": "false", + "required": False, "placeholder": "", - "show": "false", - "multiline": "false", + "show": False, + "multiline": False, "value": 1, - "password": "false", + "password": False, "name": "n", - "advanced": "false", + "advanced": False, "type": "int", - "list": "false" + "list": False }, "max_tokens": { - "required": "false", + "required": False, "placeholder": "", - "show": "true", - "multiline": "false", - "password": "true", + "show": True, + "multiline": False, + "password": True, "name": "max_tokens", - "advanced": "false", + "advanced": False, "type": "int", - "list": "false" + "list": False }, "_type": "ChatOpenAI" } From a47dc9ae92d44a4018fcae432b4e30d1f7963f7c Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Thu, 22 Jun 2023 17:30:04 -0300 Subject: [PATCH 5/8] feat(frontend): add support for updating node template on code change in CodeAreaModal fix(API): fix UpdateTemplate function return type to match the actual response fix(vite.config.ts): add dynamic_node route to apiRoutes array to proxy requests to backend --- .../components/parameterComponent/index.tsx | 2 + .../src/CustomNodes/GenericNode/index.tsx | 2 +- .../components/codeAreaComponent/index.tsx | 10 +- src/frontend/src/controllers/API/index.ts | 4 +- .../src/modals/codeAreaModal/index.tsx | 102 +++++++++++------- src/frontend/src/types/components/index.ts | 10 ++ src/frontend/vite.config.ts | 2 +- 7 files changed, 86 insertions(+), 46 deletions(-) diff --git a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx index 65f946ba2..c35fd869b 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx @@ -227,6 +227,8 @@ export default function ParameterComponent({ ) : left === true && type === "code" ? ( {data.node.template = template}} + template={data.node.template} disabled={disabled} value={data.node.template[name].value ?? ""} onChange={handleOnNewValue} diff --git a/src/frontend/src/CustomNodes/GenericNode/index.tsx b/src/frontend/src/CustomNodes/GenericNode/index.tsx index fb1ed5f59..e2ddc051f 100644 --- a/src/frontend/src/CustomNodes/GenericNode/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/index.tsx @@ -62,7 +62,7 @@ export default function GenericNode({ } useEffect(() => {}, [closePopUp, data.node.template]); - + console.log({data}) return ( <> diff --git a/src/frontend/src/components/codeAreaComponent/index.tsx b/src/frontend/src/components/codeAreaComponent/index.tsx index 399ab40b2..a4b7231c8 100644 --- a/src/frontend/src/components/codeAreaComponent/index.tsx +++ b/src/frontend/src/components/codeAreaComponent/index.tsx @@ -3,7 +3,7 @@ import { useContext, useEffect, useState } from "react"; import { PopUpContext } from "../../contexts/popUpContext"; import CodeAreaModal from "../../modals/codeAreaModal"; import TextAreaModal from "../../modals/textAreaModal"; -import { TextAreaComponentType } from "../../types/components"; +import { CodeAreaComponentType, TextAreaComponentType } from "../../types/components"; import { INPUT_STYLE } from "../../constants"; export default function CodeAreaComponent({ @@ -11,7 +11,9 @@ export default function CodeAreaComponent({ onChange, disabled, editNode = false, -}: TextAreaComponentType) { + template, + setTemplate, +}: CodeAreaComponentType) { const [myValue, setMyValue] = useState(value); const { openPopUp } = useContext(PopUpContext); useEffect(() => { @@ -37,6 +39,8 @@ export default function CodeAreaComponent({ openPopUp( { setMyValue(t); onChange(t); @@ -59,7 +63,9 @@ export default function CodeAreaComponent({ onClick={() => { openPopUp( { setMyValue(t); onChange(t); diff --git a/src/frontend/src/controllers/API/index.ts b/src/frontend/src/controllers/API/index.ts index f19dbd5d8..60820bb7e 100644 --- a/src/frontend/src/controllers/API/index.ts +++ b/src/frontend/src/controllers/API/index.ts @@ -322,6 +322,6 @@ export async function postBuildInit( return await axios.post(`/api/v1/build/init`, flow); } -export async function UpdateTemplate(type:string, template:APITemplateType):Promise>{ - return await axios.post(`/api/v1/UpdateTemplate`); +export async function UpdateTemplate(type:string, template:APITemplateType):Promise>{ + return await axios.get(`/dynamic_node`); } \ No newline at end of file diff --git a/src/frontend/src/modals/codeAreaModal/index.tsx b/src/frontend/src/modals/codeAreaModal/index.tsx index 9f8815f4b..451946b0e 100644 --- a/src/frontend/src/modals/codeAreaModal/index.tsx +++ b/src/frontend/src/modals/codeAreaModal/index.tsx @@ -8,7 +8,7 @@ import "ace-builds/src-noconflict/theme-twilight"; import "ace-builds/src-noconflict/ext-language_tools"; // import "ace-builds/webpack-resolver"; import { darkContext } from "../../contexts/darkContext"; -import { postValidateCode } from "../../controllers/API"; +import { UpdateTemplate, postValidateCode } from "../../controllers/API"; import { alertContext } from "../../contexts/alertContext"; import { TabsContext } from "../../contexts/tabsContext"; import { @@ -22,16 +22,23 @@ import { } from "../../components/ui/dialog"; import { Button } from "../../components/ui/button"; import { CODE_PROMPT_DIALOG_SUBTITLE } from "../../constants"; +import Loading from "../../components/ui/loading"; +import { APITemplateType } from "../../types/api"; export default function CodeAreaModal({ value, setValue, + template, + setTemplate }: { setValue: (value: string) => void; value: string; + template: APITemplateType, + setTemplate: (template: APITemplateType) => void; }) { const [open, setOpen] = useState(true); const [code, setCode] = useState(value); + const [loading, setLoading] = useState(false); const { dark } = useContext(darkContext); const { setErrorData, setSuccessData } = useContext(alertContext); const { closePopUp } = useContext(PopUpContext); @@ -44,6 +51,58 @@ export default function CodeAreaModal({ }, 300); } } + + function handleClick() { + setLoading(true); + postValidateCode(code) + .then((apiReturn) => { + setLoading(false); + if (apiReturn.data) { + let importsErrors = apiReturn.data.imports.errors; + let funcErrors = apiReturn.data.function.errors; + if (funcErrors.length === 0 && importsErrors.length === 0) { + setSuccessData({ + title: "Code is ready to run", + }); + // setValue(code); + } else { + if (funcErrors.length !== 0) { + setErrorData({ + title: "There is an error in your function", + list: funcErrors, + }); + } + if (importsErrors.length !== 0) { + setErrorData({ + title: "There is an error in your imports", + list: importsErrors, + }); + } + } + } else { + setErrorData({ + title: "Something went wrong, please try again", + }); + } + }) + .catch((_) => { + setLoading(false); + setErrorData({ + title: + "There is something wrong with this code, please review it", + }) + } + ); + UpdateTemplate('code',template).then((apiReturn) => { + const data = apiReturn.data; + if (data.template) { + console.log('updated') + setTemplate(data.template); + setModalOpen(false); + } + }) + } + return ( @@ -80,47 +139,10 @@ export default function CodeAreaModal({ diff --git a/src/frontend/src/types/components/index.ts b/src/frontend/src/types/components/index.ts index 11f8aec07..5b31d63f1 100644 --- a/src/frontend/src/types/components/index.ts +++ b/src/frontend/src/types/components/index.ts @@ -1,6 +1,7 @@ import { ForwardRefExoticComponent, ReactElement, ReactNode } from "react"; import { NodeDataType } from "../flow/index"; import { typesContextType } from "../typesContext"; +import { APITemplateType } from "../api"; export type InputComponentType = { value: string; disabled?: boolean; @@ -50,6 +51,15 @@ export type TextAreaComponentType = { editNode?: boolean; }; +export type CodeAreaComponentType = { + disabled: boolean; + onChange: (value: string[] | string) => void; + value: string; + editNode?: boolean; + template: APITemplateType; + setTemplate: (value: APITemplateType) => void; +}; + export type FileComponentType = { disabled: boolean; onChange: (value: string[] | string) => void; diff --git a/src/frontend/vite.config.ts b/src/frontend/vite.config.ts index 860c690ea..176c73aea 100644 --- a/src/frontend/vite.config.ts +++ b/src/frontend/vite.config.ts @@ -1,7 +1,7 @@ import { defineConfig } from "vite"; import react from "@vitejs/plugin-react-swc"; import svgr from "vite-plugin-svgr"; -const apiRoutes = ["^/api/v1/", "/health"]; +const apiRoutes = ["^/api/v1/", "/health","/dynamic_node"]; // Use environment variable to determine the target. const target = process.env.VITE_PROXY_TARGET || "http://127.0.0.1:7860"; From 6736288e6f5542552df58d1953a0afb0bc2a2e5b Mon Sep 17 00:00:00 2001 From: gustavoschaedler Date: Thu, 22 Jun 2023 21:37:01 +0100 Subject: [PATCH 6/8] Add code section --- src/backend/langflow/main.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/backend/langflow/main.py b/src/backend/langflow/main.py index 713c921cd..caa70a79b 100644 --- a/src/backend/langflow/main.py +++ b/src/backend/langflow/main.py @@ -6,6 +6,18 @@ from langflow.database.base import create_db_and_tables template_node = { "template": { + "code": { + "required": True, + "placeholder": "", + "show": True, + "multiline": True, + "value": "\ndef my_user_python_function(text: str) -> str:\n \"\"\"This is a default python function that returns the input text\"\"\"\n return text.upper()\n", + "password": False, + "name": "code", + "advanced": False, + "type": "code", + "list": False + }, "lc_kwargs": { "required": False, "placeholder": "", From 531b3b3f7abdcebaca181384b8794395ef602861 Mon Sep 17 00:00:00 2001 From: gustavoschaedler Date: Thu, 22 Jun 2023 21:49:22 +0100 Subject: [PATCH 7/8] Base classes data added --- src/backend/langflow/main.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/backend/langflow/main.py b/src/backend/langflow/main.py index caa70a79b..801abbe3a 100644 --- a/src/backend/langflow/main.py +++ b/src/backend/langflow/main.py @@ -226,6 +226,13 @@ template_node = { "type": "int", "list": False }, + "base_classes": [ + "BaseChatModel", + "Serializable", + "BaseLanguageModel", + "ChatOpenAI" + ], + "description": "Wrapper around OpenAI Chat large language models.", "_type": "ChatOpenAI" } } From 37e1ea05b428f82d7c8dcb760d39f43cab8b0b9e Mon Sep 17 00:00:00 2001 From: gustavoschaedler Date: Thu, 22 Jun 2023 22:15:59 +0100 Subject: [PATCH 8/8] Base classes data moved --- src/backend/langflow/main.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/backend/langflow/main.py b/src/backend/langflow/main.py index 801abbe3a..7f5644d69 100644 --- a/src/backend/langflow/main.py +++ b/src/backend/langflow/main.py @@ -226,15 +226,15 @@ template_node = { "type": "int", "list": False }, - "base_classes": [ - "BaseChatModel", - "Serializable", - "BaseLanguageModel", - "ChatOpenAI" - ], - "description": "Wrapper around OpenAI Chat large language models.", "_type": "ChatOpenAI" - } + }, + "base_classes": [ + "BaseChatModel", + "Serializable", + "BaseLanguageModel", + "ChatOpenAI" + ], + "description": "Wrapper around OpenAI Chat large language models." }