Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds dynamic loading of agent workflow modules #2095

Merged
merged 8 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions docs/release-notes/breaking-changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,53 @@
> [!NOTE]
> This section is for changes that are not yet released but will affect future releases.

## Starting with 0.9.1-rc105

### Configuration changes

The following new App Configuration settings are required:

|Name | Default value | Description |
|--- | --- | --- |
|`FoundationaLLM:PythonSDK:Logging:LogLevel:Azure` | `Warning` | Provides the default level of logging for Azure modules in the Python SDK. |

### Agent workflow configuration changes

Agent resource configuration files that have a `workflow` property now requires a `name` and `package_name` property. This is to support loading external workflows via plugins. For internal workflows, the `package_name` should be set to `FoundationaLLM`. Example below truncated for brevity.

```json
{
"workflow": {
"type": "langgraph-react-agent-workflow",
"name": "LangGraphReactAgent",
"package_name": "FoundationaLLM",
"workflow_host": "LangChain",
"graph_recursion_limit": 10,
"resource_object_ids": {}
}
}
```

A new `Workflow` resource must be added to the `FoundationaLLM.Agent` resource provider:

```json
{
"type": "external-agent-workflow",
"name": "ExternalAgentWorkflow",
"object_id": "/instances/<instance_id>/providers/FoundationaLLM.Agent/workflows/ExternalAgentWorkflow",
"display_name": "ExternalAgentWorkflow",
"description": "External Agent workflow",
"cost_center": null,
"properties": null,
"created_on": "2024-11-13T18:12:07.0223039+00:00",
"updated_on": "0001-01-01T00:00:00+00:00",
"created_by": "[email protected]",
"updated_by": null,
"deleted": false,
"expiration_date": null
}
```

## Starting with 0.9.1-rc102

