Skip to content

Commit b36b9cf

Browse files
authored
Create classes ad sample code for Azure Functions (Azure#47319)
* Add Azure Functions
1 parent 68fcfb6 commit b36b9cf

File tree

65 files changed

+3693
-101
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+3693
-101
lines changed

sdk/ai/Azure.AI.Projects/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,16 @@
44

55
### Features Added
66

7+
* Added `AzureFunctionToolDefinition` support to inform Agents about Azure Functions.
8+
* Added `OpenApiTool` for Agents, which creates and executes a REST function defined by an OpenAPI spec.
9+
* Add `parallelToolCalls` parameter to `CreateRunRequest`, `CreateRunAsync`, `CreateRunStreaming` and `CreateRunStreamingAsync`, which allows parallel tool execution for Agents.
10+
711
### Breaking Changes
812

913
### Bugs Fixed
1014

15+
* Fix a bug preventing additional messages to be created when using `CreateRunStreamingAsync` and `CreateRunAsync` see [issue](https://github.com/Azure/azure-sdk-for-net/issues/47244).
16+
1117
### Other Changes
1218

1319
## 1.0.0-beta.1 (2024-11-19)

sdk/ai/Azure.AI.Projects/README.md

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ Use the AI Projects client library to:
2020
- [Retrieve messages](#retrieve-messages)
2121
- [File search](#file-search)
2222
- [Function call](#function-call)
23+
- [Azure function call](#azure-function-call)
24+
- [Azure Function Call](#create-agent-with-azure-function-call)
25+
- [OpenAPI](#create-agent-with-openapi)
2326
- [Troubleshooting](#troubleshooting)
2427
- [Next steps](#next-steps)
2528
- [Contributing](#contributing)
@@ -347,6 +350,126 @@ while (runResponse.Value.Status == RunStatus.Queued
347350
|| runResponse.Value.Status == RunStatus.InProgress);
348351
```
349352

353+
#### Azure function call
354+
355+
We also can use Azure Function from inside the agent. In the example below we are calling function "foo", which responds "Bar". In this example we create `AzureFunctionToolDefinition` object, with the function name, description, input and output queues, followed by function parameters.
356+
```C# Snippet:AzureFunctionsDefineFunctionTools
357+
AzureFunctionToolDefinition azureFnTool = new(
358+
name: "foo",
359+
description: "Get answers from the foo bot.",
360+
inputBinding: new AzureFunctionBinding(
361+
new AzureFunctionStorageQueue(
362+
queueName: "azure-function-foo-input",
363+
storageServiceEndpoint: storageQueueUri
364+
)
365+
),
366+
outputBinding: new AzureFunctionBinding(
367+
new AzureFunctionStorageQueue(
368+
queueName: "azure-function-tool-output",
369+
storageServiceEndpoint: storageQueueUri
370+
)
371+
),
372+
parameters: BinaryData.FromObjectAsJson(
373+
new
374+
{
375+
Type = "object",
376+
Properties = new
377+
{
378+
query = new
379+
{
380+
Type = "string",
381+
Description = "The question to ask.",
382+
},
383+
outputqueueuri = new
384+
{
385+
Type = "string",
386+
Description = "The full output queue uri."
387+
}
388+
},
389+
},
390+
new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }
391+
)
392+
);
393+
```
394+
395+
Note that in this scenario we are asking agent to supply storage queue URI to the azure function whenever it is called.
396+
```C# Snippet:AzureFunctionsCreateAgentWithFunctionTools
397+
Response<Agent> agentResponse = await client.CreateAgentAsync(
398+
model: "gpt-4",
399+
name: "azure-function-agent-foo",
400+
instructions: "You are a helpful support agent. Use the provided function any "
401+
+ "time the prompt contains the string 'What would foo say?'. When you invoke "
402+
+ "the function, ALWAYS specify the output queue uri parameter as "
403+
+ $"'{storageQueueUri}/azure-function-tool-output'. Always responds with "
404+
+ "\"Foo says\" and then the response from the tool.",
405+
tools: new List<ToolDefinition> { azureFnTool }
406+
);
407+
Agent agent = agentResponse.Value;
408+
```
409+
410+
After we have created a message with request to ask "What would foo say?", we need to wait while the run is in queued, in progress or requires action states.
411+
```C# Snippet:AzureFunctionsHandlePollingWithRequiredAction
412+
Response<ThreadMessage> messageResponse = await client.CreateMessageAsync(
413+
thread.Id,
414+
MessageRole.User,
415+
"What is the most prevalent element in the universe? What would foo say?");
416+
ThreadMessage message = messageResponse.Value;
417+
418+
Response<ThreadRun> runResponse = await client.CreateRunAsync(thread, agent);
419+
420+
do
421+
{
422+
await Task.Delay(TimeSpan.FromMilliseconds(500));
423+
runResponse = await client.GetRunAsync(thread.Id, runResponse.Value.Id);
424+
}
425+
while (runResponse.Value.Status == RunStatus.Queued
426+
|| runResponse.Value.Status == RunStatus.InProgress
427+
|| runResponse.Value.Status == RunStatus.RequiresAction);
428+
```
429+
430+
#### Create Agent With OpenAPI
431+
432+
OpenAPI specifications describe REST operations against a specific endpoint. Agents SDK can read an OpenAPI spec, create a function from it, and call that function against the REST endpoint without additional client-side execution.
433+
434+
Here is an example creating an OpenAPI tool (using anonymous authentication):
435+
```C# Snippet:OpenAPIDefineFunctionTools
436+
OpenApiAnonymousAuthDetails oaiAuth = new();
437+
OpenApiToolDefinition openapiTool = new(
438+
name: "get_weather",
439+
description: "Retrieve weather information for a location",
440+
spec: BinaryData.FromBytes(File.ReadAllBytes(file_path)),
441+
auth: oaiAuth
442+
);
443+
444+
Response<Agent> agentResponse = await client.CreateAgentAsync(
445+
model: "gpt-4",
446+
name: "azure-function-agent-foo",
447+
instructions: "You are a helpful assistant.",
448+
tools: new List<ToolDefinition> { openapiTool }
449+
);
450+
Agent agent = agentResponse.Value;
451+
```
452+
453+
In this example we are using the `weather_openapi.json` file and agent will request the wttr.in website for the weather in a location fron the prompt.
454+
```C# Snippet:OpenAPIHandlePollingWithRequiredAction
455+
Response<ThreadMessage> messageResponse = await client.CreateMessageAsync(
456+
thread.Id,
457+
MessageRole.User,
458+
"What's the weather in Seattle?");
459+
ThreadMessage message = messageResponse.Value;
460+
461+
Response<ThreadRun> runResponse = await client.CreateRunAsync(thread, agent);
462+
463+
do
464+
{
465+
await Task.Delay(TimeSpan.FromMilliseconds(500));
466+
runResponse = await client.GetRunAsync(thread.Id, runResponse.Value.Id);
467+
}
468+
while (runResponse.Value.Status == RunStatus.Queued
469+
|| runResponse.Value.Status == RunStatus.InProgress
470+
|| runResponse.Value.Status == RunStatus.RequiresAction);
471+
```
472+
350473
## Troubleshooting
351474

352475
Any operation that fails will throw a [RequestFailedException][RequestFailedException]. The exception's `code` will hold the HTTP response status code. The exception's `message` contains a detailed message that may be helpful in diagnosing the issue:

0 commit comments

Comments
 (0)