-
Notifications
You must be signed in to change notification settings - Fork 138
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
add config field in MLToolSpec for static parameters #2977
Conversation
Signed-off-by: Jing Zhang <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you open an issue on Flow Framework repo amplifying what changed here? We will need to update the ToolStep
to account for a change in API. Better yet, open a PR with the changes!
Also please make sure you update the API specification which Flow Framework will be using to validate these API parameters. (It's a checklist item at the top of this PR.)
common/src/main/java/org/opensearch/ml/common/agent/MLToolSpec.java
Outdated
Show resolved
Hide resolved
The flow framework issue, opensearch-project/flow-framework#878. |
Signed-off-by: Jing Zhang <[email protected]>
common/src/main/java/org/opensearch/ml/common/agent/MLToolSpec.java
Outdated
Show resolved
Hide resolved
common/src/main/java/org/opensearch/ml/common/agent/MLToolSpec.java
Outdated
Show resolved
Hide resolved
common/src/main/java/org/opensearch/ml/common/agent/MLToolSpec.java
Outdated
Show resolved
Hide resolved
common/src/test/java/org/opensearch/ml/common/agent/MLAgentTest.java
Outdated
Show resolved
Hide resolved
common/src/test/java/org/opensearch/ml/common/agent/MLToolSpecTest.java
Outdated
Show resolved
Hide resolved
common/src/test/java/org/opensearch/ml/common/agent/MLToolSpecTest.java
Outdated
Show resolved
Hide resolved
Signed-off-by: Jing Zhang <[email protected]>
@reuschling Can you help review this PR? |
@jngz-es Can you please provide an example on how to use tool |
String description, | ||
Map<String, String> parameters, | ||
boolean includeOutputInAgentResponse, | ||
Map<String, String> configMap |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it valid that all the configs are Strings? Is it better to use Map<String, Object> here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 on this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-1 on that. The parameters map is already a Map<String, String>
. In the initial PR comment an example is given of a much more complex "object" but escaped as a String.
Trying to parse anything else from Flow Framework will get a lot more complex without typed objects to construct from the JSON.
@@ -56,6 +70,9 @@ public MLToolSpec(StreamInput input) throws IOException { | |||
parameters = input.readMap(StreamInput::readString, StreamInput::readOptionalString); | |||
} | |||
includeOutputInAgentResponse = input.readBoolean(); | |||
if (input.getVersion().onOrAfter(MINIMAL_SUPPORTED_VERSION_FOR_TOOL_CONFIG) && input.readBoolean()) { | |||
configMap = input.readMap(StreamInput::readString, StreamInput::readOptionalString); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why readOptionalString
? so a key might not have a value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this allows you to override a value with a non-value.
if (tools.get(action).useOriginalInput()) { | ||
toolParams.put("input", question); | ||
lastActionInput.set(question); | ||
} else if (toolSpecConfigMap != null && toolSpecConfigMap.containsKey("input")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we have any test class for this?
@@ -428,12 +428,18 @@ Map<String, String> getToolExecuteParams(MLToolSpec toolSpec, Map<String, String | |||
} | |||
} | |||
|
|||
// Override all parameters in tool config to tool execution parameters as the config contains the static parameters. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment isn’t quite clear to me. Could we try to explain it more clearly?
@@ -287,13 +287,18 @@ Map<String, String> getToolExecuteParams(MLToolSpec toolSpec, Map<String, String | |||
executeParams.put(key, params.get(key)); | |||
} | |||
} | |||
// Override all parameters in tool config to tool execution parameters as the config contains the static parameters. | |||
if (toolSpec.getConfigMap() != null && !toolSpec.getConfigMap().isEmpty()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rather than putting same piece of code, can we try to use a common method getToolExecuteParams
for both MLFlowAgentRunner & MLConversationalFlowAgentRunner?
Pinging @reuschling to review the PR. |
Thanks @yuye-aws for prompting review on this. Thanks @Zhangxunmt for approval. Thanks @dhrubo-os for your initial review. Code freeze / 2.18 RC generation is next Tuesday Oct 22. Downstream plugin PRs (opensearch-project/flow-framework#899) are dependent on this one being merged and need time to update and consume tne new snapshots, get proper reviews, and merge before code freeze. Please do not wait until the last minute to get this merged; last-minute PR merges have occurred in at least 2 previous releases and this one's been open for a few weeks. I'm sensing a pattern here. CC: @minalsha @ylwu-amzn |
if (executeParams.containsKey("input")) { | ||
String input = executeParams.get("input"); | ||
StringSubstitutor substitutor = new StringSubstitutor(executeParams, "${parameters.", "}"); | ||
input = substitutor.replace(input); | ||
executeParams.put("input", input); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if we have a chicken-and-egg problem here regarding the 'input' parameter. In #2918 'SearchIndexTool inside conversational agent', there is the need of a placeholder for the last output (i.e. action input) of the former agent step. This output/action input must be inserted into the OpenSearch query defined statically inside the new config, by placeholder.
There exists two possibilities for this:
- There is an existing placeholder reference to the last output/action input that can be used, i.e. a dedicated parameter list entry. I'm not aware of such an entry, but if such a placeholder exists, the current solution would fix this scenario with a static config of e.g. ["input='"query": {"match": {"body": {"query": "${someUnknownPlaceholderToActionInput}"}}'"].
- There is no such a placeholder, the last output/action input is just the 'input' entry in the current 'params' method parameter - so the placeholder inside the static config would be 'input'. This value inside 'params' is currently overwritten with 'input' from the static config, before substitution. So it is lost, right?
The final behavior should be as follows:
- method params: "input='What is Frodos age?'" (comes from former agent step)
- static config params "input='"query": {"match": {"body": {"query": "${parameters.input}"}}'"
=> final params for tool execution should be then
"input='"query": {"match": {"body": {"query": "What is Frodos age?"}}'"
This could be achieved as follows:
// remember former input
String formerInput = executeParams.get("input");
if (toolSpec.getConfigMap() != null && !toolSpec.getConfigMap().isEmpty()) {
executeParams.putAll(toolSpec.getConfigMap());
}
if (executeParams.containsKey("input")) {
String input = executeParams.get("input");
// set former input as substitution value
if(formerInput != null)
executeParams.put("input", formerInput); // add it as "formerInput" or "actionInput" to introduce a new placeholder
StringSubstitutor substitutor = new StringSubstitutor(executeParams, "${parameters.", "}");
input = substitutor.replace(input);
executeParams.put("input", input);
The lack is that you can not reference to the input specified in the new static config anymore, which is maybe wanted behavior. To overcome this, we could introduce a new placeholder for the former input (aka the placeholder I mentioned in 1.). This would be a new parameter list entry, e.g. 'formerInput' (just add the formerInput with executeParams.put("formerInput", formerInput);
).
The static config could be defined now as ["input='"query": {"match": {"body": {"query": "${parameters.formerInput}"}}'"].
Another name for 'formerInput' could be 'actionInput', maybe this is more intuitive.
The same is true for MLFlowAgentRunner
of course, and for AgentUtils
, whereby in AgentUtils the former input is defined in the method parameter 'actionInput'. So the only change here would be executeParams.put("formerInput", actionInput);
or executeParams.put("actionInput", actionInput);
respectively.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @reuschling for the detailed comment. Actually we are the first possibility you mentioned.
Flow Agent
We have a dedicated parameter parameter for the previous tool output here https://github.com/opensearch-project/ml-commons/blob/main/ml-algorithms/src/main/java/org/opensearch/ml/engine/algorithms/agent/MLFlowAgentRunner.java#L112. So you can reference it in the current tool input parameter as ${parameters.previous_tool_name.output}.
Conversational Agent
We take the action input for tools only from LLM response, i.e, the agent totally depends on LLM to do the ReAct. User can define a tool input to override the action input, but I don't see a use case for a placeholder of action input.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good to hear that there is already a parameter for flow agent.
For Conversational agent, my example is exactly my use case. I want to predefine an Opensearch query, and the tool description says what's to insert. Thus, the previous llm step (the agent) doesn't have to generate the opensearch syntax, only a simple drop in, so I can guarantee this query will be executed, under all circumstances.
More specifically, I want to e. g. count documents with a query string inside.
Without a placeholder, the agent would have no possibility to adjust the query - only static queries independent from the previous steps in the thought chain would be possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got your point. I created another issue to track it. #3134
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a chance left that it make it to 2.18?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@reuschling The backport PR has been merged into the 2.x branch. The 2.18 branch will include this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean the conversational agent placeholder now tracked in #3134
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @reuschling , I raised a pr #3200, could you take a look?
String input = toolSpecConfigMap.get("input"); | ||
StringSubstitutor substitutor = new StringSubstitutor(toolParams, "${parameters.", "}"); | ||
input = substitutor.replace(input); | ||
toolParams.put("input", input); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add these
if (isJson(actionInput)) {
Map<String, String> params = getParameterMap(gson.fromJson(actionInput, Map.class));
toolParams.putAll(params);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good catch, added
Signed-off-by: Jing Zhang <[email protected]>
* add config field in MLToolSpec for static parameters Signed-off-by: Jing Zhang <[email protected]> * add version control Signed-off-by: Jing Zhang <[email protected]> * address comments I Signed-off-by: Jing Zhang <[email protected]> * address commits II Signed-off-by: Jing Zhang <[email protected]> * address comments III Signed-off-by: Jing Zhang <[email protected]> --------- Signed-off-by: Jing Zhang <[email protected]> (cherry picked from commit 9ed0040)
* add config field in MLToolSpec for static parameters Signed-off-by: Jing Zhang <[email protected]> * add version control Signed-off-by: Jing Zhang <[email protected]> * address comments I Signed-off-by: Jing Zhang <[email protected]> * address commits II Signed-off-by: Jing Zhang <[email protected]> * address comments III Signed-off-by: Jing Zhang <[email protected]> --------- Signed-off-by: Jing Zhang <[email protected]> (cherry picked from commit 9ed0040) Co-authored-by: Jing Zhang <[email protected]>
Description
Add config field in MLToolSpec to support static parameters in tool execution.
An example from the issue 2918.
Related Issues
#2836
#2918
Check List
--signoff
.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.