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

feat(core): Implement Dynamic Parameters within regular nodes used as AI Tools #10862

Merged
merged 15 commits into from
Oct 2, 2024

Conversation

OlegIvaniv
Copy link
Contributor

@OlegIvaniv OlegIvaniv commented Sep 17, 2024

Summary

This PR introduces a new feature that allows LLM to dynamically interact with n8n nodes when used as tools. The core of this feature is the new $fromAI() function, which allows for the definition of parameters that can be populated by AI models during workflow execution.

CleanShot.2024-09-17.at.21.50.55.mp4

Key Changes

  1. Introduced a new $fromAI() function for defining AI-powered parameters in node configurations.
  2. Updated the WorkflowDataProxy to handle $fromAI() calls and retrieve values passed by LLMs.
  3. Modified the createNodeAsTool function to support AI tool conversions, including automatic description generation based on resource and operation.
  4. Added support for various data types (string, number, boolean, json, date) in AI-powered parameters.
  5. Updated several nodes to be usable as AI tools.

Implementation Details

$fromAI Function

The $fromAI() function is implemented in the WorkflowDataProxy class and accepts four parameters:

  1. name: A string identifier for the parameter (required)
  2. description: A string describing the parameter's purpose (optional)
  3. type: A string specifying the data type (optional, defaults to 'string')
  4. defaultValue: A fallback value if no AI input is provided (optional)

Example usage:

"inputText": "={{ $fromAI('inputText', 'Enter main text to process', 'string') }}"

Parsing and Schema Generation

  • The parseFromAIArguments function uses a regex to extract all $fromAI() calls from the node parameters.
  • Each extracted call is parsed into a FromAIArgument object using the parseArguments function.
  • The generateZodSchema function creates a Zod schema based on the parsed arguments, which is used for validation and type-checking.

Node Conversion to AI Tools

The convertNodeToAiTool function has been updated to:

  • Modify the node's name, displayName, and I/O configuration for AI tool usage.
  • Add a descriptionType property allowing users to choose between automatic and manual description generation.
  • Insert a toolDescription property for manual description input when needed.

WorkflowDataProxy Updates

  • The $fromAI method in WorkflowDataProxy retrieves values passed by LLMs from the runExecutionData.
  • It includes validation for parameter names and handles cases where no execution data is available.

CodeMirror Integration

CleanShot 2024-09-17 at 21 53 09

  • Added $fromAI() to the list of root dollar completions in the CodeMirror plugin.
  • Updated the completion info to include examples and parameter descriptions.

Node Updates

Several core nodes (including Airtable, Baserow, Google Calendar, Gmail, Google Sheets, HackerNews, Postgres, Supabase, Telegram) have been updated with a usableAsTool: true property to indicate their compatibility with this new feature.

Review / Merge checklist

  • PR title and summary are descriptive. (conventions)
  • Docs updated or follow-up ticket created.
  • Tests included.
  • PR Labeled with release/backport (if the PR is an urgent fix that needs to be backported)

@n8n-assistant n8n-assistant bot added core Enhancement outside /nodes-base and /editor-ui n8n team Authored by the n8n team node/improvement New feature or request ui Enhancement in /editor-ui or /design-system labels Sep 17, 2024
Copy link
Contributor

@jeanpaul jeanpaul left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bravo! This is awesome work!

I have a couple of smaller comments / questions, but one thing that we definitely need to address is the parsing of the arguments to $fromAI. One thing that came to mind is that we may need to do more proper parsing, because users might be inclined to do things we don't anticipate yet, that are valid javascript.

Also, as discussed, I encountered an issue with Claude, when returning plain results from the HN node; I'm not sure what to do there, but maybe we need to wrap the results in something that's more easily digestible for some models?

packages/workflow/src/NodeHelpers.ts Outdated Show resolved Hide resolved
packages/core/test/CreateNodeAsTool.test.ts Outdated Show resolved Hide resolved
packages/core/src/CreateNodeAsTool.ts Outdated Show resolved Hide resolved
if (!(remainingPath[i] in current)) {
current[remainingPath[i]] = {};
// Handle quotes (single or double)
if (char === "'" || char === '"') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this handle escaped characters properly? I tried it, and got some weird results:

argsString: 'database-filter', 'the filter\\'s keyword to apply to the database', string, ['a\\'b', 'b']
result: {
  key: 'database-filter',
  description: "the filter\\\\'s keyword to apply to the database', string, ['a\\\\'b",
  type: "b']",
  defaultValue: undefined
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I improved the parsing method and added a few more tests; could you have another look?

@OlegIvaniv
Copy link
Contributor Author

Thanks for the review @jeanpaul! I improved the parsing logic and added a few more tests, could you re-review, pls?

Copy link
Contributor

@jeanpaul jeanpaul left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice! Awesome expansion of the tests as well.
Left another few small comments, but other than that looks great.

packages/core/src/CreateNodeAsTool.ts Outdated Show resolved Hide resolved
continue;
}

if (char === '"' || char === "'") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we add backticks as quote-chars as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated + added unit tests

@OlegIvaniv
Copy link
Contributor Author

@jeanpaul I updated the PR with the fixes product and reorganized unit tests + removed some duplicates. Could you have one last look? 🙏

Copy link
Contributor

@jeanpaul jeanpaul left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One small gotcha (and a quick check for my understanding :))

packages/core/src/CreateNodeAsTool.ts Outdated Show resolved Hide resolved
packages/core/src/CreateNodeAsTool.ts Show resolved Hide resolved
Copy link
Contributor

github-actions bot commented Oct 2, 2024

✅ All Cypress E2E specs passed

Copy link

cypress bot commented Oct 2, 2024

n8n    Run #7127

Run Properties:  status check passed Passed #7127  •  git commit 193f913c0d: 🌳 🖥️ browsers:node18.12.0-chrome107 🤖 OlegIvaniv 🗃️ e2e/*
Project n8n
Branch Review ai-285-implement-placeholders
Run status status check passed Passed #7127
Run duration 04m 33s
Commit git commit 193f913c0d: 🌳 🖥️ browsers:node18.12.0-chrome107 🤖 OlegIvaniv 🗃️ e2e/*
Committer Oleg Ivaniv
View all properties for this run ↗︎

Test results
Tests that failed  Failures 0
Tests that were flaky  Flaky 0
Tests that did not run due to a developer annotating a test with .skip  Pending 0
Tests that did not run due to a failure in a mocha hook  Skipped 0
Tests that passed  Passing 437
View all changes introduced in this branch ↗︎

@OlegIvaniv OlegIvaniv merged commit ef5b7cf into master Oct 2, 2024
51 checks passed
@OlegIvaniv OlegIvaniv deleted the ai-285-implement-placeholders branch October 2, 2024 11:31
@github-actions github-actions bot mentioned this pull request Oct 2, 2024
@janober
Copy link
Member

janober commented Oct 2, 2024

Got released with [email protected]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core Enhancement outside /nodes-base and /editor-ui n8n team Authored by the n8n team node/improvement New feature or request Released ui Enhancement in /editor-ui or /design-system
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants