Skip to content

Commit 0dfe56c

Browse files
committed
adding java
1 parent 171cacd commit 0dfe56c

File tree

2 files changed

+237
-0
lines changed

2 files changed

+237
-0
lines changed

articles/ai-foundry/agents/how-to/tools/function-calling.md

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,3 +676,238 @@ curl --request GET \
676676
```
677677

678678
::: zone-end
679+
680+
::: zone pivot="java"
681+
682+
```java
683+
package com.example.agents;
684+
685+
import com.azure.ai.agents.persistent.MessagesClient;
686+
import com.azure.ai.agents.persistent.PersistentAgentsAdministrationClient;
687+
import com.azure.ai.agents.persistent.PersistentAgentsClient;
688+
import com.azure.ai.agents.persistent.PersistentAgentsClientBuilder;
689+
import com.azure.ai.agents.persistent.RunsClient;
690+
import com.azure.ai.agents.persistent.ThreadsClient;
691+
import com.azure.ai.agents.persistent.models.CreateAgentOptions;
692+
import com.azure.ai.agents.persistent.models.CreateRunOptions;
693+
import com.azure.ai.agents.persistent.models.FunctionDefinition;
694+
import com.azure.ai.agents.persistent.models.FunctionToolDefinition;
695+
import com.azure.ai.agents.persistent.models.MessageImageFileContent;
696+
import com.azure.ai.agents.persistent.models.MessageRole;
697+
import com.azure.ai.agents.persistent.models.MessageTextContent;
698+
import com.azure.ai.agents.persistent.models.PersistentAgent;
699+
import com.azure.ai.agents.persistent.models.PersistentAgentThread;
700+
import com.azure.ai.agents.persistent.models.RequiredFunctionToolCall;
701+
import com.azure.ai.agents.persistent.models.RequiredToolCall;
702+
import com.azure.ai.agents.persistent.models.RunStatus;
703+
import com.azure.ai.agents.persistent.models.SubmitToolOutputsAction;
704+
import com.azure.ai.agents.persistent.models.ThreadMessage;
705+
import com.azure.ai.agents.persistent.models.ThreadRun;
706+
import com.azure.ai.agents.persistent.models.ToolOutput;
707+
import com.azure.ai.agents.persistent.models.MessageContent;
708+
import com.azure.core.http.rest.PagedIterable;
709+
import com.azure.core.util.BinaryData;
710+
import com.azure.identity.DefaultAzureCredentialBuilder;
711+
import com.fasterxml.jackson.core.JsonProcessingException;
712+
import com.fasterxml.jackson.databind.JsonNode;
713+
import com.fasterxml.jackson.databind.json.JsonMapper;
714+
715+
import java.net.URL;
716+
import java.io.File;
717+
import java.io.FileNotFoundException;
718+
import java.net.URISyntaxException;
719+
import java.nio.file.Path;
720+
import java.util.ArrayList;
721+
import java.util.Arrays;
722+
import java.util.HashMap;
723+
import java.util.Map;
724+
import java.util.function.Function;
725+
726+
public class AgentExample {
727+
728+
public static void main(String[] args) throws FileNotFoundException, URISyntaxException {
729+
730+
// variables for authenticating requests to the agent service
731+
String projectEndpoint = "https://aahi-may-resource.services.ai.azure.com/api/projects/aahi-may";//System.getenv("PROJECT_ENDPOINT");
732+
String modelName = "gpt-4o";//System.getenv("MODEL_DEPLOYMENT_NAME");
733+
734+
PersistentAgentsClientBuilder clientBuilder = new PersistentAgentsClientBuilder().endpoint(projectEndpoint)
735+
.credential(new DefaultAzureCredentialBuilder().build());
736+
PersistentAgentsClient agentsClient = clientBuilder.buildClient();
737+
PersistentAgentsAdministrationClient administrationClient = agentsClient.getPersistentAgentsAdministrationClient();
738+
ThreadsClient threadsClient = agentsClient.getThreadsClient();
739+
MessagesClient messagesClient = agentsClient.getMessagesClient();
740+
RunsClient runsClient = agentsClient.getRunsClient();
741+
742+
Supplier<String> getUserFavoriteCity = () -> "Seattle, WA";
743+
FunctionToolDefinition getUserFavoriteCityTool = new FunctionToolDefinition(
744+
new FunctionDefinition(
745+
"getUserFavoriteCity",
746+
BinaryData.fromObject(
747+
new Object()
748+
))
749+
);
750+
751+
Function<String, String> getCityNickname = location -> {
752+
return "The Emerald City";
753+
};
754+
755+
FunctionToolDefinition getCityNicknameTool = new FunctionToolDefinition(
756+
new FunctionDefinition(
757+
"getCityNickname",
758+
BinaryData.fromObject(
759+
mapOf(
760+
"type", "object",
761+
"properties", mapOf(
762+
"location",
763+
mapOf(
764+
"type", "string",
765+
"description", "The city and state, e.g. San Francisco, CA")
766+
),
767+
"required", new String[]{"location"}))
768+
).setDescription("Get the nickname of a city")
769+
);
770+
771+
Function<RequiredToolCall, ToolOutput> getResolvedToolOutput = toolCall -> {
772+
if (toolCall instanceof RequiredFunctionToolCall) {
773+
RequiredFunctionToolCall functionToolCall = (RequiredFunctionToolCall) toolCall;
774+
String functionName = functionToolCall.getFunction().getName();
775+
if (functionName.equals("getUserFavoriteCity")) {
776+
return new ToolOutput().setToolCallId(functionToolCall.getId())
777+
.setOutput(getUserFavoriteCity.get());
778+
} else if (functionName.equals("getCityNickname")) {
779+
String arguments = functionToolCall.getFunction().getArguments();
780+
try {
781+
JsonNode root = new JsonMapper().readTree(arguments);
782+
String location = String.valueOf(root.get("location").asText());
783+
return new ToolOutput().setToolCallId(functionToolCall.getId())
784+
.setOutput(getCityNickname.apply(location));
785+
} catch (JsonProcessingException e) {
786+
throw new RuntimeException(e);
787+
}
788+
}
789+
}
790+
return null;
791+
};
792+
793+
String agentName = "functions_example";
794+
CreateAgentOptions createAgentOptions = new CreateAgentOptions(modelName)
795+
.setName(agentName)
796+
.setInstructions("You are a weather bot. Use the provided functions to help answer questions. "
797+
+ "Customize your responses to the user's preferences as much as possible and use friendly "
798+
+ "nicknames for cities whenever possible.")
799+
.setTools(Arrays.asList(getUserFavoriteCityTool, getCityNicknameTool));
800+
PersistentAgent agent = administrationClient.createAgent(createAgentOptions);
801+
802+
PersistentAgentThread thread = threadsClient.createThread();
803+
ThreadMessage createdMessage = messagesClient.createMessage(
804+
thread.getId(),
805+
MessageRole.USER,
806+
"What's the nickname of my favorite city?");
807+
808+
try {
809+
//run agent
810+
CreateRunOptions createRunOptions = new CreateRunOptions(thread.getId(), agent.getId())
811+
.setAdditionalInstructions("");
812+
ThreadRun threadRun = runsClient.createRun(createRunOptions);
813+
814+
do {
815+
Thread.sleep(500);
816+
threadRun = runsClient.getRun(thread.getId(), threadRun.getId());
817+
if (threadRun.getStatus() == RunStatus.REQUIRES_ACTION
818+
&& threadRun.getRequiredAction() instanceof SubmitToolOutputsAction) {
819+
SubmitToolOutputsAction submitToolsOutputAction = (SubmitToolOutputsAction) (threadRun.getRequiredAction());
820+
ArrayList<ToolOutput> toolOutputs = new ArrayList<ToolOutput>();
821+
for (RequiredToolCall toolCall : submitToolsOutputAction.getSubmitToolOutputs().getToolCalls()) {
822+
toolOutputs.add(getResolvedToolOutput.apply(toolCall));
823+
}
824+
threadRun = runsClient.submitToolOutputsToRun(thread.getId(), threadRun.getId(), toolOutputs);
825+
}
826+
}
827+
while (
828+
threadRun.getStatus() == RunStatus.QUEUED
829+
|| threadRun.getStatus() == RunStatus.IN_PROGRESS
830+
|| threadRun.getStatus() == RunStatus.REQUIRES_ACTION);
831+
832+
if (threadRun.getStatus() == RunStatus.FAILED) {
833+
System.out.println(threadRun.getLastError().getMessage());
834+
}
835+
836+
printRunMessages(messagesClient, thread.getId());
837+
} catch (InterruptedException e) {
838+
throw new RuntimeException(e);
839+
} finally {
840+
//cleanup
841+
threadsClient.deleteThread(thread.getId());
842+
administrationClient.deleteAgent(agent.getId());
843+
}
844+
}
845+
846+
// Use "Map.of" if available
847+
@SuppressWarnings("unchecked")
848+
private static <T> Map<String, T> mapOf(Object... inputs) {
849+
Map<String, T> map = new HashMap<>();
850+
for (int i = 0; i < inputs.length; i += 2) {
851+
String key = (String) inputs[i];
852+
T value = (T) inputs[i + 1];
853+
map.put(key, value);
854+
}
855+
return map;
856+
}
857+
// A helper function to print messages from the agent
858+
public static void printRunMessages(MessagesClient messagesClient, String threadId) {
859+
860+
PagedIterable<ThreadMessage> runMessages = messagesClient.listMessages(threadId);
861+
for (ThreadMessage message : runMessages) {
862+
System.out.print(String.format("%1$s - %2$s : ", message.getCreatedAt(), message.getRole()));
863+
for (MessageContent contentItem : message.getContent()) {
864+
if (contentItem instanceof MessageTextContent) {
865+
System.out.print((((MessageTextContent) contentItem).getText().getValue()));
866+
} else if (contentItem instanceof MessageImageFileContent) {
867+
String imageFileId = (((MessageImageFileContent) contentItem).getImageFile().getFileId());
868+
System.out.print("Image from ID: " + imageFileId);
869+
}
870+
System.out.println();
871+
}
872+
}
873+
}
874+
875+
// a helper function to wait until a run has completed running
876+
public static void waitForRunCompletion(String threadId, ThreadRun threadRun, RunsClient runsClient)
877+
throws InterruptedException {
878+
879+
do {
880+
Thread.sleep(500);
881+
threadRun = runsClient.getRun(threadId, threadRun.getId());
882+
}
883+
while (
884+
threadRun.getStatus() == RunStatus.QUEUED
885+
|| threadRun.getStatus() == RunStatus.IN_PROGRESS
886+
|| threadRun.getStatus() == RunStatus.REQUIRES_ACTION);
887+
888+
if (threadRun.getStatus() == RunStatus.FAILED) {
889+
System.out.println(threadRun.getLastError().getMessage());
890+
}
891+
}
892+
private static Path getFile(String fileName) throws FileNotFoundException, URISyntaxException {
893+
URL resource = AgentExample.class.getClassLoader().getResource(fileName);
894+
if (resource == null) {
895+
throw new FileNotFoundException("File not found");
896+
}
897+
File file = new File(resource.toURI());
898+
return file.toPath();
899+
}
900+
@FunctionalInterface
901+
public interface Supplier<T> extends java.util.function.Supplier<T> {
902+
/**
903+
* Retrieves an instance of the appropriate type. The returned object may or may not be a new
904+
* instance, depending on the implementation.
905+
*
906+
* @return an instance of the appropriate type
907+
*/
908+
@Override
909+
T get();
910+
}
911+
}
912+
```
913+
::: zone-end

zone-pivots/zone-pivot-groups.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1355,6 +1355,8 @@ groups:
13551355
pivots:
13561356
- id: csharp
13571357
title: C#
1358+
- id: java
1359+
title: Java
13581360
- id: python
13591361
title: Python
13601362
- id: typescript

0 commit comments

Comments
 (0)