### Configuration changes
Expand Down
8 changes: 8 additions & 0 deletions src/dotnet/Common/Constants/Data/AppConfiguration.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@
"content_type": "",
"first_version": "0.9.0"
},
{
"name": "Logging:LogLevel:Azure",
"description": "The default logging level used by the Python SDK.",
"secret": "",
"value": "Warning",
"content_type": "",
"first_version": "0.9.1"
},
{
"name": "Logging:EnableConsoleLogging",
"description": "The flag indicating whether the Python SDK sends logs to the console or not.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace FoundationaLLM.Common.Models.ResourceProviders.Agent.AgentWorkflows
[JsonDerivedType(typeof(AzureOpenAIAssistantsAgentWorkflow), AgentWorkflowTypes.AzureOpenAIAssistants)]
[JsonDerivedType(typeof(LangChainExpressionLanguageAgentWorkflow), AgentWorkflowTypes.LangChainExpressionLanguage)]
[JsonDerivedType(typeof(LangGraphReactAgentWorkflow), AgentWorkflowTypes.LangGraphReactAgent)]
[JsonDerivedType(typeof(ExternalAgentWorkflow), AgentWorkflowTypes.ExternalAgentWorkflow)]
public class AgentWorkflowBase
{
/// <summary>
Expand All @@ -20,12 +21,17 @@ public class AgentWorkflowBase

/// <summary>
/// The name of the workflow.
/// </summary>
[JsonPropertyName("name")]
public required string Name { get; set; }

/// <summary>
/// Gets or sets the package name of the workflow.
/// For internal workflows, this value will be FoundationaLLM
/// For external workflows, this value will be the name of the package.
/// </summary>
/// <remarks>
/// This value is always derived from the <see cref="ResourceObjectIds"/> property.
/// </remarks>
[JsonPropertyName("workflow_name")]
public string? WorkflowName { get; set; }
[JsonPropertyName("package_name")]
public required string PackageName { get; set; }

/// <summary>
/// The host of the workflow environment.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,10 @@ public static class AgentWorkflowTypes
/// The LangGraph ReAct agent workflow.
/// </summary>
public const string LangGraphReactAgent = "langgraph-react-agent-workflow";

/// <summary>
/// The External Agent workflow.
/// </summary>
public const string ExternalAgentWorkflow = "external-agent-workflow";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.Text.Json.Serialization;

namespace FoundationaLLM.Common.Models.ResourceProviders.Agent.AgentWorkflows
{
/// <summary>
/// Provides an agent workflow configuration for an External Agent workflow loaded via an external module.
/// </summary>
public class ExternalAgentWorkflow : AgentWorkflowBase
{
/// <inheritdoc/>
[JsonIgnore]
public override string Type => AgentWorkflowTypes.ExternalAgentWorkflow;
}
}
7 changes: 7 additions & 0 deletions src/dotnet/Common/Templates/AppConfigurationKeys.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ public static class AppConfigurationKeys
public const string FoundationaLLM_PythonSDK_Logging_LogLevel_Default =
"FoundationaLLM:PythonSDK:Logging:LogLevel:Default";

/// <summary>
/// The app configuration key for the FoundationaLLM:PythonSDK:Logging:LogLevel:Azure setting.
/// <para>Value description:<br/>The default logging level used by the Python SDK.</para>
/// </summary>
public const string FoundationaLLM_PythonSDK_Logging_LogLevel_Azure =
"FoundationaLLM:PythonSDK:Logging:LogLevel:Azure";

/// <summary>
/// The app configuration key for the FoundationaLLM:PythonSDK:Logging:EnableConsoleLogging setting.
/// <para>Value description:<br/>The flag indicating whether the Python SDK sends logs to the console or not.</para>
Expand Down
7 changes: 7 additions & 0 deletions src/dotnet/Common/Templates/appconfig.template.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@
"content_type": "",
"tags": {}
},
{
"key": "FoundationaLLM:PythonSDK:Logging:LogLevel:Azure",
"value": "Warning",
"label": null,
"content_type": "",
"tags": {}
},
{
"key": "FoundationaLLM:PythonSDK:Logging:EnableConsoleLogging",
"value": "false",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,15 @@ await cosmosDBService.PatchOperationsItemPropertiesAsync<LongRunningOperationCon
}
break;
case AgentResourceTypeNames.Workflows:
agentWorkflow.WorkflowName = resourcePath.MainResourceId;

var retrievedWorkflow = await agentResourceProvider.GetResourceAsync<Workflow>(
resourceObjectId.ObjectId,
currentUserIdentity);

explodedObjectsManager.TryAdd(
retrievedWorkflow.ObjectId!,
retrievedWorkflow);

break;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from .skunkworks_tool_plugin_manager import SkunkworksToolPluginManager
from .skunkworks_workflow_plugin_manager import SkunkworksWorkflowPluginManager
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class SkunkworksToolPluginManager(ToolPluginManagerBase):
FOUNDATIONALLM_CODE_INTERPRETER_TOOL_NAME = 'FoundationaLLMCodeInterpreterTool'

def __init__(self):
pass
super().__init__()

def create_tool(self,
tool_config: AgentTool,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from typing import List

from foundationallm.config import Configuration, UserIdentity
from foundationallm.models.agents import AgentTool, ExternalAgentWorkflow
from foundationallm.langchain.common import FoundationaLLMWorkflowBase
from foundationallm.plugins import WorkflowPluginManagerBase

from skunkworks_foundationallm.workflows import (
FoundationaLLMRouterWorkflow
)

class SkunkworksWorkflowPluginManager(WorkflowPluginManagerBase):

FOUNDATIONALLM_ROUTER_WORKFLOW_NAME = 'FoundationaLLMRouterWorkflow'

def __init__(self):
super().__init__()

def create_workflow(
self,
workflow_config: ExternalAgentWorkflow,
objects: dict,
tools: List[AgentTool],
user_identity: UserIdentity,
config: Configuration) -> FoundationaLLMWorkflowBase:
"""
Create a workflow instance based on the given configuration and tools.
Parameters
----------
workflow_config : ExternalAgentWorkflow
The workflow assigned to the agent.
objects : dict
The exploded objects assigned from the agent.
tools : List[AgentTool]
The tools assigned to the agent.
user_identity : UserIdentity
The user identity of the user initiating the request.
config : Configuration
The application configuration for FoundationaLLM.
"""
match workflow_config.name:
case SkunkworksWorkflowPluginManager.FOUNDATIONALLM_ROUTER_WORKFLOW_NAME:
return FoundationaLLMRouterWorkflow(workflow_config, objects, tools, user_identity, config)
case _:
raise ValueError(f"Unknown tool name: {workflow_config.name}")

def refresh_tools():
print('Refreshing tools...')
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .foundationallm_router_workflow import FoundationaLLMRouterWorkflow
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
"""
Class: FoundationaLLMWorkflowBase
Description: FoundationaLLM base class for tools that uses the agent workflow model for its configuration.
"""
from abc import ABC, abstractmethod
from azure.identity import DefaultAzureCredential
from langchain_core.messages import BaseMessage
from pydantic import BaseModel
from typing import List
from foundationallm.config import Configuration, UserIdentity
from foundationallm.langchain.common import FoundationaLLMWorkflowBase
from foundationallm.models.agents import AgentTool, ExternalAgentWorkflow
from foundationallm.models.constants import AgentCapabilityCategories
from foundationallm.models.orchestration import CompletionResponse, OpenAITextMessageContentItem
from foundationallm.telemetry import Telemetry

class FoundationaLLMRouterWorkflow(FoundationaLLMWorkflowBase):
"""
FoundationaLLM base class for workflows that uses the agent workflow model for its configuration.
"""
def __init__(self,
workflow_config: ExternalAgentWorkflow,
objects: dict,
tools: List[AgentTool],
user_identity: UserIdentity,
config: Configuration):
"""
Initializes the FoundationaLLMWorkflowBase class with the workflow configuration.

Parameters
----------
workflow_config : ExternalAgentWorkflow
The workflow assigned to the agent.
objects : dict
The exploded objects assigned from the agent.
tools : List[AgentTool]
The tools assigned to the agent.
user_identity : UserIdentity
The user identity of the user initiating the request.
config : Configuration
The application configuration for FoundationaLLM.
"""
super().__init__(workflow_config, objects, tools, user_identity, config)

async def invoke_async(self,
operation_id: str,
user_prompt:str,
message_history: List[BaseMessage])-> CompletionResponse:
"""
Invokes the workflow asynchronously.

Parameters
----------
operation_id : str
The unique identifier of the FoundationaLLM operation.
user_prompt : str
The user prompt message.
message_history : List[BaseMessage]
The message history.
"""
response_content = OpenAITextMessageContentItem(
value = '42 is the answer to all questions',
agent_capability_category = AgentCapabilityCategories.FOUNDATIONALLM_KNOWLEDGE_MANAGEMENT
)


return CompletionResponse(
operation_id = operation_id,
content = [response_content],
content_artifacts = [],
user_prompt = user_prompt,
full_prompt = '',
completion_tokens = 0,
prompt_tokens = 0,
total_tokens = 0,
total_cost = 0
)
8 changes: 8 additions & 0 deletions src/python/PythonSDK/PythonSDK.pyproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,15 @@
<Compile Include="foundationallm\exceptions\__init__.py" />
<Compile Include="foundationallm\langchain\agents\langchain_knowledge_management_agent.py" />
<Compile Include="foundationallm\langchain\common\foundationallm_tool_base.py" />
<Compile Include="foundationallm\langchain\common\foundationallm_workflow_base.py" />
<Compile Include="foundationallm\langchain\common\__init__.py" />
<Compile Include="foundationallm\langchain\workflows\external_workflow_factory.py" />
<Compile Include="foundationallm\langchain\workflows\__init__.py" />
<Compile Include="foundationallm\models\agents\agent_tool.py" />
<Compile Include="foundationallm\models\agents\agent_workflows\agent_workflow_ai_model.py" />
<Compile Include="foundationallm\models\agents\agent_workflows\agent_workflow_base.py" />
<Compile Include="foundationallm\models\agents\agent_workflows\azure_openai_assistants_agent_workflow.py" />
<Compile Include="foundationallm\models\agents\agent_workflows\external_agent_workflow.py" />
<Compile Include="foundationallm\models\agents\agent_workflows\langchain_expression_language_agent_workflow.py" />
<Compile Include="foundationallm\models\agents\agent_workflows\langgraph_react_agent_workflow.py" />
<Compile Include="foundationallm\models\attachments\attachment_properties.py" />
Expand All @@ -56,7 +60,9 @@
<Compile Include="foundationallm\models\services\openai_assistants_response.py" />
<Compile Include="foundationallm\plugins\external_module.py" />
<Compile Include="foundationallm\plugins\plugin_manager.py" />
<Compile Include="foundationallm\plugins\plugin_manager_types.py" />
<Compile Include="foundationallm\plugins\tools\tool_plugin_manager_base.py" />
<Compile Include="foundationallm\plugins\workflows\workflow_plugin_manager_base.py" />
<Compile Include="foundationallm\plugins\__init__.py" />
<Compile Include="foundationallm\services\audio_analysis_service.py" />
<Compile Include="foundationallm\services\gateway_text_embedding\text_chunk.py" />
Expand Down Expand Up @@ -185,12 +191,14 @@
<Folder Include="foundationallm\langchain\language_models\" />
<Folder Include="foundationallm\langchain\language_models\openai\" />
<Folder Include="foundationallm\langchain\exceptions\" />
<Folder Include="foundationallm\langchain\workflows\" />
<Folder Include="foundationallm\models\agents\agent_workflows\" />
<Folder Include="foundationallm\models\attachments\" />
<Folder Include="foundationallm\models\constants\" />
<Folder Include="foundationallm\event_handlers\" />
<Folder Include="foundationallm\models\messages\" />
<Folder Include="foundationallm\plugins\" />
<Folder Include="foundationallm\plugins\workflows\" />
<Folder Include="foundationallm\plugins\tools\" />
<Folder Include="foundationallm\services\" />
<Folder Include="foundationallm\langchain\retrievers\" />
Expand Down
Loading
Loading