diff --git a/src/backend/langflow/config.yaml b/src/backend/langflow/config.yaml index a1a1ed826..a5e952fc3 100644 --- a/src/backend/langflow/config.yaml +++ b/src/backend/langflow/config.yaml @@ -3,7 +3,7 @@ agents: - ZeroShotAgent - JsonAgent - CSVAgent - - initialize_agent + - AgentInitializer - VectorStoreAgent - VectorStoreRouterAgent - SQLAgent diff --git a/src/backend/langflow/custom/customs.py b/src/backend/langflow/custom/customs.py index e315d27fd..fb6c1da16 100644 --- a/src/backend/langflow/custom/customs.py +++ b/src/backend/langflow/custom/customs.py @@ -13,7 +13,7 @@ CUSTOM_NODES = { "agents": { "JsonAgent": frontend_node.agents.JsonAgentNode(), "CSVAgent": frontend_node.agents.CSVAgentNode(), - "initialize_agent": frontend_node.agents.InitializeAgentNode(), + "AgentInitializer": frontend_node.agents.InitializeAgentNode(), "VectorStoreAgent": frontend_node.agents.VectorStoreAgentNode(), "VectorStoreRouterAgent": frontend_node.agents.VectorStoreRouterAgentNode(), "SQLAgent": frontend_node.agents.SQLAgentNode(), diff --git a/src/backend/langflow/interface/agents/custom.py b/src/backend/langflow/interface/agents/custom.py index d544cfb47..b0c794c2d 100644 --- a/src/backend/langflow/interface/agents/custom.py +++ b/src/backend/langflow/interface/agents/custom.py @@ -64,7 +64,9 @@ class JsonAgent(CustomAgentExecutor): llm=llm, prompt=prompt, ) - agent = ZeroShotAgent(llm_chain=llm_chain, allowed_tools=tool_names) # type: ignore + agent = ZeroShotAgent( + llm_chain=llm_chain, allowed_tools=tool_names # type: ignore + ) return cls.from_agent_and_tools(agent=agent, tools=tools, verbose=True) def run(self, *args, **kwargs): @@ -111,7 +113,9 @@ class CSVAgent(CustomAgentExecutor): prompt=partial_prompt, ) tool_names = {tool.name for tool in tools} - agent = ZeroShotAgent(llm_chain=llm_chain, allowed_tools=tool_names, **kwargs) # type: ignore + agent = ZeroShotAgent( + llm_chain=llm_chain, allowed_tools=tool_names, **kwargs # type: ignore + ) return cls.from_agent_and_tools(agent=agent, tools=tools, verbose=True) @@ -148,7 +152,9 @@ class VectorStoreAgent(CustomAgentExecutor): prompt=prompt, ) tool_names = {tool.name for tool in tools} - agent = ZeroShotAgent(llm_chain=llm_chain, allowed_tools=tool_names, **kwargs) # type: ignore + agent = ZeroShotAgent( + llm_chain=llm_chain, allowed_tools=tool_names, **kwargs # type: ignore + ) return AgentExecutor.from_agent_and_tools( agent=agent, tools=tools, verbose=True ) @@ -216,7 +222,9 @@ class SQLAgent(CustomAgentExecutor): prompt=prompt, ) tool_names = {tool.name for tool in tools} # type: ignore - agent = ZeroShotAgent(llm_chain=llm_chain, allowed_tools=tool_names, **kwargs) # type: ignore + agent = ZeroShotAgent( + llm_chain=llm_chain, allowed_tools=tool_names, **kwargs # type: ignore + ) return AgentExecutor.from_agent_and_tools( agent=agent, tools=tools, # type: ignore @@ -263,7 +271,9 @@ class VectorStoreRouterAgent(CustomAgentExecutor): prompt=prompt, ) tool_names = {tool.name for tool in tools} - agent = ZeroShotAgent(llm_chain=llm_chain, allowed_tools=tool_names, **kwargs) # type: ignore + agent = ZeroShotAgent( + llm_chain=llm_chain, allowed_tools=tool_names, **kwargs # type: ignore + ) return AgentExecutor.from_agent_and_tools( agent=agent, tools=tools, verbose=True ) @@ -273,11 +283,11 @@ class VectorStoreRouterAgent(CustomAgentExecutor): class InitializeAgent(CustomAgentExecutor): - """Implementation of initialize_agent function""" + """Implementation of AgentInitializer function""" @staticmethod def function_name(): - return "initialize_agent" + return "AgentInitializer" @classmethod def initialize( diff --git a/src/backend/langflow/interface/chains/custom.py b/src/backend/langflow/interface/chains/custom.py index 411042b0f..01dd9bab0 100644 --- a/src/backend/langflow/interface/chains/custom.py +++ b/src/backend/langflow/interface/chains/custom.py @@ -97,7 +97,7 @@ class TimeTravelGuideChain(BaseCustomConversationChain): class CombineDocsChain(CustomChain): - """Implementation of initialize_agent function""" + """Implementation of load_qa_chain function""" @staticmethod def function_name(): diff --git a/src/backend/langflow/interface/custom_lists.py b/src/backend/langflow/interface/custom_lists.py index fbdba0a9c..2f7f69f14 100644 --- a/src/backend/langflow/interface/custom_lists.py +++ b/src/backend/langflow/interface/custom_lists.py @@ -17,14 +17,14 @@ from langflow.interface.importing.utils import import_class from langflow.interface.agents.custom import CUSTOM_AGENTS from langflow.interface.chains.custom import CUSTOM_CHAINS -## LLMs +# LLMs 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 -## Toolkits +# Toolkits toolkit_type_to_loader_dict: dict[str, Any] = { toolkit_name: import_class(f"langchain.agents.agent_toolkits.{toolkit_name}") # if toolkit_name is lower case it is a loader @@ -39,25 +39,25 @@ toolkit_type_to_cls_dict: dict[str, Any] = { if not toolkit_name.islower() } -## Memories +# Memories memory_type_to_cls_dict: dict[str, Any] = { memory_name: import_class(f"langchain.memory.{memory_name}") for memory_name in memory.__all__ } -## Wrappers +# Wrappers wrapper_type_to_cls_dict: dict[str, Any] = { wrapper.__name__: wrapper for wrapper in [requests.RequestsWrapper] } -## Embeddings +# Embeddings embedding_type_to_cls_dict: dict[str, Any] = { embedding_name: import_class(f"langchain.embeddings.{embedding_name}") for embedding_name in embeddings.__all__ } -## Document Loaders +# Document Loaders documentloaders_type_to_cls_dict: dict[str, Any] = { documentloader_name: import_class( f"langchain.document_loaders.{documentloader_name}" @@ -65,7 +65,7 @@ documentloaders_type_to_cls_dict: dict[str, Any] = { for documentloader_name in document_loaders.__all__ } -## Text Splitters +# Text Splitters textsplitter_type_to_cls_dict: dict[str, Any] = dict( inspect.getmembers(text_splitter, inspect.isclass) ) diff --git a/tests/data/basic_example.json b/tests/data/basic_example.json index 2555562f9..2c08512bb 100644 --- a/tests/data/basic_example.json +++ b/tests/data/basic_example.json @@ -1 +1,509 @@ -{"description":"","name":"BasicExample","id":"a53f9130-f2fa-4a3e-b22a-3856d946351a","data":{"nodes":[{"width":384,"height":267,"id":"dndnode_81","type":"genericNode","position":{"x":1030,"y":694},"data":{"type":"TimeTravelGuideChain","node":{"template":{"llm":{"required":true,"placeholder":"","show":true,"multiline":false,"password":false,"name":"llm","advanced":false,"type":"BaseLanguageModel","list":false},"memory":{"required":false,"placeholder":"","show":true,"multiline":false,"password":false,"name":"memory","advanced":false,"type":"BaseChatMemory","list":false},"_type":"TimeTravelGuideChain"},"description":"Time travel guide chain to be used in the flow.","base_classes":["LLMChain","BaseCustomChain","TimeTravelGuideChain","Chain","ConversationChain"]},"id":"dndnode_81","value":null},"selected":false,"positionAbsolute":{"x":1030,"y":694},"dragging":false},{"width":384,"height":597,"id":"dndnode_82","type":"genericNode","position":{"x":520,"y":732},"data":{"type":"OpenAI","node":{"template":{"cache":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"cache","advanced":false,"type":"bool","list":false},"verbose":{"required":false,"placeholder":"","show":false,"multiline":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},"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":"text-davinci-003","password":false,"options":["text-davinci-003","text-davinci-002","text-curie-001","text-babbage-001","text-ada-001"],"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},"max_tokens":{"required":false,"placeholder":"","show":true,"multiline":false,"value":256,"password":true,"name":"max_tokens","advanced":false,"type":"int","list":false},"top_p":{"required":false,"placeholder":"","show":false,"multiline":false,"value":1,"password":false,"name":"top_p","advanced":false,"type":"float","list":false},"frequency_penalty":{"required":false,"placeholder":"","show":false,"multiline":false,"value":0,"password":false,"name":"frequency_penalty","advanced":false,"type":"float","list":false},"presence_penalty":{"required":false,"placeholder":"","show":false,"multiline":false,"value":0,"password":false,"name":"presence_penalty","advanced":false,"type":"float","list":false},"n":{"required":false,"placeholder":"","show":false,"multiline":false,"value":1,"password":false,"name":"n","advanced":false,"type":"int","list":false},"best_of":{"required":false,"placeholder":"","show":false,"multiline":false,"value":1,"password":false,"name":"best_of","advanced":false,"type":"int","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":"abc","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":true,"name":"openai_api_base","advanced":false,"type":"str","list":false},"openai_organization":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"openai_organization","advanced":false,"type":"str","list":false},"batch_size":{"required":false,"placeholder":"","show":false,"multiline":false,"value":20,"password":false,"name":"batch_size","advanced":false,"type":"int","list":false},"request_timeout":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"request_timeout","advanced":false,"type":"float","list":false},"logit_bias":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"logit_bias","advanced":false,"type":"code","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},"allowed_special":{"required":false,"placeholder":"","show":false,"multiline":false,"value":[],"password":false,"name":"allowed_special","advanced":false,"type":"Literal'all'","list":true},"disallowed_special":{"required":false,"placeholder":"","show":false,"multiline":false,"value":"all","password":false,"name":"disallowed_special","advanced":false,"type":"Literal'all'","list":false},"_type":"OpenAI"},"description":"Wrapper around OpenAI large language models.","base_classes":["BaseLLM","OpenAI","BaseOpenAI","BaseLanguageModel"]},"id":"dndnode_82","value":null},"selected":false,"positionAbsolute":{"x":520,"y":732},"dragging":false},{"width":384,"height":273,"id":"dndnode_83","type":"genericNode","position":{"x":512,"y":402},"data":{"type":"ConversationBufferMemory","node":{"template":{"chat_memory":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"chat_memory","advanced":false,"type":"BaseChatMessageHistory","list":false},"output_key":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"output_key","advanced":false,"type":"str","list":false},"input_key":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"input_key","advanced":false,"type":"str","list":false},"return_messages":{"required":false,"placeholder":"","show":false,"multiline":false,"password":false,"name":"return_messages","advanced":false,"type":"bool","list":false},"human_prefix":{"required":false,"placeholder":"","show":false,"multiline":false,"value":"Human","password":false,"name":"human_prefix","advanced":false,"type":"str","list":false},"ai_prefix":{"required":false,"placeholder":"","show":false,"multiline":false,"value":"AI","password":false,"name":"ai_prefix","advanced":false,"type":"str","list":false},"memory_key":{"required":false,"placeholder":"","show":true,"multiline":false,"value":"history","password":false,"name":"memory_key","advanced":false,"type":"str","list":false},"_type":"ConversationBufferMemory"},"description":"Buffer for storing conversation memory.","base_classes":["ConversationBufferMemory","BaseChatMemory","BaseMemory"]},"id":"dndnode_83","value":null},"selected":false,"positionAbsolute":{"x":512,"y":402},"dragging":false}],"edges":[{"source":"dndnode_82","sourceHandle":"OpenAI|dndnode_82|BaseLLM|OpenAI|BaseOpenAI|BaseLanguageModel","target":"dndnode_81","targetHandle":"BaseLanguageModel|llm|dndnode_81","className":"animate-pulse","id":"reactflow__edge-dndnode_82OpenAI|dndnode_82|BaseLLM|OpenAI|BaseOpenAI|BaseLanguageModel-dndnode_81BaseLanguageModel|llm|dndnode_81","selected":false},{"source":"dndnode_83","sourceHandle":"ConversationBufferMemory|dndnode_83|ConversationBufferMemory|BaseChatMemory|BaseMemory","target":"dndnode_81","targetHandle":"BaseChatMemory|memory|dndnode_81","className":"animate-pulse","id":"reactflow__edge-dndnode_83ConversationBufferMemory|dndnode_83|ConversationBufferMemory|BaseChatMemory|BaseMemory-dndnode_81BaseChatMemory|memory|dndnode_81"}],"viewport":{"x":1,"y":0,"zoom":0.5}}} \ No newline at end of file +{ + "description": "", + "name": "BasicExample", + "id": "a53f9130-f2fa-4a3e-b22a-3856d946351a", + "data": { + "nodes": [ + { + "width": 384, + "height": 267, + "id": "dndnode_81", + "type": "genericNode", + "position": { + "x": 1030, + "y": 694 + }, + "data": { + "type": "TimeTravelGuideChain", + "node": { + "template": { + "llm": { + "required": true, + "placeholder": "", + "show": true, + "multiline": false, + "password": false, + "name": "llm", + "advanced": false, + "type": "BaseLanguageModel", + "list": false + }, + "memory": { + "required": false, + "placeholder": "", + "show": true, + "multiline": false, + "password": false, + "name": "memory", + "advanced": false, + "type": "BaseChatMemory", + "list": false + }, + "_type": "TimeTravelGuideChain" + }, + "description": "Time travel guide chain to be used in the flow.", + "base_classes": [ + "LLMChain", + "BaseCustomChain", + "TimeTravelGuideChain", + "Chain", + "ConversationChain" + ] + }, + "id": "dndnode_81", + "value": null + }, + "selected": false, + "positionAbsolute": { + "x": 1030, + "y": 694 + }, + "dragging": false + }, + { + "width": 384, + "height": 597, + "id": "dndnode_82", + "type": "genericNode", + "position": { + "x": 520, + "y": 732 + }, + "data": { + "type": "OpenAI", + "node": { + "template": { + "cache": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "cache", + "advanced": false, + "type": "bool", + "list": false + }, + "verbose": { + "required": false, + "placeholder": "", + "show": false, + "multiline": 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 + }, + "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": "text-davinci-003", + "password": false, + "options": [ + "text-davinci-003", + "text-davinci-002", + "text-curie-001", + "text-babbage-001", + "text-ada-001" + ], + "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 + }, + "max_tokens": { + "required": false, + "placeholder": "", + "show": true, + "multiline": false, + "value": 256, + "password": true, + "name": "max_tokens", + "advanced": false, + "type": "int", + "list": false + }, + "top_p": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "value": 1, + "password": false, + "name": "top_p", + "advanced": false, + "type": "float", + "list": false + }, + "frequency_penalty": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "value": 0, + "password": false, + "name": "frequency_penalty", + "advanced": false, + "type": "float", + "list": false + }, + "presence_penalty": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "value": 0, + "password": false, + "name": "presence_penalty", + "advanced": false, + "type": "float", + "list": false + }, + "n": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "value": 1, + "password": false, + "name": "n", + "advanced": false, + "type": "int", + "list": false + }, + "best_of": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "value": 1, + "password": false, + "name": "best_of", + "advanced": false, + "type": "int", + "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": "abc", + "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": true, + "name": "openai_api_base", + "advanced": false, + "type": "str", + "list": false + }, + "openai_organization": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "openai_organization", + "advanced": false, + "type": "str", + "list": false + }, + "batch_size": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "value": 20, + "password": false, + "name": "batch_size", + "advanced": false, + "type": "int", + "list": false + }, + "request_timeout": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "request_timeout", + "advanced": false, + "type": "float", + "list": false + }, + "logit_bias": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "logit_bias", + "advanced": false, + "type": "code", + "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 + }, + "allowed_special": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "value": [], + "password": false, + "name": "allowed_special", + "advanced": false, + "type": "Literal'all'", + "list": true + }, + "disallowed_special": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "value": "all", + "password": false, + "name": "disallowed_special", + "advanced": false, + "type": "Literal'all'", + "list": false + }, + "_type": "OpenAI" + }, + "description": "Wrapper around OpenAI large language models.", + "base_classes": [ + "BaseLLM", + "OpenAI", + "BaseOpenAI", + "BaseLanguageModel" + ] + }, + "id": "dndnode_82", + "value": null + }, + "selected": false, + "positionAbsolute": { + "x": 520, + "y": 732 + }, + "dragging": false + }, + { + "width": 384, + "height": 273, + "id": "dndnode_83", + "type": "genericNode", + "position": { + "x": 512, + "y": 402 + }, + "data": { + "type": "ConversationBufferMemory", + "node": { + "template": { + "chat_memory": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "chat_memory", + "advanced": false, + "type": "BaseChatMessageHistory", + "list": false + }, + "output_key": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "output_key", + "advanced": false, + "type": "str", + "list": false + }, + "input_key": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "input_key", + "advanced": false, + "type": "str", + "list": false + }, + "return_messages": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "password": false, + "name": "return_messages", + "advanced": false, + "type": "bool", + "list": false + }, + "human_prefix": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "value": "Human", + "password": false, + "name": "human_prefix", + "advanced": false, + "type": "str", + "list": false + }, + "ai_prefix": { + "required": false, + "placeholder": "", + "show": false, + "multiline": false, + "value": "AI", + "password": false, + "name": "ai_prefix", + "advanced": false, + "type": "str", + "list": false + }, + "memory_key": { + "required": false, + "placeholder": "", + "show": true, + "multiline": false, + "value": "history", + "password": false, + "name": "memory_key", + "advanced": false, + "type": "str", + "list": false + }, + "_type": "ConversationBufferMemory" + }, + "description": "Buffer for storing conversation memory.", + "base_classes": [ + "ConversationBufferMemory", + "BaseChatMemory", + "BaseMemory" + ] + }, + "id": "dndnode_83", + "value": null + }, + "selected": false, + "positionAbsolute": { + "x": 512, + "y": 402 + }, + "dragging": false + } + ], + "edges": [ + { + "source": "dndnode_82", + "sourceHandle": "OpenAI|dndnode_82|BaseLLM|OpenAI|BaseOpenAI|BaseLanguageModel", + "target": "dndnode_81", + "targetHandle": "BaseLanguageModel|llm|dndnode_81", + "className": "animate-pulse", + "id": "reactflow__edge-dndnode_82OpenAI|dndnode_82|BaseLLM|OpenAI|BaseOpenAI|BaseLanguageModel-dndnode_81BaseLanguageModel|llm|dndnode_81", + "selected": false + }, + { + "source": "dndnode_83", + "sourceHandle": "ConversationBufferMemory|dndnode_83|ConversationBufferMemory|BaseChatMemory|BaseMemory", + "target": "dndnode_81", + "targetHandle": "BaseChatMemory|memory|dndnode_81", + "className": "animate-pulse", + "id": "reactflow__edge-dndnode_83ConversationBufferMemory|dndnode_83|ConversationBufferMemory|BaseChatMemory|BaseMemory-dndnode_81BaseChatMemory|memory|dndnode_81" + } + ], + "viewport": { + "x": 1, + "y": 0, + "zoom": 0.5 + } + } +} \ No newline at end of file