From 2bc7d3afd8cf039aeb0effb9c838ad268a5316aa Mon Sep 17 00:00:00 2001 From: Gabriel Almeida Date: Sat, 13 May 2023 21:49:06 -0300 Subject: [PATCH 1/4] temporary fix for intermediate steps --- src/backend/langflow/interface/run.py | 77 ++++++++++++--------------- 1 file changed, 34 insertions(+), 43 deletions(-) diff --git a/src/backend/langflow/interface/run.py b/src/backend/langflow/interface/run.py index af80b7acd..a20587b54 100644 --- a/src/backend/langflow/interface/run.py +++ b/src/backend/langflow/interface/run.py @@ -1,6 +1,6 @@ import contextlib import io -from typing import Any, Dict +from typing import Any, Dict, List, Tuple from chromadb.errors import NotEnoughElementsException # type: ignore @@ -8,6 +8,7 @@ from langflow.api.callback import AsyncStreamingLLMCallbackHandler, StreamingLLM from langflow.cache.base import compute_dict_hash, load_cache, memoize_dict from langflow.graph.graph import Graph from langflow.utils.logger import logger +from langchain.schema import AgentAction def load_langchain_object(data_graph, is_first_message=False): @@ -175,33 +176,25 @@ async def get_result_and_steps(langchain_object, message: str, **kwargs): langchain_object.return_intermediate_steps = True fix_memory_inputs(langchain_object) + try: + async_callbacks = [AsyncStreamingLLMCallbackHandler(**kwargs)] + output = await langchain_object.acall(chat_input, callbacks=async_callbacks) + except Exception as exc: + # make the error message more informative + logger.debug(f"Error: {str(exc)}") + sync_callbacks = [StreamingLLMCallbackHandler(**kwargs)] + output = langchain_object(chat_input, callbacks=sync_callbacks) - with io.StringIO() as output_buffer, contextlib.redirect_stdout(output_buffer): - try: - async_callbacks = [AsyncStreamingLLMCallbackHandler(**kwargs)] - output = await langchain_object.acall( - chat_input, callbacks=async_callbacks - ) - except Exception as exc: - # make the error message more informative - logger.debug(f"Error: {str(exc)}") - sync_callbacks = [StreamingLLMCallbackHandler(**kwargs)] - output = langchain_object(chat_input, callbacks=sync_callbacks) - - intermediate_steps = ( - output.get("intermediate_steps", []) if isinstance(output, dict) else [] - ) - - result = ( - output.get(langchain_object.output_keys[0]) - if isinstance(output, dict) - else output - ) - if intermediate_steps: - thought = format_intermediate_steps(intermediate_steps) - else: - thought = output_buffer.getvalue() + intermediate_steps = ( + output.get("intermediate_steps", []) if isinstance(output, dict) else [] + ) + result = ( + output.get(langchain_object.output_keys[0]) + if isinstance(output, dict) + else output + ) + thought = format_actions(intermediate_steps) if intermediate_steps else "" except NotEnoughElementsException as exc: raise ValueError( "Error: Not enough documents for ChromaDB to index. Try reducing chunk size in TextSplitter." @@ -257,7 +250,7 @@ def get_result_and_thought(langchain_object, message: str): else output ) if intermediate_steps: - thought = format_intermediate_steps(intermediate_steps) + thought = format_actions(intermediate_steps) else: thought = output_buffer.getvalue() @@ -266,19 +259,17 @@ def get_result_and_thought(langchain_object, message: str): return result, thought -def format_intermediate_steps(intermediate_steps): - formatted_chain = "> Entering new AgentExecutor chain...\n" - for step in intermediate_steps: - action = step[0] - observation = step[1] - - formatted_chain += ( - f" {action.log}\nAction: {action.tool}\nAction Input: {action.tool_input}\n" - ) - formatted_chain += f"Observation: {observation}\n" - - final_answer = f"Final Answer: {observation}\n" - formatted_chain += f"Thought: I now know the final answer\n{final_answer}\n" - formatted_chain += "> Finished chain.\n" - - return formatted_chain +def format_actions(actions: List[Tuple[AgentAction, str]]) -> str: + """Format a list of (AgentAction, answer) tuples into a string.""" + output = [] + for action, answer in actions: + log = action.log + tool = action.tool + tool_input = action.tool_input + output.append(f"Log: {log}") + if "Action" not in log and "Action Input" not in log: + output.append(f"Tool: {tool}") + output.append(f"Tool Input: {tool_input}") + output.append(f"Answer: {answer}") + output.append("") # Add a blank line + return "\n".join(output) From d39f08f75f44ab9c0890535427e601195814a255 Mon Sep 17 00:00:00 2001 From: Gabriel Almeida Date: Sat, 13 May 2023 21:50:03 -0300 Subject: [PATCH 2/4] chore(pyproject.toml): update package version from 0.0.69 to 0.0.70 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 1e819234a..2a42a94fd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langflow" -version = "0.0.69" +version = "0.0.70" description = "A Python package with a built-in web application" authors = ["Logspace "] maintainers = [ From 9627005f8d2f43c9a8146b386265f6c561bcfe50 Mon Sep 17 00:00:00 2001 From: Gabriel Almeida Date: Sun, 14 May 2023 20:21:42 -0300 Subject: [PATCH 3/4] refactor(loading.py): change instantiate_prompt function signature to include class_object parameter and use it to instantiate the prompt object --- src/backend/langflow/interface/loading.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/backend/langflow/interface/loading.py b/src/backend/langflow/interface/loading.py index 0e23c2b45..148efd5b7 100644 --- a/src/backend/langflow/interface/loading.py +++ b/src/backend/langflow/interface/loading.py @@ -54,7 +54,7 @@ def instantiate_based_on_type(class_object, base_type, node_type, params): if base_type == "agents": return instantiate_agent(class_object, params) elif base_type == "prompts": - return instantiate_prompt(node_type, params) + return instantiate_prompt(class_object, node_type, params) elif base_type == "tools": return instantiate_tool(node_type, class_object, params) elif base_type == "toolkits": @@ -77,12 +77,12 @@ def instantiate_agent(class_object, params): return load_agent_executor(class_object, params) -def instantiate_prompt(node_type, params): +def instantiate_prompt(class_object, node_type, params): if node_type == "ZeroShotPrompt": if "tools" not in params: params["tools"] = [] return ZeroShotAgent.create_prompt(**params) - return None # Or some other default action + return class_object(**params) def instantiate_tool(node_type, class_object, params): From 22b00a98dbf7400f8e1590aff4bbdce514fc2ec3 Mon Sep 17 00:00:00 2001 From: Gabriel Almeida Date: Sun, 14 May 2023 20:22:38 -0300 Subject: [PATCH 4/4] chore(pyproject.toml): update package version from 0.0.70 to 0.0.71 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 2a42a94fd..0cc181617 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langflow" -version = "0.0.70" +version = "0.0.71" description = "A Python package with a built-in web application" authors = ["Logspace "] maintainers = [