-
Notifications
You must be signed in to change notification settings - Fork 778
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
Enable AIFunctionFactory to resolve parameters from an IServiceProvider #5956
base: main
Are you sure you want to change the base?
Conversation
🎉 Good job! The coverage increased 🎉
Full code coverage report: https://dev.azure.com/dnceng-public/public/_build/results?buildId=960014&view=codecoverage-tab |
src/Libraries/Microsoft.Extensions.AI.Abstractions/FromServiceProviderAttribute.cs
Outdated
Show resolved
Hide resolved
src/Libraries/Microsoft.Extensions.AI.Abstractions/Utilities/AIJsonUtilities.Schema.cs
Outdated
Show resolved
Hide resolved
src/Libraries/Microsoft.Extensions.AI/ChatCompletion/FunctionInvocationContext.cs
Outdated
Show resolved
Hide resolved
src/Libraries/Microsoft.Extensions.AI/Functions/AIFunctionFactory.cs
Outdated
Show resolved
Hide resolved
src/Libraries/Microsoft.Extensions.AI/Functions/AIFunctionFactory.cs
Outdated
Show resolved
Hide resolved
170d874
to
31a6da0
Compare
src/Libraries/Microsoft.Extensions.AI/ChatCompletion/FromServiceProviderAttribute.cs
Outdated
Show resolved
Hide resolved
src/Libraries/Microsoft.Extensions.AI/ChatCompletion/FromServiceProviderAttribute.cs
Outdated
Show resolved
Hide resolved
src/Libraries/Microsoft.Extensions.AI/Functions/AIFunctionFactory.cs
Outdated
Show resolved
Hide resolved
src/Libraries/Microsoft.Extensions.AI/Functions/AIFunctionFactory.cs
Outdated
Show resolved
Hide resolved
src/Libraries/Microsoft.Extensions.AI/ChatCompletion/FunctionInvokingChatClient.cs
Outdated
Show resolved
Hide resolved
31a6da0
to
0f43eed
Compare
{ | ||
if (fspAttr.ServiceKey is object serviceKey) | ||
if ((arguments as AIFunctionArguments)?.ServiceProvider is IServiceProvider services) |
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 need to use a magic dictionary type makes me sad, but at the same time I can't think of a better solution that addresses our current dependency constraints.
Making it optional does seem like a pit of failure for library authors whose test coverage doesn't include DI scenaria. Should we consider requiring that input dictionaries are always of this type regardless?
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.
One possibility I considered is using a dependency inversion scheme where the InvokeAsync
method accepts a Func<Type, object>
either directly or through an "AIFunctionInvocationContext" type that contains it as a property.
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.
consider requiring that input dictionaries are always of this type regardless?
I'd rather not, both because it limits what input types are possible but also because it makes the IServiceProvider a prominent thing that's part of the base abstraction, when it's not really.
Making it optional does seem like a pit of failure for library authors whose test coverage doesn't include DI scenaria. Should we consider requiring that input dictionaries are always of this type regardless?
I wouldn't expect this to be an issue for most library authors. What are these libraries doing? The only component that would need to instantiate this type to flow additional data through would be something that's invoking arbitrary AIFunction instances, ala FunctionInvokingChatClient.
I agree it's not ideal. I just don't have a better answer that keeps AIFunction.InvokeAsync simple and clean while still allowing for other ambient context to be passed through. If we want to change InvokeAsync now, before it's stable, options would include changing the type of the argument, adding an additional dictionary argument for ambient context in addition to named arguments, adding some kind of callback argument that the AIFunction could use to retrieve the value for an argument, e.g. Func<string, object?>? argumentFactory
(where we establish a search order between the dictionary and the callback), etc. I'm not sure any of those is better, though I'm open to arguments (no pun intended).
0f43eed
to
c9b580a
Compare
src/Libraries/Microsoft.Extensions.AI/ChatCompletion/FunctionInvokingChatClient.cs
Outdated
Show resolved
Hide resolved
c9b580a
to
08c4d4b
Compare
In a discussion last week, @eiriktsarpalis suggested that sooner or later we'll want to support AIFunctionFactory being able to populate parameters from DI. The second commit here is how I think we could do that. (Ignore the first commit, it's just #5954.) What do we think? Is this something we'd want to proceed with, or if not, are we comfortable with this as a future solution, in which case this demonstrates it's possible without breakage?
Effectively, it enables someone to write:
ala what you can do with MVC and SK and others. When constructing a FunctionInvokingChatClient, it'll hold onto whatever IServiceProvider was used to construct it, and then feed that into AIFunction.InvokeAsync via an AIFunctionArguments type that AIFunctionFactory type checks for.
cc: @eiriktsarpalis, @SteveSandersonMS, @halter73
Microsoft Reviewers: Open in CodeFlow