Skip to content

Commit

Permalink
feat: Add SimpleAgentComponent and related pytests (#4318)
Browse files Browse the repository at this point in the history
* simple ai agent

new component:
simple ai agent

py tests for tool calling agent as well as for simple ai agent

* Update simple_agent.py

update _config Changes and code oprimised

* Update simple_agent.py

Error or inputType as None Solved

* [autofix.ci] apply automated fixes

* fix: INP001 ruff error

* Update test_tool_calling_agent.py

added pytest mark as api required

* Update simple_agent.py

added system prompt

* [autofix.ci] apply automated fixes

* updates in the input field orders

* [autofix.ci] apply automated fixes

* Update simple_agent.py

chat memory added

* [autofix.ci] apply automated fixes

* lint Errors Solved

* Squashed commit of the following:

commit e965fd3
Author: Sebastián Estévez <estevezsebastian@gmail.com>
Date:   Thu Oct 31 17:16:08 2024 -0400

    fix: broken docker test (#4337)

    * Fix broken docker test

    Fixes #4336

    Update the Docker test workflow to use the `get_version` function from `langflow.utils.version`.

    * Modify the `Test image` step in `.github/workflows/docker_test.yml` to use the `get_version` function instead of directly importing `__version__`.
    * Modify the `Test backend image` step in `.github/workflows/docker_test.yml` to use the `get_version` function instead of directly importing `__version__`.

    ---

    For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/langflow-ai/langflow/issues/4336?shareId=XXXX-XXXX-XXXX-XXXX).

    * version.version not util.version

commit 3279b8a
Author: Lucas Oliveira <62335616+lucaseduoli@users.noreply.github.com>
Date:   Thu Oct 31 16:39:58 2024 -0300

    fix: add collapsible function to templates and fix design bugs (#4305)

    * Updated colors

    * Fixed design for small screens

    * Change border radius

    * Changed size of text on templates description

    * Fix shine effect on small screens

    * Fixed icons on starter templates

    * Updated mono font to JetBrains

    * Updated icon hit area for X

    * Added gradient wrapper and x-gradient

    * Changed colors and font weights for nav component

    * Added zoom on hover of gradient

    * Fixed input size

    * Fixed all templates to show everything

    * Hide scrollbar

    * Change text size of card

    * Removed title of the categories

    * Removed unused currentTab from templatecategory

    * Updated position of search icon

    * Updated style of inputs

    * Updated search clear button

    * Fixed bug on small screens

    * Added no results query

    * Fixed background on get started cards

    * Added focus ring on nav component

    * Added tab index to search and sidebar buttons

    * Added keyboard navigation to templates

    * Updated templatesModal to use ShadCN Sidebar

    * Implemented collapsible sidebar

    * Fix collapsible to work on mobile but be overlaying content

    * Added noise to styleUtils

    * Updated padding and sizes for mobile

    * Updated text size

    * Updated font family to inter

    * Made get started components fetch title and description from the flow

    * Updated description on get started component

    * Updated naming of sidebar

    * Updated description of start from scratch

    * Updated color of selected sidebar item

    * Changed text color for sidebar not active items

    * changed description sizes

    * changed to line clamp

    * Reduced gap between icon and category text

    * Fixed no results state

    * Fixed X icon only appearing on hover

    * Fix auto focus issue

    * fixed hover color of primary button

    * Fixed gradients to use stops if it exists and stop using random gradient

    * removed random gradient

    * Fixed design of cards in templates

    * Updated nav to go through tests

    * Fixed focus on input

    * [autofix.ci] apply automated fixes

    * New color

    * fix testes

    * Fixed starter projects test

    * ✨ (starter-projects.spec.ts): add Page import to test function parameters for better code readability and maintainability
    📝 (starter-projects.spec.ts): refactor test to include a function for waiting for template visibility, improving code readability and reducing duplication

    ---------

    Co-authored-by: Cristhian Zanforlin Lousa <cristhian.lousa@gmail.com>
    Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

commit a03da10
Author: Sebastián Estévez <estevezsebastian@gmail.com>
Date:   Thu Oct 31 14:57:07 2024 -0400

    fix: langfuse upgrade and crew result usage (#4342)

    * lanfuse upgrade and crew result usage

    * ✅ (Dynamic Agent.spec.ts): Enable tests for checking the presence of required environment variables before running the test suite.

    ✨ (Hierarchical Agent.spec.ts): Add integration test for Hierarchical Tasks Agent to ensure proper functionality and behavior
    ✨ (Sequential Task Agent.spec.ts): Add integration test for Sequential Tasks Agent to ensure proper functionality and behavior

    ---------

    Co-authored-by: cristhianzl <cristhian.lousa@gmail.com>

* [autofix.ci] apply automated fixes

* Update worker.py

adding  # noqa: to solve CI Error

* [autofix.ci] apply automated fixes

* Update worker.py

removed unused params that were causing the issue

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: italojohnny <italojohnnydosanjos@gmail.com>
  • Loading branch information
3 people authored Nov 2, 2024
1 parent 0fed08a commit e2c26f1
Show file tree
Hide file tree
Showing 7 changed files with 786 additions and 654 deletions.
2 changes: 1 addition & 1 deletion src/backend/base/langflow/base/agents/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,10 @@ def create_agent_runnable(self) -> Runnable:

class LCToolsAgentComponent(LCAgentComponent):
_base_inputs = [
*LCAgentComponent._base_inputs,
HandleInput(
name="tools", display_name="Tools", input_types=["Tool", "BaseTool", "StructuredTool"], is_list=True
),
*LCAgentComponent._base_inputs,
]

def build_agent(self) -> AgentExecutor:
Expand Down
156 changes: 156 additions & 0 deletions src/backend/base/langflow/components/agents/agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
from langflow.base.agents.agent import LCToolsAgentComponent
from langflow.base.models.model import LCModelComponent
from langflow.components.agents.tool_calling import ToolCallingAgentComponent
from langflow.components.helpers.memory import MemoryComponent
from langflow.components.models.azure_openai import AzureChatOpenAIComponent
from langflow.components.models.openai import OpenAIModelComponent
from langflow.io import (
DropdownInput,
MultilineInput,
Output,
)
from langflow.schema.dotdict import dotdict
from langflow.schema.message import Message


def set_advanced_true(component_input):
component_input.advanced = True
return component_input


class AgentComponent(ToolCallingAgentComponent):
display_name: str = "Agent"
description: str = "Define the agent's instructions, then enter a task to complete using tools."
icon = "bot"
beta = True
name = "Agent"

azure_inputs = [
set_advanced_true(component_input) if component_input.name == "temperature" else component_input
for component_input in AzureChatOpenAIComponent().inputs
if component_input.name not in [input_field.name for input_field in LCModelComponent._base_inputs]
]
openai_inputs = [
set_advanced_true(component_input) if component_input.name == "temperature" else component_input
for component_input in OpenAIModelComponent().inputs
if component_input.name not in [input_field.name for input_field in LCModelComponent._base_inputs]
]

memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]

inputs = [
DropdownInput(
name="agent_llm",
display_name="Model Provider",
options=["Azure OpenAI", "OpenAI", "Custom"],
value="OpenAI",
real_time_refresh=True,
refresh_button=True,
input_types=[],
),
*openai_inputs,
MultilineInput(
name="system_prompt",
display_name="Agent Instructions",
info="Initial instructions and context provided to guide the agent's behavior.",
value="You are a helpful assistant that can use tools to answer questions and perform tasks.",
advanced=False,
),
*LCToolsAgentComponent._base_inputs,
*memory_inputs,
]
outputs = [Output(name="response", display_name="Response", method="get_response")]

async def get_response(self) -> Message:
llm_model = self.get_llm()
if llm_model is None:
msg = "No language model selected"
raise ValueError(msg)
self.chat_history = self.get_memory_data()

agent = ToolCallingAgentComponent().set(
llm=llm_model,
tools=[self.tools],
chat_history=self.chat_history,
input_value=self.input_value,
system_prompt=self.system_prompt,
)

return await agent.message_response()

def get_memory_data(self):
memory_kwargs = {
component_input.name: getattr(self, f"{component_input.name}") for component_input in self.memory_inputs
}

return MemoryComponent().set(**memory_kwargs).retrieve_messages()

def get_llm(self):
try:
if self.agent_llm == "OpenAI":
return self._build_llm_model(OpenAIModelComponent(), self.openai_inputs)
if self.agent_llm == "Azure OpenAI":
return self._build_llm_model(AzureChatOpenAIComponent(), self.azure_inputs, prefix="azure_param_")
except Exception as e:
msg = f"Error building {self.agent_llm} language model"
raise ValueError(msg) from e
return self.agent_llm

def _build_llm_model(self, component, inputs, prefix=""):
return component.set(
**{component_input.name: getattr(self, f"{prefix}{component_input.name}") for component_input in inputs}
).build_model()

def delete_fields(self, build_config, fields):
for field in fields:
build_config.pop(field, None)

def update_build_config(self, build_config: dotdict, field_value: str, field_name: str | None = None):
if field_name == "agent_llm":
openai_fields = {component_input.name: component_input for component_input in self.openai_inputs}
azure_fields = {
f"azure_param_{component_input.name}": component_input for component_input in self.azure_inputs
}

if field_value == "OpenAI":
self.delete_fields(build_config, {**azure_fields})
if not any(field in build_config for field in openai_fields):
build_config.update(openai_fields)
build_config["agent_llm"]["input_types"] = []
build_config = self.update_input_types(build_config)

elif field_value == "Azure OpenAI":
self.delete_fields(build_config, {**openai_fields})
build_config.update(azure_fields)
build_config["agent_llm"]["input_types"] = []
build_config = self.update_input_types(build_config)
elif field_value == "Custom":
self.delete_fields(build_config, {**openai_fields})
self.delete_fields(build_config, {**azure_fields})
new_component = DropdownInput(
name="agent_llm",
display_name="Language Model",
options=["Azure OpenAI", "OpenAI", "Custom"],
value="Custom",
real_time_refresh=True,
input_types=["LanguageModel"],
)
build_config.update({"agent_llm": new_component.to_dict()})
build_config = self.update_input_types(build_config)
default_keys = ["code", "_type", "agent_llm", "tools", "input_value"]
missing_keys = [key for key in default_keys if key not in build_config]
if missing_keys:
msg = f"Missing required keys in build_config: {missing_keys}"
raise ValueError(msg)
return build_config

def update_input_types(self, build_config):
for key, value in build_config.items():
# Check if the value is a dictionary
if isinstance(value, dict):
if value.get("input_types") is None:
build_config[key]["input_types"] = []
# Check if the value has an attribute 'input_types' and it is None
elif hasattr(value, "input_types") and value.input_types is None:
value.input_types = []
return build_config
Loading

0 comments on commit e2c26f1

Please # to comment.